Quel est le meilleur moyen de convertir les numéros de téléphone au format international (E.164) en utilisant Java?

StackOverflow https://stackoverflow.com/questions/187216

Question

Quel est le meilleur moyen de convertir les numéros de téléphone au format international (E.164) en utilisant Java?

Etant donné un "numéro de téléphone" et un identifiant de pays (disons un indicatif de pays ISO), j'aimerais le convertir en un numéro de téléphone au format international standard E.164.

Je suis sûr de pouvoir le faire à la main assez facilement, mais je ne serais pas sûr que cela fonctionnerait correctement dans toutes les situations.

Quel framework / bibliothèque / utilitaire Java recommanderiez-vous pour cela?

P.S. Le "numéro de téléphone" peut être tout ce qui est identifiable par le grand public - tel que

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

ce dernier est mon préféré - c’est la façon dont certaines personnes écrivent leur numéro au Royaume-Uni. Cela signifie que vous devez soit utiliser le +44, soit le 0.

Le numéro de format E.164 doit être entièrement numérique et utiliser le code de pays international complet (par exemple, + 44)

Était-ce utile?

La solution

Google fournit une bibliothèque pour travailler avec des numéros de téléphone. Le même qu'ils utilisent pour 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));

Autres conseils

Parlant d’expérience en écrivant ce genre de choses, c’est vraiment difficile à faire avec une fiabilité à 100%. Pour ce faire, j'ai écrit du code Java qui est raisonnablement bon pour traiter les données que nous avons mais ne sera pas applicable dans tous les pays. Les questions à poser sont les suivantes:

Les mappages de personnage à nombre sont-ils cohérents entre les pays? Les États-Unis en utilisent beaucoup (par exemple, 1800-GOT-MILK), mais en Australie, par exemple, il est plutôt rare. Ce que vous devez faire, c'est vous assurer que vous faites la cartographie correcte pour le pays en question si elle varie (cela peut ne pas être le cas). Je ne sais pas ce que les pays qui utilisent des alphabets différents (par exemple, le cyrilic en Russie et les pays de l'ancien bloc de l'Est) le font;

Vous devez accepter le fait que votre solution ne sera pas à 100% et que vous ne devriez pas vous y attendre. Vous devez prendre une "meilleure estimation". approche. Par exemple, il n’existe aucun moyen réel de savoir que 132345 est un numéro de téléphone valide en Australie, comme le 1300 123 456, mais que ce sont les deux seuls modèles qui correspondent à des numéros 13xx et qu’ils ne sont pas appelables de l’étranger;

Vous devez également vous demander si vous souhaitez valider des régions (indicatifs régionaux). Je crois que les États-Unis utilisent un système dans lequel le deuxième chiffre de l'indicatif régional est 1 ou 0. C'est peut-être une fois le cas, mais je ne sais pas si cela s'applique toujours. Quoi qu’il en soit, de nombreux autres pays auront d’autres règles. En Australie, les indicatifs régionaux valides pour les lignes fixes et les téléphones mobiles (cellulaires) sont composés de deux chiffres (le premier est 0). 08, 03 et 04 sont tous valables. 01 n'est pas. Comment répondez-vous à cela? Voulez-vous?

Les pays utilisent des conventions différentes, quel que soit le nombre de chiffres qu’ils écrivent. Vous devez décider si vous souhaitez accepter autre chose que la "norme". Ce sont tous communs en Australie:

  • (02) 1234 5678
  • 02 1234 5678
  • 0411 123 123 (mais je n'ai jamais vu le 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 est l'indicatif international standard)
  • (44) 078 1234 1234 (non commun)

Et ça me vient à l'esprit. Pour un pays. En France, par exemple, il est courant d’écrire le numéro de téléphone par paires (12 34 56 78) et de le prononcer ainsi: au lieu de:

un (un), deux (deux), trois (trois), ...

sa

douze (douze), trente-quatre (trente), ...

Voulez-vous répondre à ce niveau de différence culturelle? Je suppose que non, mais la question mérite d’être examinée au cas où vous imposeriez des règles trop strictes.

De plus, certaines personnes peuvent ajouter des numéros de poste sur leurs numéros de téléphone, éventuellement avec " ext " ou abréviation similaire. Voulez-vous répondre à cela?

Désolé, pas de code ici. Juste une liste de questions à vous poser et de questions à considérer. Comme d'autres l'ont déjà dit, une série d'expressions régulières peut servir en grande partie à ce qui est décrit ci-dessus, mais au final, les champs de numéro de téléphone sont (principalement) du texte libre à la fin de la journée.

C’était ma solution:

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

J'espère que cela aidera quelqu'un qui a le même problème.

Profiter et utiliser librement.

Merci pour les réponses. Comme indiqué dans la question initiale, le formatage du numéro au format standard m'intéresse beaucoup plus que le fait de déterminer s'il s'agit d'un numéro de téléphone valide (en véritable).

J'ai actuellement un code fait à la main qui prend un numéro de téléphone, une chaîne (saisie par l'utilisateur), ainsi qu'un contexte de pays source et de pays cible (le pays à partir duquel le numéro est composé et le pays vers lequel le numéro est en cours de composition - le système le sait), puis effectue la conversion suivante par étapes

  1. Supprimez tous les espaces du nombre

  2. Traduisez tous les caractères alpha en chiffres - en utilisant un tableau de correspondance lettre par chiffre (par exemple, A -> 2, B -> 2, C -> 2, D -> 3) etc. pour le clavier (je ne savais pas que certains claviers les distribuent différemment)

  3. Supprimez toute la ponctuation - conservez le caractère '+' précédent s'il existe (si le nombre est déjà dans un format international).

  4. Déterminez si le numéro a un préfixe de numérotation international pour le contexte du pays - par exemple. si le contexte source est le Royaume-Uni, je verrais s'il commence par un «00» - et le remplace par un «+». Je ne vérifie pas actuellement si les chiffres suivant le «00» sont suivis de l'indicatif international du pays cible. Je recherche le préfixe de numérotation international du pays source dans une table de correspondance (par exemple, GB - > '00 ', US - >' 011 ', etc.)

  5. Déterminez si le numéro a un préfixe de numérotation local pour le contexte du pays - par exemple. si le contexte source est le Royaume-Uni, je vérifierais s'il commence par un «0» - et le remplace par un «+» suivi de l'indicatif international du pays cible. Je recherche le préfixe de numérotation local du pays source dans une table de correspondance (par exemple, GB - > '0', US - > '1', etc.), ainsi que l'indicatif international du pays cible dans une autre consultation. table (par exemple, 'GB' = '44', US = '1')

Cela semble fonctionner pour tout ce que j'ai jeté jusqu'à présent - à l'exception du +44 (0) 1234-567-890 - j'ajouterai une vérification de cas particulier pour celui-là.

L'écriture n'a pas été difficile - et je peux ajouter des cas particuliers pour chaque exception étrange que je rencontre. Mais j'aimerais vraiment savoir s'il existe une solution standard.

Les compagnies de téléphone semblent régler ce problème tous les jours. Je n'obtiens jamais de résultats incohérents lorsque je compose des numéros à l'aide du réseau téléphonique commuté. Par exemple, aux États-Unis (où les téléphones mobiles ont les mêmes indicatifs régionaux que les lignes fixes, je pourrais composer le + 1-123-456-7890 ou le 011-1-123-456-7890 (où 011 est le préfixe de composition international du numéro de téléphone). US et 1 est l’indicatif téléphonique international des États-Unis), 1-123-456-7890 (où 1 est le préfixe de numérotation local aux États-Unis) ou même 456-7890 (en supposant que j’étais dans l’indicatif régional 123 à l’époque). et obtenez les mêmes résultats à chaque fois. Je suppose qu'en interne, ces numéros composés sont convertis au même format standard E.164, et que la conversion est entièrement effectuée à l'aide de logiciels.

Pour être honnête, il semble que la plupart des bases soient déjà couvertes.

Le format +44 (0) 800 parfois utilisé (à tort) au Royaume-Uni est gênant et n’est pas strictement valide, conformément à la Recommandation E.123, qui est la recommandation de l’UIT-T concernant la manière dont les chiffres doivent être affichés. Si vous ne possédez pas d’exemplaire de la norme E.123, cela vaut la peine d’être examiné.

Pour ce que cela vaut, le réseau téléphonique lui-même n'utilise pas toujours E.164. Il arrive souvent que la signalisation RNIS générée par le PBX (ou le réseau si vous êtes sur un téléphone Steam) indique au réseau si le numéro composé est local, national ou international.

C’est une tâche très difficile car les numéros de téléphone sont écrits différemment dans presque chaque pays.

Nous avions l'habitude de conserver une liste de REGEXP (nous prenions en charge 19 formats) pour analyser 3 parties d'un nombre, puis les convertir en "+ {1} {2} {3}".

Triez les expressions rationnelles par plus spécifiques en premier, puis prenez le premier qui réussit à analyser.

Dans certains pays, vous pouvez valider le 112 en tant que numéro de téléphone valide, mais si vous y placez un indicatif de pays, celui-ci ne sera plus valide. Dans d’autres pays, vous ne pouvez pas valider le 112 mais vous pouvez valider le 911 en tant que numéro de téléphone valide.

J'ai vu des téléphones mettant Q sur la touche 7 et Z sur la touche 9. J'ai vu des téléphones qui mettent Q et Z sur la touche 0 et d'autres qui mettent Q et Z sur la touche 1.

Un indicatif régional qui existait hier pourrait ne pas exister aujourd'hui, et inversement.

Dans la moitié de l'Amérique du Nord (code de pays 1), la règle du deuxième chiffre était 0 ou 1 pour les indicatifs régionaux, mais cette règle a disparu il y a 10 ans.

Je ne connais pas de bibliothèque ou de structure standard disponible pour formater les numéros de téléphone dans E.164.

La solution utilisée pour notre produit, qui nécessite le formatage de l'identifiant de l'appelant fourni par le PBX dans E.164, consiste à déployer un fichier (table de base de données) contenant les informations de format E.164 pour tous les pays concernés. Cela présente l’avantage que l’application peut être mise à jour (pour traiter tous les cas étranges dans divers réseaux RTPC) sans nécessiter de modification de la base de code de production.

Le tableau contient une ligne pour chaque code de pays et des informations concernant la longueur de l'indicatif régional et la longueur de l'abonné. Il peut y avoir plusieurs entrées pour un pays en fonction des variations possibles avec la longueur de l'indicatif régional et du numéro d'abonné.

Utilisation du plan de numérotation PSTN (partiel) néo-zélandais comme exemple de tableau.

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

Nous faisons quelque chose de similaire à ce que vous avez décrit, c'est-à-dire que nous supprimons le numéro de téléphone fourni de tous les caractères non numériques, puis le formatons en fonction de diverses règles concernant la longueur totale du plan de numérotation, le code d'accès extérieur et les codes d'accès longue distance / international.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top