PHP
SQLite3
電話番号

ハイフン無しの電話番号をハイフン付の形式に変換してみる

概要

システムの移行で元々ハイフン無しの電話番号やFAX番号をハイフン有り形式(3分割)に変換する可能性を考慮して、プログラムで変換がかけられないかを考えてみました。

ちなみに「電話番号」とは通称で、正式には「電気通信番号」、つまり電話以外にもFAXやIoT機器にも割り当てることが出来る番号ということで、総務省が所管しています。
市外局番や市内局番の一覧も、同省ホームページからダウンロード出来るんですが、法改正や市区町村合併とかで変更されることがあると思うのでご注意ください。
本稿は2017年8月時点で確認したものになります。

なお、結構認識とか間違ってるかもしれないので、その辺はご容赦くださいm(_ _)m

実装対象と実装対象の仕様

電話番号の種類

0A0-CDE-FGHJK形式のみ番号のフォーマット順にしています。それ以外は総務省ホームページで紹介されている順に記載しています。

電話番号の種類 フォーマット 桁数 備考
固定電話 0A-BCDE-XXXX 10 Bは原則2~9のみ
固定電話 0AB-CDE-XXXX 10 Cは原則2~9のみ
固定電話 0ABC-DE-XXXX 10 Dは原則2~9のみ
固定電話 0ABCD-E-XXXX 10 Eは原則2~9のみ
M2M等専用番号 020-CDE-FGHJK 11 Cは1~3と5~9のみ。理由は次行。
発信者課金ポケベル 020-4DE-FGHJK 11
IP電話 050-CDEF-XXXX 11 Cは1~9のみ。
UPTサービス/FMCサービス 060-4DE-FGHJK 11 IoT機器とかに割り当てる番号? たぶんCは1~9のみ。
携帯電話、PHS 070-CDE-FGHJK 11 Cは1~9のみ。
携帯電話、PHS 080-CDE-FGHJK 11 Cは1~9のみ。
携帯電話、PHS 090-CDE-FGHJK 11 Cは1~9のみ。
着信課金用電話番号 0120-DEF-XXX 10
着信課金用電話番号 0800-DEF-XXX 10
情報料代理徴収用電話番号 0990-DEF-XXX 10 いわゆる「ダイヤルQ2」などがこれに該当する。
統一番号用電話番号 0570-DEF-XXX 10
  • 固定電話の場合0{市外局番1~4桁}-{市内局番1~4桁}-{加入者番号4桁}となっており、合わせて10桁、市外局番(国内プレフィックス含む)と市内局番をあわせて6桁固定となっているようです。(画像は総務省に掲載のもの)

固定電話の場合

  • 他にも「010」から始まる国際電話番号プレフィックスや、警察(110)、消防(119)、時報(117)などありますが、今回は実装対象外とします。
  • 携帯電話、PHSなど0A0-CDE-FGHJKの番号は、初期契約時の事業者を特定できますが、不要なので対象外とします。

ちなみに書いている途中で「オープンデータ化されていないのかな?」と思って検索してみたらされてました。
電気通信番号指定状況
が、上記ページのファイルへのリンクがあるだけでした。定期的にアップデートする仕組みとか作れるといいかなと思ったんですけどね。

実装

どう実装するか?

仕様はある程度理解できました。
固定電話番号についてに、総務省ホームページのExcelファイルを連結すればマスタは作れそうです。

0A0で始まる番号についてはC(4桁目)には0が入らないようなので、例えば060CDEFGHJと大阪の市外局番06BCDEFGHJを見分けることができそうです。

ということでなんとかできそうなので、まとめます。

桁数のチェック

ハイフンを除いて10桁か11桁しか存在しないみたいなので、それ以外は対象外とします。

国内プレフィックスのチェック

0から始まっていないものは対象外とします。

プレフィックスがはっきりしているものからチェックする

以下のものはプレフィックスがはっきりしていますので、これらを優先的にチェックします。

  • 0A0-CDE-FGHJK形式
    • M2M等専用番号、発信者課金ポケベル(020-CDE-FGHJK
    • IP電話(050-CDEF-XXXX
    • UPTサービス/FMCサービス(060-4DE-FGHJK
    • 携帯電話、PHS(070-CDE-FGHJK080-CDE-FGHJK090-CDE-FGHJK
  • 0ABC-DEF-XXX形式
    • 着信課金用電話番号(0120-DEF-XXX0800-DEF-XXX
    • 情報料代理徴収用電話番号(0990-DEF-XXX
    • 統一番号用電話番号(0570-DEF-XXX

固定電話番号のチェック

2017年8月の時点で、総務省で公開されている固定電話の市外・市内局番のデータは42,691件あります。
流石にこれの判定には時間がかかりそうなので、一番最後にやることにします。

とは言っても、最初6桁で判定が可能なので、データベースで検索する仕組みを作れば問題なさそうです。
なんでもいいのですが、今回は公開されているデータをExcelで統合して、CSVに出力、それをSQLiteに作ったテーブルにインポートしました(SQLiteを選んだのは一番お手軽だったのと他の言語からもアクセスしやすいようにするためです)。ファイル名はja_com_spec_master.sqlite3としています。
もちろんデータに簡単にアクセスできればなんでもいいでの、下図の番号をキーにしたKVSとかに入れておくと高速に処理できると思います。

統合したデータは以下のような感じです。
ma_list.png

設定ファイルにまとめる

ここまでの内容を設定ファイルにまとめて、プログラムで使いやすいようにします。
これもなんでもいいのですが、今回はYAMLにしました。

settings.yml
formats:
  - category: "0A0-CDE-FGHJK" # 0A0-で始まる番号のチェック設定
    length: 11
    regexp: "^0(2|[5-9])0[1-9][0-9]+$" # 0A0-0は存在しない
    digits: [3, 4, 4] # 総務省的には[3, 3, 5]っぽいけど

  - category: "0ABC-DEF-GHJK" # 0ABC-で始まる番号のチェック設定
    length: 10
    regexp: "^0(120|800|990|570)[0-9]+$"
    digits: [4, 3, 3]

  - category: "固定電話" # 固定電話の番号のチェック設定
    length: 10
    regexp: "^0[0-9]+$"
    digits: [0, 0, 4] # 0の部分はデータベースに入れています。3つ目が4桁なのは固定です。

プログラム

今回はPHPを使います。
ということで、Githubに上げました。詳しくはそちらを御覧ください。
https://github.com/tomgoodsun/parse_jp_phone_number

なお、テストデータとして、都道府県庁や地方公共自治体の電話番号を使わせて頂きました。一応全件で正しく処理されたみたいなので、たぶん大丈夫。
こちらもネットで公開されている情報になりますが、リポジトリには上げていません。

まとめ

ここまで来て思った。
Qiitaにすでに同じことやっている人がいた。。。と。
ハイフンなしの電話番号からハイフン付き電話番号を復元する。
俺乙。