Нормализация номеров телефона
Довольно часто приходится приводить номера телефонов в единому формату.
Особенно перех получением хеша номера телефона.
Согласно рекомендации E.164
указывается в формате:
+код_страны код_региона номер_телефона
Данные скрипты приводят номера телефонов в этот формат.
Если код страны не указан, предполагается Россия +7.
Проверочные данные
Следующие примеры показывают приведение и нормализацию номеров телефона.
Входная строка | Нормализованный номер |
---|---|
+7 (999) 999-99-99 | +79999999999 |
7 999 999-99-99 | +79999999999 |
8 (999) 999-99-99 | +79999999999 |
999 999-99-99 | +79999999999 |
+9 999 999-99-99 | +99999999999 |
Правила нормализации
- Если длина строки меньше 8 символов, нормализация не производится
- Удалить из строки все символы, кроме цифры и +
- Если строка не начинается на + и содержит меньше 11 символов, добавить +7 в начало
- Если строка начинается на 8 и содержит 11 символов, заменить начальный 8 на +7
- Если строка не начинается на +, добавить + в начало
Если ваша компания собирает телефоны клиентов из нескольких каналов, в базе наверняка куча некорректных номеров: формы на сайте заполняют кое-как, менеджеры неправильно записывают контакты, а партнёры вовсе не думают о качестве данных. Из-за этого операторы тратят время на бесполезные звонки.
Мы спросили у колл-центров MaxiPost, InteractiveCenter и СКБ «Контур», как привести в порядок телефонные номера. Результат исследования — базовые советы по подготовке к обзвонам. С ними вы быстро уберёте из базы некорректные номера. Всё, что понадобится — Excel и пара сайтов-справочников.
Чтобы проверить советы, мы взяли настоящую базу с 3795 номерами. Эти телефоны оставляли в форме онлайн-заявки на сайте компании. Ниже мы показываем, как шаг за шагом чистим базу от бесполезных контактов.
Предварительный этап: привести номера к единому формату
Что не так. Телефоны попадают в базу через сотрудников поддержки, форму на сайте, анкеты на мероприятиях. Разные люди пишут номера по-разному, и в базе форматы перемешиваются.
- +7987707.21.21,
- 8(986)457834,
- +73957072721,
- 56.56.45.
Если привести номера к одному формату и убрать лишние символы, станет видно: вот эти номера дублируются, а в этих слишком много или мало цифр. Такую базу проще чистить.
Как исправить. Чтобы отформатировать телефоны, мы написали функцию PrepareNumbers для Excel. Она оставляет в номере только цифры, добавляет пропущенный «+», а потом меняет «+7» на «8». Если вы не программист, не вчитывайтесь в код, это лишнее.
Public Function PrepareNumbers(InputString As String)
Dim i As Long, newString As String
For i = 1 To Len(InputString)
If IsNumeric(Mid(InputString, i, 1)) Or (i = 1 And Mid(InputString, i, 1) = «+») Then
newString = newString & Mid(InputString, i, 1)
End If
Next i
If Len(newString) = 11 And InStr(newString, 7) = 1 Then
newString = «+» & newString
End If
PrepareNumbers = Replace(newString, «+7», «8», 1, 1)
End Function
Чтобы функция работала, её добавляют в файл с базой данных
Перед форматированием номеров мы делаем копию базы: если что-то пойдёт не так, контакты легко восстановить.
PrepareNumbers не отличается от стандартных функций Excel, и вызывают её тем же способом.
Главный трюк — потянуть за угол зелёной рамки, чтобы PrepareNumbers сработала для всей колонки
Функция убирает из номеров только лишние символы. Если в базе встретится неполный телефон, PrepareNumbers его не восстановит.
Убрать дубли, чтобы не звонить одному человеку несколько раз
Что не так. Номер можно написать по-разному: например, клиент оставил на сайте +7 495 787-25-67, а потом позвонил в контакт-центр, где оператор записал +74957872567. Для базы данных это разные контакты, и теперь человеку позвонят дважды.
Как исправить. Мы привели номера к единому формату, поэтому для удаления дублей подойдёт встроенный инструмент Excel.
Таблицу выделяют целиком, но инструменту «Удалить дубликаты» указывают только колонку, где номера в едином формате
Инструмент называется «Удалить дубликаты», вы найдёте его во вкладке «Данные».
Результат на живой базе: из 3795 записей 663 оказались дубликатами. Это 17,4% от общего числа.
После удаления дублей в базе осталось 3132 номера.
Исключить некорректные номера, чтобы сэкономить время операторов
Что не так. Даже если из базы вычистили дубли, в ней остались контакты, которые отнимают время операторов и портят статистику:
-
номера без кода города или страны;
-
те, что выглядят нормально, но в реальности не существуют;
-
иностранные телефоны, по которым не нужно звонить.
Если исключить такие записи, операторы сэкономят время.
Как исправить. Российский телефон в полном формате — с восьмёркой в начале, кодом и локальным номером — состоит из 11 цифр. За рубежом бывает по-другому, но в этой статье мы говорим только про российских абонентов.
Если мы знаем, что в готовом к обзвону телефоне 11 цифр, простой способ почистить базу — убрать длинные и короткие номера.
Сначала мы попросили Excel посчитать длину телефонных номеров, а потом выбрали те, где ровно одиннадцать цифр. Наши инструменты — функция «ДЛСТР» и фильтр.
После чистки в базе останутся некорректные номера. Например, Excel не знает, что сочетание цифр 8 846 384-23-41 невозможно по плану нумерации Россвязи
Номера, в которых меньше или больше 11 цифр, мы убрали в отдельный файл и попытались восстановить. Об этом в следующем разделе.
Результат на живой базе: из 3132 номеров только 2578 состоят из одиннадцати цифр. Это значит, что мы избавили операторов от 554 бесполезных звонков (17,6% от числа телефонов, которые остались в базе после удаления дублей).
К этому шагу мы удалили из базы 1217 номера (32%), осталось 2578.
Восстановить номера, чтобы сохранить абонентов
Что не так. Даже если в номере меньше положенных 11 цифр, он может быть корректным. Просто не хватает кода города или страны. Если удалить такой номер из базы, потеряешь хороший контакт.
Как исправить. Телефонный код города или страны можно восстановить при следующих двух условиях.
-
В базе есть город абонента.
-
Телефон городской.
Коды городов и стран есть на сайте Ростелекома. Просто вводим на сайте город, получаем код и подставляем к номеру.
Московский номер так восстановить не получится, потому что у столицы два телефонных кода: 495 и 499
Такое восстановление номера отнимает много времени, но это единственный бесплатный способ.
Результат на живой базе: восстановили коды городов для 92 номеров, отсеянных на предыдущем шаге.
Теперь в базе 2670 номеров.
Проставить часовые пояса, чтобы не разбудить клиента
Что не так. В России 11 часовых поясов. Когда в Москве 16:00, в Хабаровске уже спят и звонить нельзя.
Как исправить. Иногда часовой пояс добавляют в базу контактов и сортируют абонентов по времени звонка.
-
Восточные регионы, их обзванивают утром.
-
Часовой пояс Екатеринбурга.
-
Часовой пояс Москвы.
В течение дня оператор переходит от одной очереди к другой, руководствуясь логикой.
Если в базе нет часового пояса и города, их находят на сайте Россвязи. Сайт принимает номер и показывает город или регион.
Сайтом Россвязи неудобно пользоваться, но это первоисточник
Когда город известен, часовой пояс подскажет поисковик. Набираем «время йошкар-ола» и видим, звонить абоненту сейчас или подождать до утра. Мы сразу запишем часовой пояс клиента в базу, чтобы больше не искать.
Как привести в порядок базу номеров
-
Привести телефоны к единому формату.
Инструмент: Excel.
Результат на живой базе: 3795 отформатированных номеров, с которыми удобно работать. -
Убрать дубли.
Инструмент: Excel.
Результат на живой базе: −663 дубля. -
Исключить «битые» номера из обзвона.
Инструмент: Excel.
Результат на живой базе: −554 слишком длинных или коротких номера. -
Восстановить номера.
Инструмент: сайт «Ростелекома».
Результат на живой базе: +92 номера, восстановленных из неполных контактов. -
Составить расписание звонков с учётом часовых поясов. Инструмент: сайт «Россвязи».
Итог на живой базе. Мы избавили операторов от 895 бесполезных звонков. Кроме того, восстановили код города для 92 номеров и получили пригодные для обзвона телефоны.
Из 3795 номеров в базе осталось 2670 (70,3%). По ним можно звонить в любой момент.
Мнение редакции может не совпадать с мнением автора. Ваши статьи присылайте нам на 42@cossa.ru. А наши требования к ним — вот тут.
Возникла задача автоматического форматирования телефонных номеров в виде страна (город) номер, и первым делом я обратился к существующим решениям.
К сожалению, оказалось, что все найденные решения основываются на обычном подгоне строки под пользовательский формат, имея ограниченную область применения и ошибки при выходе за ее пределы.
Для начала приведу обзор найденных решений. Тем, кому это не интересно, рекомендую прокрутить ниже до заголовка «Форматы телефонных номеров» — там уже представлен мой вариант разбора номера с ссылкой на код.
Всеуничтожающий примитив
(Найденное решение. Мое ниже)
Первое, на что я наткнулся — были сообщения на форумах и банки скриптов, предлагающие решения следующего плана:
<?
function phone_number($sPhone){
$sPhone = ereg_replace(«[^0-9]»,»,$sPhone);
if(strlen($sPhone) != 10) return(False);
$sArea = substr($sPhone, 0,3);
$sPrefix = substr($sPhone,3,3);
$sNumber = substr($sPhone,6,4);
$sPhone = «(«.$sArea.«)».$sPrefix.«-«.$sNumber;
return($sPhone);
}
?>
Один из простых вариантов шустрого форматирования телефонных номеров, но каждое такое решение ориентировано на телефонные номера из конкретной локальной зоны и не является решением задачи.
Форматирование с помощью sscanf
(Найденное решение. Мое ниже)
function formatPhone($phone) {
if (empty($phone)) return «»;
if (strlen($phone) == 7)
sscanf($phone, «%3s%4s», $prefix, $exchange);
else if (strlen($phone) == 10)
sscanf($phone, «%3s%3s%4s», $area, $prefix, $exchange);
else if (strlen($phone) > 10)
if(substr($phone, 0,1)==‘1’) {
sscanf($phone, «%1s%3s%3s%4s», $country, $area, $prefix, $exchange);
}
else{
sscanf($phone, «%3s%3s%4s%s», $area, $prefix, $exchange, $extension);
}
else
return «unknown phone format: $phone»;
$out = «»;
$out .= isset($country)? $country.‘ ‘: »;
$out .= isset($area)? ‘(‘. $area. ‘) ‘: »;
$out .= $prefix. ‘-‘. $exchange;
$out .= isset($extension)? ‘ x’. $extension: »;
return $out;
}
Не смотря на простое решение, эта функция уже умеет форматировать номера длиной 7, 10 и более цифр, но попадись ей номер из российской глубинки, она подавится и выдаст ошибочный результат.
Symfony, lib/helpers/PhoneHelper.php, format_phone
(Найденное решение. Мое ниже)
<?php
function format_phone($phone = », $convert = false, $trim = true)
{
// If we have not entered a phone number just return empty
if (empty($phone)) {
return »;
}// Strip out any extra characters that we do not need only keep letters and numbers
$phone = preg_replace(«/[^0-9A-Za-z]/», «», $phone);// Do we want to convert phone numbers with letters to their number equivalent?
// Samples are: 1-800-TERMINIX, 1-800-FLOWERS, 1-800-Petmeds
if ($convert == true) {
$replace = array(‘2’=>array(‘a’,‘b’,‘c’),
‘3’=>array(‘d’,‘e’,‘f’),
‘4’=>array(‘g’,‘h’,‘i’),
‘5’=>array(‘j’,‘k’,‘l’),
‘6’=>array(‘m’,‘n’,‘o’),
‘7’=>array(‘p’,‘q’,‘r’,‘s’),
‘8’=>array(‘t’,‘u’,‘v’), ‘9’=>array(‘w’,‘x’,‘y’,‘z’));// Replace each letter with a number
// Notice this is case insensitive with the str_ireplace instead of str_replace
foreach($replace as $digit=>$letters) {
$phone = str_ireplace($letters, $digit, $phone);
}
}// If we have a number longer than 11 digits cut the string down to only 11
// This is also only ran if we want to limit only to 11 characters
if ($trim == true && strlen($phone)>11) {
$phone = substr($phone, 0, 11);
} // Perform phone number formatting here
if (strlen($phone) == 7) {
return preg_replace(«/([0-9a-zA-Z]{3})([0-9a-zA-Z]{4})/», «$1-$2», $phone);
} elseif (strlen($phone) == 10) {
return preg_replace(«/([0-9a-zA-Z]{3})([0-9a-zA-Z]{3})([0-9a-zA-Z]{4})/», «($1) $2-$3», $phone);
} elseif (strlen($phone) == 11) {
return preg_replace(«/([0-9a-zA-Z]{1})([0-9a-zA-Z]{3})([0-9a-zA-Z]{3})([0-9a-zA-Z]{4})/», «$1($2) $3-$4», $phone);
}// Return original phone if not 7, 10 or 11 digits long
return $phone;
}
?>
Функция позволяет не только форматировать в XXX-XXXX, (XXX) XXX-XXXX и X (XXX) XXX-XXXX, но и конвертировать номера, написанные цифрами. Ограниченность функции в форматировании номеров длиной 7, 10 и 11 символов никак не подходит.
Форматы телефонных номеров
Из вики-статьи видно, что никакого простого и удобного паттерна для быстрого форматирования всех номеров не существует. Коды стран регистрируются, подобно доменным зонам, а коды городов — остаются на совести каждой из стран.
Другими словами, маршрутизация звонков идет по маске, начиная с кода страны: звонок, направленный в конкретную страну далее пробивает себе маршрут в соответствии с кодами области, города, района и т.д. начиная с самой левой цифры, пока последнее звено не перебросит его на конкретный телефонный/факсовый аппарат. Проблема усложняется еще и тем, что коды городов внутри стран точно так же не поддаются единой сквозной стандартизации, т.е. в худшем из вариантов для правильного форматирования номеров придется использовать двумерный массив с кодами стран и их городов.
На самом деле, все оказалось не так страшно. В каждой стране можно разделить все коды городов на две части: на те, что в большинстве своем совпадают по длине, и все остальные. Этого достаточно, чтобы резко сократить область перебора кодов при сравнении. Т.е. можно создать массив из данных по каждой стране вида:
<?
$data = Array(
‘Код страны’=>Array(
‘name’=>‘Имя страны’, // для удобства. Не будет использоваться.
‘cityCodeLength’=> обычная_длина_кода_города_для_этой_страны,
‘exceptions’=>Array(коды_городов_исключения),
)
);
?>
Затем провести предварительную обработку данных, дополнив его полями, сужающими область перебора, exceptions_max и exceptions_min — максимальной и минимальной длиной кода городов-исключений, соответственно. Также необходимо учесть страны, в которых коды городов начинаются на 0 — отразим эту «особенность» полем zeroHack. Как пример:
<?
$data = Array(
‘886’=>Array(
‘name’=>‘Taiwan’,
‘cityCodeLength’=>1,
‘zeroHack’=>false,
‘exceptions’=>Array(89,90,91,92,93,96,60,70,94,95),
‘exceptions_max’=>2,
‘exceptions_min’=>2
),
);
?>
После этого возьмем подходящие участки кода из решений выше и сделаем функцию форматирования:
<?
function phone($phone = », $convert = true, $trim = true)
{
global $phoneCodes; // только для примера! При реализации избавиться от глобальной переменной.
if (empty($phone)) {
return »;
}
// очистка от лишнего мусора с сохранением информации о «плюсе» в начале номера
$phone=trim($phone);
$plus = ($phone[ 0] == ‘+’);
$phone = preg_replace(«/[^0-9A-Za-z]/», «», $phone);
$OriginalPhone = $phone;// конвертируем буквенный номер в цифровой
if ($convert == true && !is_numeric($phone)) {
$replace = array(‘2’=>array(‘a’,‘b’,‘c’),
‘3’=>array(‘d’,‘e’,‘f’),
‘4’=>array(‘g’,‘h’,‘i’),
‘5’=>array(‘j’,‘k’,‘l’),
‘6’=>array(‘m’,‘n’,‘o’),
‘7’=>array(‘p’,‘q’,‘r’,‘s’),
‘8’=>array(‘t’,‘u’,‘v’),
‘9’=>array(‘w’,‘x’,‘y’,‘z’));foreach($replace as $digit=>$letters) {
$phone = str_ireplace($letters, $digit, $phone);
}
}// заменяем 00 в начале номера на +
if (substr($phone, 0, 2)==«00»)
{
$phone = substr($phone, 2, strlen($phone)-2);
$plus=true;
}// если телефон длиннее 7 символов, начинаем поиск страны
if (strlen($phone)>7)
foreach ($phoneCodes as $countryCode=>$data)
{
$codeLen = strlen($countryCode);
if (substr($phone, 0, $codeLen)==$countryCode)
{
// как только страна обнаружена, урезаем телефон до уровня кода города
$phone = substr($phone, $codeLen, strlen($phone)-$codeLen);
$zero=false;
// проверяем на наличие нулей в коде города
if ($data[‘zeroHack’] && $phone[ 0]==‘0’)
{
$zero=true;
$phone = substr($phone, 1, strlen($phone)-1);
}$cityCode=NULL;
// сначала сравниваем с городами-исключениями
if ($data[‘exceptions_max’]!= 0)
for ($cityCodeLen=$data[‘exceptions_max’]; $cityCodeLen>=$data[‘exceptions_min’]; $cityCodeLen—)
if (in_array(intval(substr($phone, 0, $cityCodeLen)), $data[‘exceptions’]))
{
$cityCode = ($zero? «0»: «»).substr($phone, 0, $cityCodeLen);
$phone = substr($phone, $cityCodeLen, strlen($phone)-$cityCodeLen);
break;
}
// в случае неудачи с исключениями вырезаем код города в соответствии с длиной по умолчанию
if (is_null($cityCode))
{
$cityCode = substr($phone, 0, $data[‘cityCodeLength’]);
$phone = substr($phone, $data[‘cityCodeLength’], strlen($phone)-$data[‘cityCodeLength’]);
}
// возвращаем результат
return ($plus? «+»: «»).$countryCode.‘(‘.$cityCode.‘)’.phoneBlocks($phone);
}
}
// возвращаем результат без кода страны и города
return ($plus? «+»: «»).phoneBlocks($phone);
}// функция превращает любое число в строку формата XX-XX-… или XXX-XX-XX-… в зависимости от четности кол-ва цифр
function phoneBlocks($number){
$add=»;
if (strlen($number)%2)
{
$add = $number[ 0];
$add .= (strlen($number)<=5? «-«: «»);
$number = substr($number, 1, strlen($number)-1);
}
return $add.implode(«-«, str_split($number, 2));
}// тесты
echo phone(«+38 (044) 226-22-04»).«<br />»;
echo phone(«0038 (044) 226-22-04»).«<br />»;
echo phone(«+79263874814»).«<br />»;
echo phone(«4816145»).«<br />»;
echo phone(«+44 (0) 870 770 5370»).«<br />»;
echo phone(«0044 (0) 870 770 5370»).«<br />»;
echo phone(«+436764505509»).«<br />»;
echo phone(«(+38-048) 784-15-46 «).«<br />»;
echo phone(«(38-057) 706-34-03 «).«<br />»;
echo phone(«+38 (044) 244 12 01 «).«<br />»;
?>
, где global $phoneCodes; — тот самый массив с информацией по всем странам.
Выведет
+380(44)226-22-04<br/>+380(44)226-22-04<br/>+7(926)387-48-14<br/>481-61-45<br/>+44(0870)770-53-70<br/>+44(0870)770-53-70<br/>+43(6764)50-55-09<br/>380(4878)415-46<br/>380(5770)634-03<br/>+380(44)244-12-01
Функция полностью решает поставленную задачу.
Из недостатков функции следует отметить отсутствие анализа медленных участков с целью оптимизаци, а также обработки телефонных номеров, где есть код города, но нет кода страны (в этом случае достаточно бить на блоки функцией phoneBlocks или воспользоваться одним из решений выше). При использовании ее в какой-либо реализации необходимо заменить глобальную переменную на ссылку в параметре, а также можно доработать или заменить формат вывода, за который отвечает функция phoneBlocks.
Самое интересное
Используя информацию с сайтов:
http://www.mtt.ru/info/def/index.wbp
http://www.hella.ru/code/codeuro.htm
http://www.scross.ru/guide/phone-global/
я собрал массив данных по всем представленным странам, включая города-исключения, флаги zeroHack, а также коды мобильных сетей. Код можно загрузить здесь.
Быстродействие
Вопреки всем самым пессимистичным ожиданиям, код отрабатывает 10.000 номеров менее чем за 2 секунды.
UPD Готовятся поправки:
- поддержка паттернов форматирования, принятых внутри конкретных стран («локально-принятые» нормы отображения номеров);
- добавление флага для указания, относительно какой страны выполнять форматирование номера;
- добавление параметра для указания формата вывода (в случае личных предпочтений и исключений);
- поддержка нелатинских буквенных номеров
- определение сотовых номеров и замена скобок на пробелы
UPD: Архив пропал с сервера, выложил на https://github.com/mrXCray/PhoneCodesСкоро будет обновление по поправкам выше + бонус.
Несколько PHP-функций для форматирования телефонных номеров.
1
Формат +7 (xxx) xxx-xx-xx
Формат +7 (xxx) xxx-xx-xx очень распространён, но правильнее писать номера без скобок. В нормах русского языка скобки используются для поясняющей и дополняющей информации, а так как без кода оператора или города дозвониться до абонента не получится, то это уже не дополнительная информация.
function phone_format($phone)
{
$phone = trim($phone);
$res = preg_replace(
array(
'/[+]?([7|8])[-|s]?([-|s]?(d{3})[-|s]?)[-|s]?(d{3})[-|s]?(d{2})[-|s]?(d{2})/',
'/[+]?([7|8])[-|s]?(d{3})[-|s]?(d{3})[-|s]?(d{2})[-|s]?(d{2})/',
'/[+]?([7|8])[-|s]?([-|s]?(d{4})[-|s]?)[-|s]?(d{2})[-|s]?(d{2})[-|s]?(d{2})/',
'/[+]?([7|8])[-|s]?(d{4})[-|s]?(d{2})[-|s]?(d{2})[-|s]?(d{2})/',
'/[+]?([7|8])[-|s]?([-|s]?(d{4})[-|s]?)[-|s]?(d{3})[-|s]?(d{3})/',
'/[+]?([7|8])[-|s]?(d{4})[-|s]?(d{3})[-|s]?(d{3})/',
),
array(
'+7 ($2) $3-$4-$5',
'+7 ($2) $3-$4-$5',
'+7 ($2) $3-$4-$5',
'+7 ($2) $3-$4-$5',
'+7 ($2) $3-$4',
'+7 ($2) $3-$4',
),
$phone
);
return $res;
}
PHP
Тестирование и результаты
Мобильные и городские:
echo phone_format('+7 (495) 1234567');
echo phone_format('+8 (495) 123 45 67');
echo phone_format('+7(495)123-45-67');
echo phone_format('+7(495)1234567');
echo phone_format('+7 495 123-45-67');
echo phone_format('+8 495 123 45 67');
echo phone_format('+7 495 1234567');
echo phone_format('+7-495-123-45-67');
echo phone_format('84951234567');
PHP
+7 (495) 123-45-67
+7 (495) 123-45-67
+7 (495) 123-45-67
+7 (495) 123-45-67
+7 (495) 123-45-67
+7 (495) 123-45-67
+7 (495) 123-45-67
+7 (495) 123-45-67
+7 (495) 123-45-67
Региональные:
echo phone_format('7 4734 12-34-56');
echo phone_format('7 4735 123-456');
PHP
+7 (4734) 12-34-56
+7 (4735) 123-456
С текстом:
echo phone_format('+7-495-123-45-67 Иван');
echo phone_format('+84951234567 доп. 123');
echo phone_format('+74951234567, +79031234567');
echo phone_format('тел. +84951234567');
PHP
+7 (495) 123-45-67 Иван
+7 (495) 123-45-67 доп. 123
+7 (495) 123-45-67, +7 (903) 123-45-67
тел. +7 (495) 123-45-67
Номера с ошибками:
echo phone_format('495 1234567');
echo phone_format('8(8001234567');
echo phone_format('8800;1234567');
PHP
495 1234567
8(8001234567
8800;1234567
2
Формат +7 xxx xxx-xx-xx
function phone_format($phone)
{
$phone = trim($phone);
$res = preg_replace(
array(
'/[+]?([7|8])[-|s]?([-|s]?(d{3})[-|s]?)[-|s]?(d{3})[-|s]?(d{2})[-|s]?(d{2})/',
'/[+]?([7|8])[-|s]?(d{3})[-|s]?(d{3})[-|s]?(d{2})[-|s]?(d{2})/',
'/[+]?([7|8])[-|s]?([-|s]?(d{4})[-|s]?)[-|s]?(d{2})[-|s]?(d{2})[-|s]?(d{2})/',
'/[+]?([7|8])[-|s]?(d{4})[-|s]?(d{2})[-|s]?(d{2})[-|s]?(d{2})/',
'/[+]?([7|8])[-|s]?([-|s]?(d{4})[-|s]?)[-|s]?(d{3})[-|s]?(d{3})/',
'/[+]?([7|8])[-|s]?(d{4})[-|s]?(d{3})[-|s]?(d{3})/',
),
array(
'+7 $2 $3-$4-$5',
'+7 $2 $3-$4-$5',
'+7 $2 $3-$4-$5',
'+7 $2 $3-$4-$5',
'+7 $2 $3-$4',
'+7 $2 $3-$4',
),
$phone
);
return $res;
}
PHP
Результат:
/* Мобильные и городские */
+7 495 123-45-67
+7 495 123-45-67
+7 495 123-45-67
+7 495 123-45-67
+7 495 123-45-67
+7 495 123-45-67
+7 495 123-45-67
+7 495 123-45-67
+7 495 123-45-67
/* Региональные */
+7 4734 12-34-56
+7 4735 123-456
/* С текстом */
+7 495 123-45-67 Иван
+7 495 123-45-67 доп. 123
+7 495 123-45-67, +7 903 123-45-67
тел. +7 495 123-45-67
/* Номера с ошибками */
495 1234567
8(8001234567
8800;1234567
3
Формат +7-xxx-xxx-xx-xx
function phone_format($phone)
{
$phone = trim($phone);
$res = preg_replace(
array(
'/[+]?([7|8])[-|s]?([-|s]?(d{3})[-|s]?)[-|s]?(d{3})[-|s]?(d{2})[-|s]?(d{2})/',
'/[+]?([7|8])[-|s]?(d{3})[-|s]?(d{3})[-|s]?(d{2})[-|s]?(d{2})/',
'/[+]?([7|8])[-|s]?([-|s]?(d{4})[-|s]?)[-|s]?(d{2})[-|s]?(d{2})[-|s]?(d{2})/',
'/[+]?([7|8])[-|s]?(d{4})[-|s]?(d{2})[-|s]?(d{2})[-|s]?(d{2})/',
'/[+]?([7|8])[-|s]?([-|s]?(d{4})[-|s]?)[-|s]?(d{3})[-|s]?(d{3})/',
'/[+]?([7|8])[-|s]?(d{4})[-|s]?(d{3})[-|s]?(d{3})/',
),
array(
'+7-$2-$3-$4-$5',
'+7-$2-$3-$4-$5',
'+7-$2-$3-$4-$5',
'+7-$2-$3-$4-$5',
'+7-$2-$3-$4',
'+7-$2-$3-$4',
),
$phone
);
return $res;
}
PHP
Результат:
/* Мобильные и городские */
+7-495-123-45-67
+7-495-123-45-67
+7-495-123-45-67
+7-495-123-45-67
+7-495-123-45-67
+7-495-123-45-67
+7-495-123-45-67
+7-495-123-45-67
+7-495-123-45-67
/* Региональные */
+7-4734-12-34-56
+7-4735-123-456
/* С текстом */
+7-495-123-45-67 Иван
+7-495-123-45-67 доп. 123
+7-495-123-45-67, +7 903 123-45-67
тел. +7-495-123-45-67
/* Номера с ошибками */
495 1234567
8(8001234567
8800;1234567
TEXT
Блог
Формат телефонных номеров
Читайте наш новый материал о форматах телефонных номеров при отправке рассылок из личного кабинета, API или через интеграции с популярными CMS/CRM-системами.
Достаточно часто наши клиенты и партнеры сталкиваются с некоторыми сложностями при отправке СМС-сообщений из-за того, что в их базах для рассылок используются не совсем канонические номера телефонов. Для того, чтобы СМС-сообщение было корректно отправлено получателю, наша система должна распознать:
- Код страны (например, +7 — это Россия)
- Def-код (например, 926, 903 и т.п.)
- Номер абонента (например, в России это последние 7 цифр номера)
Несмотря на кажущуюся простоту этого вопроса, на практике применяется огромное количество самых разных вариаций написания телефонных номеров, немалая часть из которых приводит к невозможности отправить сообщения, а некоторые форматы так напрямую приводят к самым неприятным моментам, когда СМС ошибочно отправляется в другую страну (и другому абоненту, соответственно) и при этом неверно тарифицируется.
На примере номера +79001234567 проиллюстрируем несколько примеров многообразия форматов, которые мы регулярно встречаем на практике:
- «Без плюса» (пишут «79001234567»)
- «Без семерки» (пишут («9001234567»)
- «Через восьмерку» (пишут «89001234567»)
- «Без def-кода (пишут «мег. 1234567»)
- «Скобки» (пишут «8(900)1234567»). Обычно может сочетаться с другими форматами, например, «+7 (900) 123-45-67»
- «Пробелы» (пишут «8 900 123 45 67»). Обычно может сочетаться с другими форматами, например, «+7 (900) 123-45-67»
- «Дефисы» (пишут «8-900-123-45-67»). Обычно может сочетаться с другими форматами, например, «+7 (900) 123-45-67»
- «Точки» (пишут «8.900.123.45.67)». Обычно может сочетаться с другими форматами, например, «900.123.45.67»
К этому стоит добавить также:
- Явно ошибочные номера телефонов, например, слишком длинные или слишком короткие
- Немобильные номера телефонов, например, городские
- Нероссийские номера телефонов, которые могут отличаться по длине от российских.
Проблема может усугубляться тем, что ряд систем имеют маски номеров телефонов, который существенным образом отличаются от канонических. Например, многие сталкивались с тем, что при введении номера телефона автоматически определяется страна, а сам номер может быть визуально представлен в любом из вышеперечисленных форматов.
Наша компания, разумеется, всеми силами пытается облегчить жизнь клиентов и партнеров и:
- Автоматически отфильтровывает (=удаляет) из баз некорректные номера (длинные, короткие, немобильные и т.п.)
- Автоматически приводит номера к каноническому формату, убирая скобки, дефисы и т.п.
- Автоматически распознает номера телефонов других стран и т.п.
Единственная оговорка: при отправке СМС через API требуется очень жесткий канонический формат номера телефона а виде +79001234567 или 79001234567, так как запросы идут напрямую на СМС-шлюзы операторов связи.
1.Резюме:
- Рекомендуем всегда придерживаться канонического формата номера телефона (+79001234567)
- Если Вы отправляете СМС через личный кабинет или интеграции, то наша система всю работу по нормализации номеров сделает за Вас автоматически
- Если Вы отправляете СМС через API, то требуется отправлять номера в каноническом формате.