什么是最好的方式转换电话号码进入国际格式,(E.164)使用Java?
-
06-07-2019 - |
题
什么是最好的方式转换电话号码进入国际格式,(E.164)使用Java?
给个电话号码和一个国家身份证(让我们说的ISO国家代码),我谨将其转换成国际标准E.164格式的电话号码。
我确信,我可以做手很容易-但我不会以确保它能正常工作在所有情况。
这Java框架/library/utility你会建议完成这个吗?
P.S.'电话数量'可能是任何东西可识别的一般公众--比如
* (510) 786-0404
* 1-800-GOT-MILK
* +44-(0)800-7310658
这最后一个是我最喜欢的-这是怎么一些人写他们的人数在英国和意味着你应该使用+44或者你应该使用的0.
E.164格式编号应该是所有数值,并利用充分的国际国家代码(例如+44)
解决方案
Google提供了一个用于处理电话号码的库。他们用于Android的同一个
http://code.google.com/p/libphonenumber/
String swissNumberStr = "044 668 18 00"
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
try {
PhoneNumber swissNumberProto = phoneUtil.parse(swissNumberStr, "CH");
} catch (NumberParseException e) {
System.err.println("NumberParseException was thrown: " + e.toString());
}
// Produces "+41 44 668 18 00"
System.out.println(phoneUtil.format(swissNumberProto, PhoneNumberFormat.INTERNATIONAL));
// Produces "044 668 18 00"
System.out.println(phoneUtil.format(swissNumberProto, PhoneNumberFormat.NATIONAL));
// Produces "+41446681800"
System.out.println(phoneUtil.format(swissNumberProto, PhoneNumberFormat.E164));
其他提示
经验之谈在编写这种事情,这真的很难做到100%的可靠性。我已经写了一些Java的代码这样做,是合理的良好在处理的数据,我们有,但不是适用于每一个国家。问题你要问的是:
是符号映射一致的国家之间?美国使用了很多这种(如1800-有-牛奶),但在澳大利亚,作为一个实例,其相当罕见的。什么你需要做的是确保你们在做正确的映射的国家的问题,如果它变化(可能)。我不知道什么样的国家使用不同的字母(例如Cyrilic在俄罗斯和前东欧国家)这样做;
你必须接受你的解决方案不会将100%,你不应该期待它。你需要采取一种"最好的猜测"的做法。例如,世界上没有真正的办法知道这132345是一个有效的电话号码在澳大利亚,作为1300 123 456,但是,这是仅有的两个模式为13xx数和他们不可调用从海外;
你还要问,如果你想要验证的区域(区域代码)。我相信我们采用一个系统,其中第二位数字的区域代码是1或0.这可能曾经被的情况下但我不确定如果它仍然适用。无论是哪种情况,许多其他国家将会有其他的规则。在澳大利亚,有效的区域代码,用于固定电话和移动(cell)电话是两位数字(第一是0)。08、03和04都是有效的。01不是。你怎么应付呢?你想要吗?
国家使用不同的公约,无论多么多的数字,他们写作。你必须决定如果要接受其他的东西比的"规范"。这些都是常见的,在澳大利亚:
- (02) 1234 5678
- 02 1234 5678
- 0411 123 123(但是我从来没有见过04 1112 3456)
- 131 123
- 13 1123
- 131 123
- 1 300 123 123
- 1300 123 123
- 02-1234-5678
- 1300-234-234
- +44 78 1234 1234
- +44 (0)78 1234 1234
- +44-78-1234-1234
- +44-(0)78-1234-1234
- 0011 44 78 1234 1234(0011是标准的国际拨号编码)
- (44)078 1234 1234(不常见)
和那只是掉我的头顶。对于一个国家。在法国,例如,其共同的写的电话号码在数量对(12 34 56 78),他们宣布这样的说法:代替:
联合国(一),deux(两个),trois(三),...
它的
兹(十二),trente-quatre(三十四),...
你想要满足这一水平的文化差异?我会假设不但问题是值得考虑的只是以防万一你让你的规则过于严格。
还有些人可能追加的分机号码在电话号码,可能与"外部"或类似的缩写。你想到满足呢?
对不起,没有代码在这里。只是一个列表中的问题要问问你自己,并要考虑的问题。正如其他人所说的那样,一系列定期的表情可以做很多以上,但最终的电话号码领域是(大部分)的自由形式的文本在这一天结束。
这是我的解决方案:
public static String FixPhoneNumber(Context ctx, String rawNumber)
{
String fixedNumber = "";
// get current location iso code
TelephonyManager telMgr = (TelephonyManager) ctx.getSystemService(Context.TELEPHONY_SERVICE);
String curLocale = telMgr.getNetworkCountryIso().toUpperCase();
PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
Phonenumber.PhoneNumber phoneNumberProto;
// gets the international dialling code for our current location
String curDCode = String.format("%d", phoneUtil.getCountryCodeForRegion(curLocale));
String ourDCode = "";
if(rawNumber.indexOf("+") == 0)
{
int bIndex = rawNumber.indexOf("(");
int hIndex = rawNumber.indexOf("-");
int eIndex = rawNumber.indexOf(" ");
if(bIndex != -1)
{
ourDCode = rawNumber.substring(1, bIndex);
}
else if(hIndex != -1)
{
ourDCode = rawNumber.substring(1, hIndex);
}
else if(eIndex != -1)
{
ourDCode = rawNumber.substring(1, eIndex);
}
else
{
ourDCode = curDCode;
}
}
else
{
ourDCode = curDCode;
}
try
{
phoneNumberProto = phoneUtil.parse(rawNumber, curLocale);
}
catch (NumberParseException e)
{
return rawNumber;
}
if(curDCode.compareTo(ourDCode) == 0)
fixedNumber = phoneUtil.format(phoneNumberProto, PhoneNumberFormat.NATIONAL);
else
fixedNumber = phoneUtil.format(phoneNumberProto, PhoneNumberFormat.INTERNATIONAL);
return fixedNumber.replace(" ", "");
}
我希望这可以帮助有同样问题的人。
享受并自由使用。
感谢您的回答。正如原始问题中所述,我更感兴趣的是将数字格式化为标准格式,而不是确定它是否是有效(如真实的)电话号码。
我目前有一些手工编写的代码,其中包含电话号码字符串(由用户输入)和源国家/地区背景和目标国家/地区背景(拨打该号码的国家/地区以及该号码所在的国家/地区)正在拨打 - 这是系统已知的,然后按步骤进行以下转换
-
从数字
中删除所有空格
-
将所有字母转换为数字 - 使用字母到数字的查找表(例如A - > 2,B - > 2,C - > 2,D - > 3)键盘等(我不知道有些键盘以不同方式分发)
-
删除所有标点符号 - 保留前面的“+”(如果存在)(如果该数字已经是某种国际格式)。
-
确定该号码是否具有国家/地区背景的国际拨号前缀 - 例如如果源上下文是英国,我会看它是否以'00'开头 - 并用'+'替换它。我目前不检查'00'后面的数字是否跟随目标国家/地区的国际拨号代码。我在查找表中查找源国家/地区的国际拨号前缀(例如GB - > '00',US - >'011'等)
-
确定该号码是否具有国家/地区背景的本地拨号前缀 - 例如如果源上下文是英国,我会查看它是否以“0”开头 - 并将其替换为“+”后跟目标国家/地区的国际拨号代码。我在查找表中查找源国家/地区的本地拨号前缀(例如GB - >'0',US - >'1'等),以及另一个查找中目标国家/地区的国际拨号代码表(例如'GB'= '44',US ='1')
醇>
到目前为止,它似乎对我所抛出的所有东西都有效 - 除了+44(0)1234-567-890情况 - 我会为那个添加一个特殊的案例检查。
写它并不难 - 我可以为我遇到的每个奇怪的例外添加特殊情况。但我真的想知道是否有标准的解决方案。
电话公司似乎每天都在处理这件事。使用PSTN拨号时,我从未得到不一致的结果。例如,在美国(移动电话具有与固定电话相同的区号,我可以拨打+ 1-123-456-7890,或011-1-123-456-7890(其中011是国际拨号前缀) US和1是美国的国际拨号代码,1-123-456-7890(其中1是美国的本地拨号前缀),甚至是456-7890(假设我当时在123区号中)并且每次都得到相同的结果。我假设在内部这些拨打的号码被转换为相同的E.164标准格式,并且转换都是在软件中完成的。
说实话,听起来你已经掌握了大部分基础。
英国有时(错误地)使用的+44(0)800格式令人烦恼,并且根据E.123不是严格有效的,这是ITU-T关于如何显示数字的建议。如果您还没有获得E.123的副本,那么值得一看。
对于它的价值,电话网络本身并不总是使用E.164。通常在PBX(或者如果你在蒸汽电话上的网络中)生成的ISDN信令中会有一个标志,告知网络拨打的号码是本地的,国内的还是国际的。
这是一项非常艰巨的任务,因为每个国家/地区的电话号码编写方式都不同。
我们曾经保留一份REGEXP列表(我们支持19种格式)来解析数字的3个部分,然后将这3部分转换为“+ {1} {2} {3}”。
首先按照更具体的方式对regexp进行排序,然后选择成功解析的第一个。
在某些国家/地区,您可以将112验证为有效的电话号码,但如果您在其前面粘贴国家/地区代码,则无法再使用该号码。在其他国家/地区,您无法验证112,但您可以将911验证为有效的电话号码。
我见过一些手机将Q放在7键上,Z放在9键上。我见过一些把Q和Z放在0键上的手机,还有一些把Q和Z放在1键上。
昨天存在的区号可能今天不存在,反之亦然。
在北美的一半(国家代码1)中,区域代码的第二位数规则曾经是0或1,但该规则在10年前消失了。
我不知道可以将电话号码格式化为E.164的标准库或框架。
用于我们产品的解决方案,需要将PBX提供的调用者ID格式化为E.164,是为所有适用的国家/地区部署包含E.164格式信息的文件(数据库表)。 这样做的好处是可以更新应用程序(处理各种PSTN网络中的所有奇怪的角落情况),而无需更改生产代码库。
该表包含每个国家/地区代码的行以及有关区号长度和用户长度的信息。一个国家/地区可能有多个条目,具体取决于区号和用户号码长度的可能变化。
使用新西兰PSTN(部分)拨号计划作为表格的示例..
CC AREA_CODE AREA_CODE_LENGTH SUBSCRIBER SUBSCRIBER_LENGTH
64 1 7
64 21 2 7
64 275 3 6
我们执行类似于您所描述的操作,即剥离所提供的任何非数字字符的电话号码,然后根据有关总体数量计划长度,外部访问代码和长途/国际访问代码的各种规则进行格式化。