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

2022-09-03 07:58:26

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

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

我已经阅读了一些关于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默认区域,我们希望该数字来自该区域。仅当 * 正在解析的数字未以国际格式写入时,才使用此选项。在这种情况下,*
数字的country_code将存储为提供的默认区域的country_code。如果数字 * 保证以“+”开头,后跟国家/地区调用代码,则可以提供 RegionCode.ZZ * 或 null。

因此,如果添加+33

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

那么自然的结果是:

数字 -> 国家代码: 33 全国 数字: 336555233634

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

感谢您的帮助!


答案 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);
    }
}

答案 2

将原始电话号码存储在非操作列RAW_PHONE中,将规范的 E.164 标准化号码存储在“电话”列中(等)。这样,您就可以为检查清单和手动更正做好准备,并提高转换率。"00" -> "+""(" -> ""

可以想象的是,表中有两个电话列,而作为第二个值只是另一个扩展名。-203

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


推荐