Каков наилучший способ преобразования телефонных номеров в международный формат (E. 164) с использованием Java?

#java #validation #formatting #phone-number

Вопрос:

Каков наилучший способ преобразования телефонных номеров в международный формат (E. 164) с использованием Java?

Учитывая «номер телефона» и идентификатор страны (скажем, код страны ISO), я хотел бы преобразовать его в стандартный телефонный номер международного формата E. 164.

Я уверен, что могу сделать это вручную довольно легко, но я не был бы уверен, что это будет работать правильно во всех ситуациях.

Какую платформу/библиотеку/утилиту Java вы бы порекомендовали для этого?

P.S. «Номер телефона» может быть любым, что может быть идентифицировано широкой публикой, например

 * (510) 786-0404
* 1-800-GOT-MILK
*  44-(0)800-7310658
 

последнее мое любимое — это то, как некоторые люди пишут свой номер в Великобритании, и это означает, что вы должны либо использовать 44, либо использовать 0.

Номер формата E. 164 должен быть полностью цифровым и использовать полный международный код страны (например, 44).

Комментарии:

1. проверьте этот сайт: droidprism.blogspot.com/2013/06/…

Ответ №1:

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

Комментарии:

1. Спасибо. Это выглядит очень многообещающе. Я попробую это сделать

2. Библиотека выглядит неплохо. Единственное, что мешает мне использовать его в веб-приложении, — это размер файла JavaScript: — (

3. Новый URL-адрес с открытым исходным кодом.google/проекты/libphonenumber

4. Есть ли способ преобразовать обычный цифровой текст в 1-647-288-4782 с помощью библиотеки? После кода страны стоит дефис. Спасибо.

Ответ №2:

Исходя из опыта написания подобных вещей, это действительно трудно сделать со 100% надежностью. Для этого я написал некоторый Java-код, который достаточно хорош для обработки имеющихся у нас данных, но не будет применим в каждой стране. Вопросы, которые вам нужно задать, следующие:

Согласуются ли сопоставления символов и чисел между странами? В США используется много этого (например, МОЛОКО 1800 г), но в Австралии, как один из примеров, это довольно редко. Что вам нужно было бы сделать, так это убедиться, что вы выполняете правильное сопоставление для рассматриваемой страны, если она меняется (это может быть не так). Я не знаю, в каких странах используются разные алфавиты (например, кириллица в России и странах бывшего Восточного блока) ;

Вы должны признать, что ваше решение не будет 100% — ным, и вы не должны ожидать, что оно будет таким. Вам нужно использовать подход «наилучшего предположения». Например, нет реального способа узнать, что 132345 является действительным телефонным номером в Австралии, как и 1300 123 456, но это единственные два шаблона, которые предназначены для номеров 13xx, и они недоступны для звонков из-за рубежа;

Вы также должны спросить, хотите ли вы проверить регионы (коды районов). Я полагаю, что в США используется система, в которой вторая цифра кода города равна 1 или 0. Возможно, когда-то так и было, но я не уверен, что это все еще применимо. В любом случае, во многих других странах будут другие правила. В Австралии действительными кодами районов для стационарных и мобильных (сотовых) телефонов являются две цифры (первая-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), и они тоже произносят его так: вместо:

оон (один), двойка (две), тройка (три), …

его

доуз (двенадцать), трент-кватр (тридцать четыре), …

Вы хотите удовлетворить этот уровень культурных различий? Я бы предположил, что нет, но этот вопрос стоит рассмотреть на тот случай, если вы сделаете свои правила слишком строгими.

Кроме того, некоторые люди могут добавлять добавочные номера к телефонным номерам, возможно, с «ext» или аналогичной аббревиатурой. Вы хотите удовлетворить это?

Извините, здесь нет кода. Просто список вопросов, которые нужно задать себе, и вопросов, которые нужно рассмотреть. Как уже говорили другие, ряд регулярных выражений может сделать многое из вышеперечисленного, но в конечном счете поля номера телефона (в основном) представляют собой текст в свободной форме в конце дня.

Комментарии:

1. Сопоставления символов с цифрами согласованы в каждой стране, где они широко используются (или, что то же самое: в странах, где нет согласованного сопоставления, телефонные номера не будут представлены в виде букв). Поскольку код страны доступен, вы также можете определить, какое сопоставление необходимо.

2. Отличный пост. Кстати, мы, мексиканцы, также группируем (и произносим) телефонные номера попарно. По крайней мере, для меня легче запомнить всего 4 отдельных номера, а не 8 (я, как правило, страдаю от английских телефонных номеров).

3. Если вы сделаете свой форматер tel. no. расширенным из java.text.Format, вы сможете корректно работать с языковым стандартом.

Ответ №3:

Это было мое решение:

 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(" ", "");
}
 

Я надеюсь, что это поможет кому-то с той же проблемой.

Наслаждайтесь и свободно пользуйтесь.

Ответ №4:

Спасибо за ответы. Как указано в исходном вопросе, меня гораздо больше интересует форматирование номера в стандартный формат, чем определение того, является ли это действительным (как в случае с подлинным) номером телефона.

В настоящее время у меня есть код ручной работы, который принимает строку номера телефона (введенную пользователем), контекст исходной страны и контекст целевой страны (страна, из которой набирается номер, и страна, в которую набирается номер — это известно системе), а затем выполняет следующее преобразование в несколько шагов

  1. Удалите все пробелы из числа
  2. Переведите все буквы алфавита в цифры — используя таблицу подстановки букв в цифры (например, A->2, B->>2, C->>>2, D->>>>3) и т. Д. для клавиатуры (я не знал, что некоторые клавиатуры распределяют их по-разному)
  3. Удалите все знаки препинания, сохранив предыдущее » » нетронутым, если оно существует (в случае, если номер уже находится в каком — то международном формате).
  4. Определите, имеет ли номер международный префикс набора для контекста страны — например, если исходный контекст — Великобритания, я бы посмотрел, начинается ли он с » 00 «- и замените его на» «. В настоящее время я не проверяю, следует ли за цифрами, следующими за «00», международный телефонный код целевой страны. Я ищу международный префикс набора номера для страны-источника в таблице поиска (например, ГБ—> «00», США—>> » 011 » и т. Д.)
  5. Определите, имеет ли номер префикс местного набора для контекста страны — например, если исходным контекстом является Великобритания, я бы посмотрел, начинается ли он с » 0 «- и замените его на» «, за которым следует международный код набора для целевой страны. Я ищу префикс местного набора для страны-источника в таблице поиска (например, ГБ—> «0», США—>> » 1 «и т. Д.), А международный код набора для целевой страны в другой таблице поиска (например, «ГБ»=»44″, США=»1»)

Похоже, это работает для всего, что я бросил на это до сих пор — за исключением ситуации 44(0)1234-567-890 — я добавлю для этого специальную проверку.

Написать это было нетрудно — и я могу добавлять особые случаи для каждого странного исключения, с которым я сталкиваюсь. Но я действительно хотел бы знать, существует ли стандартное решение.

Телефонные компании, похоже, сталкиваются с этим каждый день. Я никогда не получаю противоречивых результатов при наборе номеров с помощью ТСОП. Например, в США (где мобильные телефоны имеют те же коды районов, что и стационарные телефоны, я мог бы набрать 1-123-456-7890 или 011-1-123-456-7890 (где 011-префикс международного набора в США, а 1-международный код набора для США), 1-123-456-7890 (где 1-префикс местного набора в США) или даже 456-7890 (при условии, что в то время я был в коде 123) и каждый раз получать одни и те же результаты. Я предполагаю, что внутренне эти набранные номера преобразуются в один и тот же стандартный формат E. 164, и что все преобразование выполняется программным обеспечением.

Комментарии:

1. В шаге 5 есть потенциальный недостаток. Возможно, где-то в мире существуют телефонные номера, где код города может начинаться с той же цифры, что и префикс национального набора (NB, я не знаю, есть ли, но я не знаю, что их тоже нет), и поэтому вы не знаете, удаляете ли вы префикс или удаляете часть кода города. (это не проблема с номерами в Великобритании или США)

Ответ №5:

Честно говоря, похоже, что вы уже охватили большую часть баз.

Формат 44(0)800, иногда (неправильно) используемый в Великобритании, раздражает и не является строго допустимым в соответствии с E. 123, который является рекомендацией МСЭ-Т о том, как должны отображаться номера. Если у вас нет копии Е. 123, стоит взглянуть.

Как бы то ни было, сама телефонная сеть не всегда использует E. 164. Часто в сигнале ISDN, генерируемом АТС (или в сети, если вы используете телефон steam), будет отображаться флаг, который сообщает сети, является ли набираемый номер местным, национальным или международным.

Ответ №6:

В некоторых странах вы можете подтвердить 112 как действительный номер телефона, но если вы вставите перед ним код страны, он больше не будет действительным. В других странах вы не можете подтвердить 112, но вы можете подтвердить 911 как действительный номер телефона.

Я видел несколько телефонов, в которых Q ставится на 7-ю клавишу, а Z-на 9-ю. Я видел некоторые телефоны, которые ставят Q и Z на клавишу 0, а некоторые-Q и Z на клавишу 1.

Код города, существовавший вчера, может не существовать сегодня, и наоборот.

В половине Северной Америки (код страны 1) правило второй цифры для кодов городов обычно составляло 0 или 1, но это правило исчезло 10 лет назад.

Ответ №7:

Я не знаю стандартной библиотеки или фреймворка, доступных для форматирования телефонных номеров в E. 164.

Решение, используемое для нашего продукта, которое требует форматирования идентификатора вызывающего абонента, предоставленного АТС, в E. 164, заключается в развертывании файла (таблицы базы данных), содержащего информацию о формате E. 164 для всех применимых стран. Это имеет то преимущество, что приложение может быть обновлено (для обработки всех странных угловых случаев в различных сетях ТСОП) без необходимости внесения изменений в базу производственного кода.

Таблица содержит строку для каждого кода страны и информацию о длине кода региона и длине абонента. Для страны может быть несколько записей в зависимости от возможных вариантов с кодом города и длиной номера абонента.

В качестве примера таблицы используется абонентская группа ТФОП Новой Зеландии (частичная)..

 CC  AREA_CODE  AREA_CODE_LENGTH  SUBSCRIBER  SUBSCRIBER_LENGTH
64                            1              7
64         21                 2              7
64        275                 3              6
 

Мы делаем что-то похожее на то, что вы описали, т. Е. удаляем из предоставленного телефонного номера любые нецифровые символы, а затем форматируем на основе различных правил, касающихся общей длины плана номеров, внешнего кода доступа и междугородних/международных кодов доступа.

Комментарии:

1. Как насчет этого: CC cc AREA_CODE aa AREA_CODE_LENGTH n ПОДПИСЧИК какая ДЛИНА ПОДПИСЧИКА 6 или 7. (Я думаю, что я также видел 7 или 8.)

2. Сокращенные имена столбцов разумны, я отформатировал эту таблицу, как указано выше, исключительно по иллюстративным соображениям. Мне неясно, что означают комментарии для подписчика и их длина ниже.