32

Javaを使用して電話番号を国際形式(E.164)に変換するための最良の方法は何ですか?

「電話番号」と国ID(たとえばISO国コード)が与えられた場合、それを標準のE.164国際形式の電話番号に変換したいと思います。

手作業で簡単にできると思いますが、すべての状況で正しく機能するかどうかはわかりません。

これを実現するために、どのJavaフレームワーク/ライブラリ/ユーティリティをお勧めしますか?

PS「電話番号」は、一般の人が識別できるものであれば何でもかまいません。

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

最後の1つは私のお気に入りです。これは、英国で番号を書く方法であり、+ 44を使用するか、0を使用する必要があることを意味します。

E.164形式の番号はすべて数値であり、完全な国際国コード(eg + 44)を使用する必要があります

4

7 に答える 7

54

Google では、電話番号を操作するためのライブラリを提供しています。彼らが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));
于 2011-03-10T19:30:00.903 に答える
10

このようなことを書いた経験から言えば、100% の信頼性で行うことは非常に困難です。これを行うための Java コードをいくつか作成しました。これは、私たちが持っているデータの処理にはかなり適していますが、すべての国に適用できるわけではありません。あなたが尋ねる必要がある質問は次のとおりです。

文字から数字へのマッピングは国間で一貫していますか? 米国ではこれが多く使用されますが (例: 1800-GOT-MILK)、オーストラリアでは、一例として、非常にまれです。あなたがする必要があるのは、問題の国が異なる場合に正しいマッピングを行っていることを確認することです (そうでない場合もあります)。異なるアルファベットを使用している国 (たとえば、ロシアのキリル文字と旧東部ブロックの国) がどの国で使用されているかはわかりません。

解決策が 100% ではないことを受け入れる必要があり、それを期待するべきではありません。「最善の推測」アプローチを取る必要があります。たとえば、1300 123 456 と同様に 132345 がオーストラリアで有効な電話番号であることを実際に知る方法はありませんが、これらは 13xx 番号の 2 つのパターンのみであり、海外から発信することはできません。

また、地域 (市外局番) を検証するかどうかを確認する必要があります。米国では、市外局番の 2 桁目が 1 または 0 であるシステムを使用していると思います。これは、以前はそうだったかもしれませんが、今でも当てはまるかどうかはわかりません。いずれにせよ、他の多くの国には別のルールがあります。オーストラリアでは、固定電話と携帯電話 (携帯電話) の有効な市外局番は 2 桁です (最初の数字は 0)。08、03、04 はすべて有効です。01ではありません。どのように対応していますか?あなたは__したいですか?

国は、何桁の数字を書いているかに関係なく、さまざまな規則を使用しています。「規範」以外のものを受け入れるかどうかを決定する必要があります。これらはすべてオーストラリアで一般的です。

  • (02) 1234 5678
  • 02 1234 5678
  • 0411 123 123 (ただし、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 は標準の国際ダイヤル コードです)
  • (44) 078 1234 1234 (一般的ではありません)

そして、それは私の頭のてっぺんから外れています。一国のために。たとえば、フランスでは、電話番号を数字のペア (12 34 56 78) で書き、そのように発音するのが一般的です。

un (1)、deux (2)、trois (3)、...

これは

douze (12)、trente-quatre (34)、...

そのレベルの文化の違いに対応したいですか?そうではないと思いますが、ルールを厳しくしすぎた場合に備えて、この質問は検討する価値があります。

また、電話番号に内線番号を追加する人もいます。おそらく「ext」または同様の略語です。あなたはそれに応えたいですか?

申し訳ありませんが、ここにコードはありません。自問する質問と考慮すべき問題のリストです。他の人が言ったように、一連の正規表現は上記の多くを行うことができますが、最終的に電話番号フィールドは (ほとんど) 一日の終わりに自由形式のテキストです.

于 2008-10-10T05:02:44.470 に答える
4

これが私の解決策でした:

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

これが同じ問題を抱えている人に役立つことを願っています。

自由に使って楽しんでください。

于 2011-10-07T12:51:29.363 に答える
1

正直なところ、ほとんどの基地はすでにカバーされているようです。

英国で時々(誤って)使用される+44(0)800形式は煩わしく、数値の表示方法に関するITU-T勧告であるE.123によると厳密には有効ではありません。E.123のコピーをお持ちでない場合は、一見の価値があります。

価値のあることとして、電話網自体が常にE.164を使用するとは限りません。多くの場合、PBXによって生成されたISDNシグナリング(またはSteam電話を使用している場合はネットワーク)にフラグがあり、ダイヤルされている番号がローカル、国内、または国際のいずれであるかをネットワークに通知します。

于 2008-10-30T16:23:37.827 に答える
1

答えてくれてありがとう。元の質問で述べたように、私はそれが有効な (本物の) 電話番号であるかどうかを判断することよりも、番号を標準形式にフォーマットすることに関心があります。

現在、電話番号の文字列 (ユーザーが入力したもの) と、送信元の国のコンテキストと対象国のコンテキスト (番号がダイヤルされている国と、番号がダイヤルされている国) を受け取る手作りのコードがあります。 - これはシステムに認識されている)、次の変換を段階的に実行します。

  1. 数字からすべての空白を取り除きます

  2. すべてのアルファを数字に変換します - 文字から数字へのルックアップ テーブル (例: A-->2、B-->2、C-->2、D-->3) をキーパッドに使用します (私は知りませんでした)一部のキーパッドはこれらを異なる方法で配布します)

  3. すべての句読点を削除します - 先行する '+' が存在する場合はそのまま保持します (数字が何らかの国際形式になっている場合)。

  4. 番号に国のコンテキストの国際ダイヤル プレフィックスがあるかどうかを判断します。たとえば、ソース コンテキストが英国の場合、「00」で始まるかどうかを確認し、「+」に置き換えます。現在、「00」に続く数字の後に対象国の国際電話番号が続くかどうかを確認していません。ルックアップ テーブルで発信国の国際ダイヤル プレフィックスを検索します (例: GB-->'00'、US-->'011' など)。

  5. 番号に国のコンテキストのローカル ダイヤル プレフィックスがあるかどうかを判断します。たとえば、ソース コンテキストが英国の場合、「0」で始まるかどうかを確認し、「+」に置き換えてから国際ダイヤルに置き換えます。対象国のコード。ルックアップ テーブルでソース国のローカル ダイヤル プレフィックスを検索し (たとえば、GB-->'0'、US-->'1' など)、別のルックアップ テーブルでターゲット国の国際ダイヤル コードを検索します (例:「GB」=「44」、US=「1」)

+44(0)1234-567-890 の状況を除いて、私がこれまでに投げたすべてのものでうまくいくようです。その場合の特別なケースチェックを追加します。

それを書くことは難しくありませんでした - そして、私が遭遇した奇妙な例外ごとに特別なケースを追加することができます. しかし、標準的な解決策があるかどうかを知りたいです。

電話会社は、毎日この問題に対処しているようです。PSTN を使用して番号をダイヤルするときに、一貫性のない結果が得られることはありません。たとえば、米国 (携帯電話の市外局番は固定電話と同じ) では、+1-123-456-7890 または 011-1-123-456-7890 にダイヤルできます (011 は、 US で、1 は米国の国際ダイヤル コードです)、1-123-456-7890 (1 は米国のローカル ダイヤル プレフィックス)、または 456-7890 (当時、私が 123 市外局番にいたと仮定します)これらのダイヤルされた番号は内部的に同じ E.164 標準形式に変換され、変換はすべてソフトウェアで行われると想定しています。

于 2008-10-12T01:15:04.227 に答える
0

電話番号をE.164にフォーマットするために利用できる標準ライブラリまたはフレームワークを知りません。

PBXが提供する発信者IDをE.164にフォーマットする必要がある当社の製品に使用されるソリューションは、該当するすべての国のE.164フォーマット情報を含むファイル(データベーステーブル)を展開することです。これには、本番コードベースに変更を加えることなく、アプリケーションを更新できる(さまざまなPSTNネットワークのすべての奇妙なコーナーケースを処理できる)という利点があります。

このテーブルには、各国コードの行と、市外局番の長さと加入者の長さに関する情報が含まれています。市外局番と加入者番号の長さで可能なバリエーションによっては、国に複数のエントリが存在する場合があります。

表の例として、ニュージーランドのPSTN(部分)ダイヤルプランを使用します。

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

私たちはあなたが説明したのと同様のことをします。つまり、提供された数字以外の文字の電話番号を取り除き、全体の番号プランの長さ、外部アクセスコード、および長距離/国際アクセスコードに関するさまざまなルールに基づいてフォーマットします。

于 2008-10-12T04:23:14.147 に答える
0

一部の国では、112 を有効な電話番号として検証できますが、その前に国番号を貼り付けると、それは無効になります。他の国では、112 を検証することはできませんが、911 を有効な電話番号として検証することはできます。

Q を 7 キーに、Z を 9 キーに配置する電話を見たことがあります。Q と Z を 0 キーに配置する電話と、Q と Z を 1 キーに配置する電話を見てきました。

昨日存在した市外局番は、今日存在しない可能性があり、その逆も同様です。

北米の半分 (国コード 1) では、市外局番の 2 桁目の規則は 0 または 1 でしたが、その規則は 10 年前に廃止されました。

于 2008-10-10T05:35:54.107 に答える