Java电话号码格式API
我有一个数以百万计的电话号码与免费的格式的数据库。 也就是说,用户界面不强制执行任何约束,用户可以随心所欲地input内容。
我正在寻找的是一个Java API,可以尽最大努力将这些转换成一致的格式。 理想情况下,API将采取自由文本值和国家代码,并产生有效的国际电话号码或抛出exception。
例如,系统中的电话号码可能看起来像以下任何一种:
(555) 478-1123 555-478-1123 555.478.1123 5554781123
鉴于美国的国家,API将产生所有这些价值“+1(555)478-1123”。 确切的格式不重要,只要它是一致的。
系统中还有没有区号的号码,如“478-1123”。 在这种情况下,我会期待一个NoAreaCodeException或类似的东西。
也可能有数据如“abc”,这也应该引发exception。
当然,我发布的例子有无数的变化,以及国际电话号码的巨大复杂性,这些复杂的validation规则相当复杂。 这就是为什么我不考虑自己动手。
有没有人看过这样的API?
你可以写自己的(美国电话#格式):
- 从string中去除任何非数字字符
- 检查剩余的string是十个字符长
- 在前三个字符周围放置括号,在第六个字符和第七个字符之间划一个短划线。
- 在string上加上“+1”
更新:
谷歌最近发布了libphonenumberparsing,格式化,存储和validation国际电话号码。
你可以试试这个Java电话号码格式化库http://code.google.com/p/libphonenumber/
它有数百个国家和格式的数据。
简单的正则expression式分析器
/** * @param pPhoneNumber * @return true if the phone number is correct */ private boolean isPhoneNumberCorrect(String pPhoneNumber) { Pattern pattern = Pattern .compile("((\\+[1-9]{3,4}|0[1-9]{4}|00[1-9]{3})\\-?)?\\d{8,20}"); Matcher matcher = pattern.matcher(pPhoneNumber); if (matcher.matches()) return true; return false; }
格式
我根据我的需要做了这个,它接受数字:
- COUNTRYCODE-数
- 数
国家代码:
他们可能有一个: +
,或者一个或两个零。 然后,可能会跟着一个-
。
接受:
-
+456
-
00456
-
+1234
-
01234
以上所有可能或不可以跟随-
拒绝:
-
0456
- 它应该是:
-
00456
或+456
或04444
-
- 它应该是:
数
一个简单的8-20位数字。
接受:
-
00456-12345678
-
+457-12345678
-
+45712345678
-
0045712345678
-
99999999
扩展它?
随意,所以你可以包括支持.
或'('分隔符。只要确保你转义他们,例如(
使用\(
。
我不知道这样的API,但它看起来可以通过使用正则expression式来完成。 也许你不能将所有的数字转换成有效的格式,但大多数。
http://code.google.com/p/libphonenumber/的最新版本为许多新国家添加了元数据,并为之前列出的一些国家添加了更多的细节。;
当前的源代码版本是r74,而.jar文件是2.6版本。 之前的.jar文件是针对Java 1.6编译的,但是从libphonenumber版本2.5.1开始,现在它们已经针对Java 1.5及更高版本进行了编译。
不要忘了还有一个JavaScript代码的直接端口。 它可以在http://code.google.com/p/libphonenumber/source/browse/#svn%2Ftrunk%2Fjavascript的源代码树中find
错误报告是受欢迎的。 元数据的更新被积极鼓励,因为许多国家官方公布的地区代码清单也不完整或过时。
不要重新发明轮子; 使用一个API,例如http://libphonenumber.googlecode.com/这个API也给你很好的格式。; 例如 :
String number = "(555) 478-1123"; PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance(); try { Phonenumber.PhoneNumber phoneNumber = phoneNumberUtil.parse(number, Locale.US.getCountry()); } catch (NumberParseException e) { // error handling }
你甚至可以使用phoneNumber对象来很好地格式化一个有效的电话号码,然后将其保存到数据库或任何其他。
对于看起来像“01 44 55 66 77”的法文数字,我们可以使用下面的逻辑。
DecimalFormatSymbols dfs = new DecimalFormatSymbols(); dfs.setGroupingSeparator(' '); // sometimes '.' is used DecimalFormat decfmt = new DecimalFormat("0,0", dfs); // enable grouping decfmt.setMinimumIntegerDigits(10); // we always have 10 digits decfmt.setGroupingSize(2); // necessary in order to group digits by 2 orders System.out.println(decfmt.format(144556677)); // outputs "01 44 55 66 77"
一旦完成这个工作,使用谷歌的电话号码API,其他人提到,我们可以轻松地parsing这些序列,并将它们重新格式化为其他forms,如“+33 1 44 55 66 77”,如下所示:
Iterable<PhoneNumberMatch> numbers = PhoneNumberUtil.getInstance().findNumbers(textWithPhoneNums, "FR"); for(Iterator<PhoneNumberMatch> iterator = numbers.iterator(); iterator.hasNext(); ){ PhoneNumberMatch pnm = iterator.next(); PhoneNumber number = pnm.number(); System.out.println(PhoneNumberUtil.getInstance().formatOutOfCountryCallingNumber(number, null)); }
除非你的号码全部来自一个国家(大概是美国),否则我不认为有一种方法可以确认缺less地区代码,因为每个国家都有自己的地区代码规则。
我会在这里开始寻找详细的信息, 在这里和这里 – 如果有API来处理它(用Java或其他),它们也可能被链接到那里。
有一些商业节目可以格式化和validation国际电话号码,就像在某些国家甚至检查有效的区号一样。 对于北美, NANPA提供一些validation区号的资源 。
我发现最好的是javax.telephony
,可以在这里find: http : //java.sun.com/products/javaphone/
它有一个地址类,但遗憾的是,这个类没有解决你的问题:(好吧,也许你可以通过深入挖掘find解决scheme。
除此之外,我的第一个想法是使用正则expression式。 但是,这似乎是对这个具体问题的一种不好的解决办法。
我自己的需求非常简单。 我只需要一个7位或10位的数字,并在区号,交换号码和交换号码之间加上分隔符(短划线,句号,一些string等等)。 任何传递给方法的值不是全部数字或不是7或10的长度。 空值返回空string,分隔符的空值被视为空string。 我的代码:
import java.util.regex.Matcher; import java.util.regex.Pattern; // ... private String formatPhoneNumber(String phnumber, String separator) { phnumber = (phnumber == null) ? "" : phnumber; if ((phnumber.length() != 7) && (phnumber.length() != 10)) { return phnumber; } // If we get here, 'phnumber' is for sure either 7 or 10 chars long separator = (separator == null) ? "" : separator; Pattern p = Pattern.compile("([0-9]*)"); Matcher m = p.matcher(phnumber); if (m.matches()) { if (phnumber.length() == 7) { return phnumber.substring(0, 3) + separator + phnumber.substring(4); } else { return phnumber.substring(0, 3) + separator + phnumber.substring(3, 6) + separator + phnumber.substring(6); } // If we get here, it means 1 or more of the chars in 'phnumber' // is not a digit and so 'phnumber' is returned just as passed in. return phnumber; }