web-dev-qa-db-fra.com

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

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 une identité de pays (disons un code 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 que je peux 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 et signifie que vous devez utiliser le +44 ou 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).

26
Vihung

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));
47
Collin Peters

Parlant d'expérience d'écrire 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 que vous devez poser sont les suivantes:

Les mappages de caractère à 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 font les pays qui utilisent des alphabets différents (par exemple, Cyrilic en Russie et les pays de l'ancien bloc de l'Est);

Vous devez accepter que votre solution ne sera pas à 100% et que vous ne devriez pas vous y attendre. Vous devez adopter une approche "meilleure hypothèse". Par exemple, il n’ya 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 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? Veux-tu?

Les pays utilisent des conventions différentes quel que soit le nombre de chiffres qu'ils écrivent. Vous devez décider si vous voulez 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 c'est tout à fait par hasard. 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), ...

ses

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

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 l'abréviation "ext" ou une 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 faire la plupart des choses 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.

10
cletus

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 aide quelqu'un avec le même problème.

Profiter et utiliser librement.

3
arksoft

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

J'ai actuellement un code artisanal qui prend un numéro de téléphone 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 où il est composé - Ceci est connu du système), puis effectue la conversion suivante par étapes.

  1. Supprimer 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 certains claviers les distribuent différemment)

  3. Supprimez toutes les ponctuations - conservez le signe '+' précédent s'il existe (si le numéro est déjà dans un format international).

  4. Déterminez si le numéro a un préfixe de composition 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 table de consultation ( eg'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 un contrôle de cas particulier pour celui-là.

L'écrire 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 réalisée en logiciel.

1
Vihung

Pour être honnête, il semble que vous ayez déjà couvert la plupart des bases.

Le format +44 (0) 800 parfois utilisé (à tort) au Royaume-Uni est gênant et n’est pas strictement valide, conformément à la norme 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’y jeter un coup d’œil.

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

1
Alnitak

Je ne connais pas de bibliothèque ou de cadre 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 PBX à condition que l'identifiant de l'appelant soit 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 applicables . L’avantage de pouvoir mettre à jour l’application (pour traiter tous les cas étranges de différents réseaux RTPC) sans nécessiter de modification de la base de code de production.

Le tableau contient une ligne pour chaque indicatif 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) de la Nouvelle-Zélande 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.

0
Henk

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 garder une liste de REGEXP (19 formats supportés) pour analyser 3 parties d'un nombre, puis les convertir en "+ {1} {2} {3}".

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

0

Dans certains pays, vous pouvez valider le 112 en tant que numéro de téléphone valide, mais si vous le collez devant un indicatif de pays, celui-ci ne sera plus valable. 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 et Z sur la touche. 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.

0
Windows programmer