Qual è il modo migliore per convertire i numeri di telefono in formato internazionale (E.164) usando Java?

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

Domanda

Qual è il modo migliore per convertire i numeri di telefono in formato internazionale (E.164) usando Java?

Dato un 'numero di telefono' e un ID paese (diciamo un codice paese ISO), vorrei convertirlo in un numero di telefono standard E.164 in formato internazionale.

Sono sicuro di poterlo fare a mano abbastanza facilmente - ma non sarei sicuro che funzionerebbe correttamente in tutte le situazioni.

Quale framework / libreria / utility Java consiglieresti di realizzare questo?

P.S. Il "numero di telefono" potrebbe essere identificabile dal pubblico in generale, ad esempio

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

l'ultimo è il mio preferito - è come alcune persone scrivono il loro numero nel Regno Unito e significa che dovresti usare il +44 o dovresti usare lo 0.

Il numero del formato E.164 deve essere tutto numerico e utilizzare il codice Paese internazionale completo (ad es. + 44)

È stato utile?

Soluzione

Google fornisce una libreria per lavorare con i numeri di telefono. Lo stesso che usano per 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));

Altri suggerimenti

Parlando per esperienza nello scrivere questo genere di cose, è davvero difficile farlo con un'affidabilità del 100%. Ho scritto un codice Java per fare ciò che è ragionevolmente buono nell'elaborare i dati che abbiamo ma che non sarà applicabile in tutti i paesi. Le domande che devi porre sono:

Il carattere per numerare le mappature è coerente tra i paesi? Gli Stati Uniti ne usano molto (ad esempio 1800-GOT-MILK) ma in Australia, ad esempio, è piuttosto raro. Quello che dovresti fare è assicurarti di fare la mappatura corretta per il paese in questione se varia (potrebbe non farlo). Non so cosa facciano i paesi che usano alfabeti diversi (ad esempio il cirillico in Russia e gli ex paesi del blocco orientale);

Devi accettare che la tua soluzione non sarà al 100% e non dovresti aspettarti che lo sia. Devi prendere una "migliore ipotesi" approccio. Ad esempio, non esiste un vero modo per sapere che 132345 è un numero di telefono valido in Australia, come lo è 1300 123 456 ma che questi sono gli unici due schemi che sono per numeri 13xx e non sono richiamabili dall'estero;

Devi anche chiedere se vuoi validare le regioni (prefissi). Credo che gli Stati Uniti utilizzino un sistema in cui la seconda cifra del prefisso è 1 o 0. Questo potrebbe essere stato una volta, ma non sono sicuro che si applichi ancora. In ogni caso, molti altri paesi avranno altre regole. In Australia, i prefissi validi per i telefoni fissi e mobili (cellulari) sono a due cifre (la prima è 0). 08, 03 e 04 sono tutti validi. 01 non lo è. Come lo approvi? Vuoi?

I paesi usano convenzioni diverse, indipendentemente da quante cifre stanno scrivendo. Devi decidere se vuoi accettare qualcosa di diverso dalla "norma". Questi sono tutti comuni in Australia:

  • (02) 1234 5678
  • 02 1234 5678
  • 0411 123 123 (ma non ho mai visto 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 è il prefisso internazionale standard)
  • (44) 078 1234 1234 (non comune)

E questo è appena dalla parte superiore della mia testa. Per un paese. In Francia, ad esempio, è comune scrivere il numero di telefono in coppie di numeri (12 34 56 78) e lo pronunciano così: invece di:

un (uno), deux (due), trois (tre), ...

la sua

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

Vuoi soddisfare quel livello di differenza culturale? Suppongo di no, ma vale la pena considerare la domanda nel caso in cui le regole siano troppo rigide.

Inoltre, alcune persone possono aggiungere numeri di interno ai numeri di telefono, possibilmente con "ext" o abbreviazione simile. Vuoi soddisfare questo?

Siamo spiacenti, nessun codice qui. Solo un elenco di domande da porre e problemi da considerare. Come altri hanno già detto, una serie di espressioni regolari può fare gran parte di quanto sopra, ma alla fine i campi dei numeri di telefono sono (principalmente) testo in forma libera alla fine della giornata.

Questa era la mia soluzione:

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

Spero che questo aiuti qualcuno con lo stesso problema.

Divertiti e usa liberamente.

Grazie per le risposte. Come indicato nella domanda originale, sono molto più interessato alla formattazione del numero nel formato standard di quanto non sia nel determinare se si tratta di un numero di telefono valido (come nel vero).

Al momento ho un codice elaborato a mano che accetta un numero di telefono String (come inserito dall'utente) e un contesto di paese di origine e contesto di paese di destinazione (il paese da cui viene composto il numero e il paese in cui il numero viene selezionato - questo è noto al sistema) e quindi esegue la seguente conversione nei passaggi

  1. Rimuovi tutto lo spazio bianco dal numero

  2. Traduci tutte le alfa in cifre - usando una tabella di ricerca da lettera a cifra (es. A - > 2, B - > 2, C - > 2, D - > 3) ecc. per la tastiera (non ero a conoscenza del fatto che alcune tastiere li distribuiscono in modo diverso)

  3. Rimuovi tutta la punteggiatura - mantenendo intatto il precedente '+' se esiste (nel caso in cui il numero sia già in una sorta di formato internazionale).

  4. Determina se il numero ha un prefisso di composizione internazionale per il contesto del Paese, ad es. se il contesto di origine è il Regno Unito, vedrei se inizia con un '00' e lo sostituisco con un '+'. Attualmente non controllo se le cifre che seguono "00" sono seguite dal prefisso internazionale per il paese di destinazione. Cerco il prefisso di selezione internazionale per il paese di origine in una tabella di ricerca (ad esempio GB - > '00 ', US - >' 011 'ecc.)

  5. Determina se il numero ha un prefisso di selezione locale per il contesto del Paese, ad es. se il contesto di origine è il Regno Unito, vorrei vedere se inizia con uno '0' e sostituirlo con uno '+' seguito dal prefisso internazionale per il paese di destinazione. Cerco il prefisso di selezione locale per il paese di origine in una tabella di ricerca (ad es. GB - > '0', US - > '1' ecc.) E il prefisso internazionale per il paese di destinazione in un'altra ricerca tabella (ad esempio "GB" = "44", US = "1")

Sembra funzionare per tutto ciò che ho lanciato finora - fatta eccezione per la situazione +44 (0) 1234-567-890 - Aggiungerò un controllo del caso speciale per quello.

Scrivere non è stato difficile - e posso aggiungere casi speciali per ogni strana eccezione che incontro. Ma vorrei davvero sapere se esiste una soluzione standard.

Le compagnie telefoniche sembrano occuparsi di questa cosa ogni giorno. Non ottengo mai risultati incoerenti durante la composizione di numeri tramite PSTN. Ad esempio, negli Stati Uniti (dove i telefoni cellulari hanno gli stessi prefissi telefonici dei telefoni fissi, potrei comporre + 1-123-456-7890 o 011-1-123-456-7890 (dove 011 è il prefisso di composizione internazionale nella US e 1 è il prefisso internazionale per gli Stati Uniti), 1-123-456-7890 (dove 1 è il prefisso di composizione locale negli Stati Uniti) o addirittura 456-7890 (supponendo che in quel momento fossi nel prefisso 123) e ottenere gli stessi risultati ogni volta. Presumo che internamente questi numeri composti vengano convertiti nello stesso formato standard E.164 e che la conversione avvenga interamente tramite software.

Ad essere onesti, sembra che tu abbia già coperto la maggior parte delle basi.

Il formato +44 (0) 800 a volte (erroneamente) utilizzato nel Regno Unito è fastidioso e non è strettamente valido secondo E.123, che è la raccomandazione ITU-T per come devono essere visualizzati i numeri. Se non hai una copia di E.123, vale la pena dare un'occhiata.

Per quello che vale, la stessa rete telefonica non usa sempre E.164. Spesso ci sarà una bandiera nella segnalazione ISDN generata dal PBX (o nella rete se si è su un telefono a vapore) che indica alla rete se il numero da comporre è locale, nazionale o internazionale.

Questo è un compito molto difficile poiché i numeri di telefono sono scritti in modo diverso quasi in ogni paese.

Abbiamo usato per mantenere un elenco di REGEXP (abbiamo supportato 19 formati) per analizzare 3 parti di un numero e quindi convertirle in " + {1} {2} {3} " ;.

Ordina le regexps per prima più specifiche e poi prendi la prima che riesce ad analizzare.

In alcuni paesi è possibile convalidare il 112 come numero di telefono valido, ma se si attacca un prefisso internazionale, non sarà più valido. In altri paesi non è possibile convalidare 112 ma è possibile convalidare 911 come numero di telefono valido.

Ho visto alcuni telefoni che mettono Q sul tasto 7 e Z sul tasto 9. Ho visto alcuni telefoni che mettono Q e Z sul tasto 0 e alcuni che mettono Q e Z sul tasto 1.

Un prefisso che esisteva ieri potrebbe non esistere oggi e viceversa.

Nella metà del Nord America (codice paese 1), la regola della seconda cifra era 0 o 1 per i prefissi, ma quella regola è andata via 10 anni fa.

Non sono a conoscenza di una libreria o di un framework standard disponibili per la formattazione dei numeri di telefono in E.164.

La soluzione utilizzata per il nostro prodotto, che richiede la formattazione del PBX fornito con ID chiamante in E.164, è quella di distribuire un file (tabella del database) contenente le informazioni sul formato E.164 per tutti i paesi applicabili. Ciò ha il vantaggio che l'applicazione può essere aggiornata (per gestire tutti gli strani casi angolari in varie reti PSTN) senza richiedere modifiche alla base di codice di produzione.

La tabella contiene una riga per ciascun prefisso internazionale e informazioni sulla lunghezza del prefisso e sulla lunghezza dell'abbonato. Potrebbero essere presenti più voci per un Paese in base alle variazioni possibili con prefisso e lunghezze dei numeri degli abbonati.

Utilizzo del dial plan PSTN (parziale) della Nuova Zelanda come esempio della tabella ..

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

Facciamo qualcosa di simile a quello che hai descritto, ad esempio eliminando il numero di telefono fornito di tutti i caratteri non numerici e quindi formattandolo in base a varie regole relative alla lunghezza complessiva del piano di numerazione, al codice di accesso esterno e ai codici di accesso interurbano / internazionale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top