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

时间:2018-09-26 14:23:47

标签: java libphonenumber

我从一个很棒的图书馆那里听到了很多好处,但是我发现自己处境艰难。

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

我已经阅读了一些有关 E.164 格式的信息,并且确实打算将使用该格式的所有电话号码存储在数据库中。

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

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

由于我无法访问该信息,因此我尝试使用PhoneNumberUtil#parse()方法而不提供国家/地区代码。

看看下面的例子:

System.out.printLn("Number -> " + phoneNumberUtil.parse("00336555233634", null).toString())
  

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

在我的示例中,该号码是法国手机的号码。我相信,如果您从法国境外拨打电话,两个开头的0可以使用。

但是该库无法理解它,因为它正在延迟国家代码。 这是否意味着没有办法了解特定电话号码的来源?

文档似乎对此很清楚:

public PhoneNumber parse(CharSequence numberToParse, String defaultRegion)
  

@param defaultRegion区域,我们期望该数字为   从。仅当*解析的数字不是   以国际格式编写。 *
的country_code   在这种情况下,编号将存储为默认区域的编号   提供。如果数字*保证以'+'开头   随后是国家/地区代码,然后是RegionCode.ZZ *或   可以提供null。

因此,如果添加+33

System.out.printLn("Number -> " + phoneNumberUtil.parse("+336555233634", null).toString())

然后自然得出的结果是:

  

号码->国家/地区代码:33国家/地区号码:336555233634

如果最终用户向我的应用提供的电话号码不是以+开头,该怎么办?如果发生这种情况,我不敢相信自己是唯一的人。

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

您只需要使用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);
        }
    }

和测试用例如下。

// 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);
    }
}

答案 1 :(得分:0)

将原始电话号码存储在RAW_PHONE的不可操作列中,并将标准的E.164标准化号码存储在PHONE列中("00" -> "+""(" -> ""等)。这样,您就可以准备检查清单和手动更正,并改善转换。

可以想象,表中有两个电话栏,而另一个分机号-203作为第二个值。

如果根据国家/地区代码进行的转换失败或存在其他疑问,最好不要填写严格的字段。是默认的法国,还是用户居住在比利时时的默认值? 有人可能会说用户注册的来源(位置)决定了默认的国家/地区代码。