Замечали когда-нибудь, что все записывают телефонные номера по-разному? Некоторые пишут их через пробелы, другие через дефис, а кто-то использует скобки. Разные люди по-разному группируют цифры номеров в числа.
И это становится реальной проблемой, когда вам нужно сохранить телефонные номера в базе данных и затем извлекать из неё записи по ним.
▍ Содержание
- Что такое нормализованный телефонный номер?
- В форматах телефонных номеров неразбериха
- Почему это проблема
- Как нормализовать телефонный номер
- Философия телефонных номеров
- Заключение
▍ Что такое нормализованный телефонный номер?
В сфере IT и компьютерных науках нормализация означает приведение чего-либо к согласованности или стандарту. В отношении телефонных номеров это подразумевает, что все их записи делаются в согласованном формате.
Существует ли международный стандарт для номеров телефонов? Международный союз электросвязи (International Telecommunication Union, ITU) опубликовал стандарт E.123, который определяет стандартные записи телефонных номеров, email и веб-адресов.
Записанный в формате E.123, международный телефонный номер выглядит так:
+12 345 678 901
Символ +
указывает на международный формат номера. Код страны здесь представлен числом 12
, а остальные цифры — это, собственно, сам телефонный номер.
Но когда людей просят ввести номер в поле формы, большинство записывают его так, как принято в их регионе, или как им больше нравится. В результате варианты написания могут сильно отличаться как от страны к стране, так и от человека к человеку.
▍ В форматах телефонных номеров полная неразбериха
Например, в США тот же телефонный номер будет записан так:
(345) 678-901
В Великобритании местные номера записываются так:
01234 56 7890
А в Индии так:
0123-456-7890
При этом некоторые люди порой вместо символа +
используют международный код доступа 00
.
0012 345 678 901
▍ Почему это проблема?
Когда вы сохраняете телефонные номера в базе данных, вам нужна возможность находить их независимо от того, как они были введены.
Представьте, что у вас в базе есть следующие номера:
123-456-7890
(234) 567-8901
0345 / 678 9012
+456 789 0123
567-890-1234
Если же вам поступит вызов с +12 345 678 9012
, как вы найдёте его в базе данных, чтобы получить информацию о соответствующем клиенте?
Как нормализовать телефонный номер
Наименее неоднозначным вариантом для хранения телефонного номера является определённый E.123 международный формат, в котором отсутствуют пробелы: +123456789012
.
Но как к нему прийти?
▍ Через пользовательский интерфейс
Лучше всего будет попросить пользователей изначально вводить свои номера в этом формате.
Для этого можно предоставить им выпадающий список стран и автоматически форматировать телефонный номер на основе выбранного кода.
Например, библиотека International Telephone Input предлагает такой удобный UI:
Источник: github.com/jackocnr/intl-tel-input
▍ Обработка существующих данных
Если вы не можете обеспечить, чтобы пользователи вводили номера телефонов в подходящем формате, потому что имеете дело с легаси-данными или импортируете их из другого источника, то задача усложнится, но не станет невозможной.
Для начала рассмотрите вариант использования библиотеки. У Google есть опенсорсное решение под названием libphonenumber, которое окажется полезным во многих случаях.
Если вы работаете с Python, попробуйте портированную на этот язык версию той же libphonenumber — phonenumbers.
Также есть её вариант для JavaScript, а именно google-libphonenumber.
Но иногда вам потребуется написать собственную функцию нормализации или обрабатывать особые случаи, которые не может обработать библиотека из-за недостатка контекста.
Я же сосредоточусь на том подавляющем числе сценариев, в которых вашим основным врагом выступает несогласованное написание телефонных номеров. Кстати, в разделе «Философия телефонных номеров» приведены наиболее странные причины такого написания.
Вот список шагов, которые вам потребуется проделать для стандартизации:
▍ Исключите нечисловые символы
При удалении нечисловых символов на первом шаге нужно быть очень внимательным, так как некоторые из них могут служить для определения кода области.
Способ написания телефонного номера может дать некоторые подсказки относительно кода страны и области. Например, в США код области зачастую включается в скобки:
(234) 567-8901
А иногда отделяется пробелом или слэшем:
0345 / 678 9012
01234 56 7890
Учитывайте эти варианты написания, чтобы лишний раз не гадать о коде страны или области.
▍ Определите код страны
Если вы имеете дело с телефонными номерами одной страны, то можете предположить, что либо в эти номера уже включён соответствующий код в виде +1
, +12
или +123
, либо это местные номера.
Люди могут также вводить код страны без символа +
, например, указывая только 1
или 12
.
Если местный номер начинается с одного 0
, уберите этот 0
и добавьте код страны. Если номер начинается с 00
, уберите 00
, но предположите, что код страны уже присутствует.
01234 56 7890
станет+441234 56 7890
0044 1234 56 7890
станет+441234 56 7890
Если вы работаете с номерами из разных стран, вам потребуется понять, какую страну предполагал пользователь, когда вводил свой номер.
Если вам повезёт, и нужно будет обработать всего несколько стран, коды области могут дать подсказку, поскольку среди них есть такие, которые используются в одной стране, но не в других.
▍ Сохраните только цифры и символ +
В качестве заключительного шага удалите все нечисловые символы, кроме +
в начале.
Итоговый нормализованный номер будет выглядеть так:
+123456789012
Теперь его можно сохранить в виде строки.
Когда вам нужно найти телефонный номер, предварительно нормализуйте поисковое выражение аналогичным образом.
На всякий случай желательно также сохранить исходный номер. Он может потребоваться позднее для верификации или показа пользователю.
▍ Философия телефонных номеров
Должен признаться, что преподнёс ситуацию гораздо проще, чем она обстоит на самом деле. Предыдущая часть статьи в основном охватывает те случаи, с которыми вы никогда не столкнётесь, и в реальности всё гораздо запутанней.
Более подробно эта тема раскрыта в статье «Falsehoods Programmers Believe About Phone Numbers», которую можно найти в репозитории библиотеки libphonenumber.
Вот ряд наиболее коварных аспектов, в отношении которых нужно быть внимательными:
- Телефонные номера не всегда уникальны: люди могут иметь по несколько номеров, или один номер может использоваться разными людьми.
- Телефонные номера иногда меняются: люди порой меняют свои номера, которые впоследствии могут закрепляться за другими людьми.
- Не все номера можно набрать на телефоне или в виде текста.
- Могут использоваться символы не из кодировки ASCII: например, в Египте для написания номеров зачастую используется арабский шрифт.
- Телефонные планы нумерации изменяются: в странах иногда меняются планы нумерации. При этом может присутствовать переходный период, когда действительными являются оба формата.
- Телефонные номера — это не числа: в математическом смысле телефонный номер не является числом, то есть номер
7
не равнозначен номеру007
.
▍ Заключение
Сохранение телефонных номеров в том виде, в котором они вводятся, с большой вероятностью создаст проблемы при их дальнейшем поиске. Поэтому желательно их изначально нормализовать.
Вот краткий перечень основных пунктов статьи:
- Старайтесь изначально получать от пользователей номера в нормализованном виде.
- Показывайте эту нормализованную форму пользователям и просите её подтвердить.
- Некоторые нечисловые символы могут дать подсказку относительно кодов страны/области.
- При попытке определить код страны учитывайте местные особенности написания номеров.
- Не нужно просто удалять нечисловые символы и сохранять оставшиеся цифры как номер.
- Вносите телефонные номера в базу данных в виде нормализованных строк, а также сохраняйте их изначальную форму.
Автор: Дмитрий Брайт