API формата номера телефона Java
У меня есть база данных с миллионами телефонных номеров со свободным для всех форматированием. Т.е. пользовательский интерфейс не применяет никаких ограничений и пользователи набирают все, что захотят.
Я ищу Java API, который может приложить все усилия, чтобы преобразовать их в согласованный формат. В идеале API будет использовать значение свободного текста и код страны и выдавать действительный международный номер телефона или выдавать исключение.
Например, номер телефона в системе может выглядеть следующим образом:
(555) 478-1123
555-478-1123
555.478.1123
5554781123
Учитывая страну США, API будет производить значение "+1 (555) 478-1123" для всех этих. Точный формат не имеет значения, если он согласован.
В системе также есть номера без кодов областей, таких как "478-1123". В этом случае я ожидал бы исключение NoAreaCodeException или что-то подобное.
Также могут быть такие данные, как "abc", которые также должны генерировать исключения.
Конечно, есть множество вариаций приведенных мной примеров, а также огромное количество международных телефонных номеров, которые имеют довольно сложные правила валидации. Вот почему я бы не стал отказываться от своих собственных.
Кто-нибудь видел такой API?
Ответы
Ответ 1
Вы можете написать свой собственный (для формата телефона США #):
- Сбросьте любые нечисловые символы из строки
- Убедитесь, что оставшаяся строка содержит десять символов
- Поместите круглые скобки вокруг первых трех символов и тире между шестым и седьмым символами.
- Подготовьте "+1" к строке
<ч/" >
Обновление:
Недавно Google опубликовал libphonenumber для разбора, форматирования, хранения и проверки международных телефонных номеров.
Ответ 2
Вы можете попробовать эту библиотеку форматирования номера Java http://code.google.com/p/libphonenumber/
Он содержит данные для сотен стран и форматов.
Ответ 3
Простой парсер регулярных выражений
/**
* @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-Number
- Количество
Коды стран:
Они могут иметь: +
или один или два нули.
Тогда за ним может следовать a -
.
Принимает:
Все вышеизложенное может или не может сопровождаться a -
Отклонение:
Число
Простое число с 8-20 цифрами.
Принимает:
-
00456-12345678
-
+457-12345678
-
+45712345678
-
0045712345678
-
99999999
Расширить его?
Не стесняйтесь, поэтому вы можете включить поддержку .
или '(' separators. Просто убедитесь, что вы их избегаете, например, для (
используйте \(
.
Ответ 4
Я не знаю такого API, но, похоже, это можно сделать с помощью регулярных выражений. Вероятно, вы не можете преобразовать все числа в допустимый формат, но большинство из них.
Ответ 5
Последние версии 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
Отчеты об ошибках приветствуются. Активно поощряется обновление метаданных, поскольку даже официальные опубликованные в правительственных списках списки кодов для многих стран являются либо неполными, либо устаревшими.
Ответ 6
Не изобретайте колесо повторно; использовать 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, чтобы красиво отформатировать его действительным номером телефона, прежде чем сохранять его в БД или что-то еще.
Ответ 7
Для французского номера, который выглядит как "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-интерфейсом телефона google, упомянутым выше, мы можем легко проанализировать эти последовательности и переформатировать их в другие формы, такие как "+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));
}
Ответ 8
Существуют коммерческие программы, которые форматируют и подтверждают международные телефонные номера, например этот, который даже проверяет действительные коды областей в некоторых странах. Для Северной Америки NANPA предоставляет некоторые ресурсы для проверки кода зоны.
Ответ 9
Я не думаю, что есть способ признать отсутствие регионального кода, если только ваши номера не указаны из одной страны (предположительно, США), поскольку каждая страна имеет свои правила для таких вещей, как коды областей.
Я бы начал искать подробную информацию здесь, здесь и здесь - если есть API-интерфейсы для его обработки (на Java или иначе), они также могут быть связаны с ними.
Ответ 10
Лучшее, что я нашел, было javax.telephony
, которое можно найти здесь: http://java.sun.com/products/javaphone/
У него класс адресов, но, к сожалению, этот класс не решил вашу проблему:(
Ну, может быть, вы сможете найти решение, углубляясь в него.
Кроме того, моя первая идея заключалась в том, чтобы использовать регулярное выражение. Однако это кажется своего рода плохим решением этой конкретной проблемы.
Ответ 11
Мои собственные потребности были очень простыми. Мне просто нужно было сделать 7 или 10-значный номер и поместить разделители (тире, период, несколько строк символов и т.д.) Между кодом города, обменом и номером обмена. Любое значение, переданное в метод, который не является числом или не является длиной 7 или 10, просто возвращается. Нулевое значение возвращает пустую строку, а нулевое значение для разделителя рассматривается как пустая строка. Мой код:
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;
}