libphonenumber - 在不知道国家代码的情况下格式化电话号码

Mac*_*ich 11 java libphonenumber

我从看起来很棒的图书馆听到了很多好消息,但我发现自己处于一种微妙的境地。

这是我工作过的第一个项目,我应该将电话号码存储在数据库中。

我已经阅读了一些关于E.164格式的内容,我确实打算将所有使用这种格式的电话号码存储在我的数据库中。

我面临的问题是数据源。我无法控制数据源。我所知道的是,我收到了一堆电话号码,而且它们的格式不一致。有些有国际分机,有些没有。有些有括号、连字符、前导 0 等,有些没有。

我怎么可能从所述来源中提取电话号码,将它们格式化为 E.164,以便我可以安全地存储它们?

我尝试在PhoneNumberUtil#parse()不提供国家代码的情况下使用该方法,因为我无法访问该信息。

看看下面的例子:

System.out.printLn("Number -> " + phoneNumberUtil.parse("00336555233634", null).toString())
Run Code Online (Sandbox Code Playgroud)

错误类型:INVALID_COUNTRY_CODE。缺少或无效的默认区域。

在我的例子中,号码是法国手机的号码。0我相信,如果您从法国以外的地方拨打电话,则这两个启动项都有效。

但是图书馆无法理解它,因为它正在吸收国家/地区代码。 这是否意味着不存在了解该特定电话号码来自何处的方法?

文档似乎很清楚:

public PhoneNumber parse(CharSequence numberToParse, String defaultRegion)
Run Code Online (Sandbox Code Playgroud)

@param defaultRegion 我们期望数字来自的区域。仅当 * 解析的数字不是以国际格式写入时才使用。
在这种情况下,*编号的国家/地区代码将作为提供的默认区域的国家/地区代码存储。如果数字 * 保证以“+”开头,后跟国家/地区调用代码,则可以提供 RegionCode.ZZ * 或 null。

所以,如果添加 +33

System.out.printLn("Number -> " + phoneNumberUtil.parse("+336555233634", null).toString())
Run Code Online (Sandbox Code Playgroud)

那么结果自然是:

号码 -> 国家代码:33 国家号码:336555233634

如果最终用户向我的应用提供不以 开头的电话号码,我应该/可以做什么+?如果出现这种情况,我无法相信我是唯一的人。

谢谢您的帮助 !

Vin*_*bin 3

您只需使用 E164Format。这里我以挪威为例

我有一个测试用例,可以测试并以一种格式给出电话号码。

public static String getE164FormattedMobileNumber(String mobile, String locale)
            throws PhoneNumberFormatException {
        try {
            PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
            PhoneNumber phoneProto = phoneUtil.parse(mobile, locale);
            if (phoneUtil.isValidNumber(phoneProto)
                    && phoneUtil.isPossibleNumberForType(phoneProto, PhoneNumberType.MOBILE)) {
                return phoneUtil.format(phoneProto, PhoneNumberFormat.E164);
            }
            throw new PhoneNumberFormatException(
                    "Mobile number is invalid with the provided locale");
        } catch (NumberParseException e) {
            throw new PhoneNumberFormatException("Error in parsing mobile number", e);
        }
    }
Run Code Online (Sandbox Code Playgroud)

和测试用例如下。

// this is the test mobile used
    private String expectedMobileNumber = "+4746205615";
private List<String> sucessMobileNumbers;

private List<String> failMobileNumbers;

public PhoneNumberE164FormatTest() {
    sucessMobileNumbers =
            Arrays.asList(
                    "46205615",
                    "004746205615",
                    "+4746205615",
                    "4746205615",
                    "46205615",
                    "+47 46205615",
                    "462 05 615");
    failMobileNumbers = Arrays.asList("abcdsds3434", "abcdsds343?#4", "21448410", "9946739087");
}

@Test
public void e164FormattedMobileNumbersSucessCase() throws PhoneNumberFormatException {

    for (String mobileNumber : sucessMobileNumbers) {
        Assert.assertEquals(
                expectedMobileNumber,
                (PhoneNumberUtils.getE164FormattedMobileNumber(mobileNumber, NO)));
    }
}

@Test(expected = PhoneNumberFormatException.class)
public void e164FormattedMobileNumbersFailCase() throws PhoneNumberFormatException {
    for (String mobileNumber : failMobileNumbers) {
        PhoneNumberUtils.getE164FormattedMobileNumber(mobileNumber, NO);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢您的详细解答,我真的很感激。总而言之,我理解你的例子,但这里有一个关键点是我真正的问题所在:**国家/地区代码**。在您的示例中,是挪威。但就我而言,它可以是**任何东西**!这真是令人不安。我有我的手机(目前作为我的数据源),我查看我的联系人列表。其中一些是我知道的法国号码,但没有法国的国际代码“+33”。我该如何将这些数字格式化为 **E164** ?我的意思是我的短信应用程序似乎正确......当我发送/接收短信时 (6认同)
  • 这根本没有回答这个问题。如果您提取联系人列表以在数据库中进行比较,您无法询问系统该号码位于哪个国家/地区,因为您无权访问该号码所指的每个人的电话。 (4认同)