[ Excel_Tipe29 へ戻る ]
( Coloring by SyntaxHighlighter )
Tips29: JavaScript で電話番号(局番)の検証/編集 [ ソースファイル ダウンロード ] [ Python 用 テストツール ]
[ JavaScript with JSON ( AreaCode4JSON.json ) ]
[ JavaScript ]
[ JAVA ]
[ PHP ]
[ Perl ]
[ Python ]
[ Ruby ]
[ VBA / VB6 ]
[ VB.net ]
( Source Code : Python Ver 1.00 )
動作確認環境 [ IDLE / Python 3.7.2 ] 番号翻訳テーブル [ 2022/7/1 版 ]
#!/usr/bin/env python # -*- coding: utf-8 -*- # ※※ このコードは「タブ」でインデントしてあります ※※ # #//--【 Python 移植版 TelephoneCheck.py ( Ver 1.00 , 翻訳テーブル:2022/7/1 版) 】--------- #// #// 電話番号のハイフン検証/編集関数 #// ( validate_telephone / format_telephone / get_type_telephone / phone_number ) #// #// 【 移植元ソース:番号翻訳テーブル 内包版 TelephoneCheck.js 】 #// #// Tips29: JavaScriptで電話番号(局番)のハイフン検証/編集 #// http://addinbox.sakura.ne.jp/Excel_Tips29.htm #// #// Author : AddinBox(角田) http://addinbox.sakura.ne.jp/ #// #// β 1.00 , 2019/ 2/14 (JavaScript版 初版) #// β 4.40 , 2019/ 3/27 (JavaScript版) #// β 4.40 , 2019/ 3/27 (Python 移植) #// - - - - - - - - - - - - #// Ver 1.00 , 2019/ 4/ 4 (Python 移植, 番号翻訳テーブル:2019/4/1 版) #// Ver 1.00 , 2019/ 5/11 (Python 移植, 番号翻訳テーブル:2019/5/7 版) #// Ver 1.00 , 2020/ 7/20 (Python 移植, 番号翻訳テーブル:2020/6/1 版) #// Ver 1.00 , 2022/ 8/ 1 (Python 移植, 番号翻訳テーブル:2022/7/1 版) #// #// *1 固定電話番号は番号翻訳テーブルによって、全国の市外局番を忠実に判定します。 #// 下記で翻訳テーブルの仕組みを確認できます。 #// [ 電話番号翻訳テーブル 翻訳シュミレーター ] #// http://addinbox.sakura.ne.jp/Excel_Tips29.htm#S2_2 #//------------------------------------------------------------------------------- #// 【 サポートしている電話番号 】 #// 固定電話 10桁(先頭 0) [ 0ABCDE-FGHJ ] #// 携帯電話 11桁(先頭 070/080/090) [ 0x0-CDEF-GHJK , C:1-9 ] 補:060は実施未定 #// 着信課金 10桁(先頭 0120) [ 0120-DEF-GHJ ] #// 着信課金 11桁(先頭 0800) [ 0800-DEF-GHJK ] #// IP電話 11桁(先頭 050) [ 050-CDEF-GHJK , C:1-9 ] #// M2M 11桁(先頭 020x) [ 020-CDE-FGHJK , C:1-3,5-9 ] #// ポケベル 11桁(先頭 0204) [ 020-4DE-FGHJK ] #// FMC 11桁(先頭 0600) [ 0600-DEF-GHJK ] #// 情報料代理徴収 10桁(先頭 0990) [ 0990-DEF-GHJ ] #// 全国統一番号 10桁(先頭 0570) [ 0570-DEF-GHJ ] #//------------------------------------------------------------------------------- import re import sys # 番号翻訳テーブル(2022/7/1 版) # 固定電話の全国の局番(市外局番+市内局番)および携帯電話(070/080/090)等の局番を # 収録しているJSONファイル(AreaCode4JSON.json)を必要最小限の内容に編集しています。 # 完全版のフォーマットは [ http://addinbox.sakura.ne.jp/Excel_Tips29.htm ] を参照の事。 # 尚、このPython用データはJSONファイル作成ツールで一緒に作成していますので、 # 「配列データ」の同一性/正確性は保障します。 # area_code_array = [ [0,1,22,41,42,54,69,70,81,114], [0,-3,2,4,7,10,15,19,20,21], [-103,0,0,-4,-4,-4,3,0,0,0], [0,0,-4,-4,-4,-4,-4,-5,0,0], [0,0,0,-4,-4,-4,-4,5,-4,6], [0,0,-5,0,-5,-4,-4,-5,-4,0], [0,0,-5,-4,-4,-4,-4,-5,-5,0], [0,0,-4,-4,-4,8,9,0,0,0], [0,0,-4,-4,-4,0,-5,-5,0,0], [0,0,-4,-4,-4,-4,-5,0,0,0], [0,0,-4,-4,11,12,13,-4,14,0], [0,0,-4,-4,-4,-4,-4,-5,-3,-4], [0,-3,-4,-4,-4,-4,-4,-3,-5,-4], [0,0,-4,-4,-5,0,-4,-4,0,0], [0,0,-4,-4,-4,-4,-5,-5,-4,0], [0,0,-4,16,17,18,-4,-4,0,0], [0,0,-5,0,-5,-5,-4,0,-4,-4], [0,0,-4,-4,-4,-4,-4,0,-5,0], [0,0,-4,-4,-5,-5,-5,0,-5,0], [0,0,-4,-4,-4,-4,-4,-3,-4,-4], [0,0,-4,-4,-4,-4,-4,-4,-3,0], [0,-4,-4,-4,-4,-4,-3,-4,-4,-3], [130,0,23,25,26,27,32,34,36,39], [-4,0,-3,24,-4,-4,-4,-3,-4,-4], [-3,0,-4,-4,-3,-3,-3,-3,-3,-3], [0,0,0,-4,-4,-4,-3,-4,-4,0], [-4,-4,-4,-4,-4,-3,-4,-4,-4,-3], [-4,0,-3,-3,-4,28,29,30,31,-4], [-3,-3,-3,-3,-3,-3,-3,-4,-4,-3], [-3,0,0,-4,-4,-4,-4,-4,-4,-4], [-3,-3,-4,-4,-4,-3,-3,-3,-3,-3], [-3,0,-4,-4,-4,-4,-4,-4,-4,-4], [-4,-4,-3,-4,33,-4,-4,-4,-4,-4], [-3,0,-4,-4,-4,-4,-3,-3,-3,0], [-4,0,-3,-3,-4,0,-4,-4,35,-4], [0,0,-4,-4,0,-4,-4,-4,-3,-3], [-4,0,-4,37,-4,-4,-3,-4,-4,38], [-3,0,-4,-3,-3,-4,-4,0,-4,-4], [-3,0,0,0,0,-3,-4,-4,-4,-4], [0,-4,-3,40,-4,-4,-4,-4,-3,-4], [-3,0,-4,-4,-4,-3,-3,0,-3,0], [0,0,0,-2,-2,-2,-2,0,0,0], [0,0,43,47,-3,-3,48,49,51,52], [-2,0,44,-3,-3,-3,-3,-3,45,46], [-3,0,-4,-4,-4,-4,-4,-4,-4,-4], [-3,-3,-4,-4,-3,-3,-3,-4,-4,0], [-2,-3,-2,-2,-2,-2,-2,-3,-3,-2], [0,0,-3,-3,-3,0,-4,0,-4,-4], [-4,0,-3,-4,-3,-4,-4,-4,-3,0], [50,-2,0,-3,-3,-4,-4,-3,-4,-4], [-2,0,-4,-4,-4,-4,-4,-4,-4,-2], [-4,0,-3,0,-3,-3,-3,-3,-3,-3], [0,0,-3,-4,-4,-4,0,0,0,53], [0,0,-5,0,-5,0,-5,0,-5,0], [131,0,-3,55,59,60,61,62,64,65], [0,-4,-4,-4,-3,-3,-4,-4,-4,56], [0,0,-3,0,0,0,57,58,-3,0], [0,-4,-4,-4,-3,-3,-3,-3,-3,-3], [0,0,0,-3,-4,0,0,-4,0,0], [0,0,-3,-3,-4,-4,-3,-4,-4,-3], [-4,-4,-3,-4,-4,-4,-4,-4,-4,-3], [0,-4,-4,-4,-4,-4,-4,-4,-4,-4], [-110,0,-4,-4,-4,-4,63,-4,-4,0], [0,0,-4,-4,-4,-4,-4,-4,0,-5], [0,-4,-3,-3,-4,-4,-4,-4,0,0], [0,0,-3,-3,-4,-4,-4,66,-4,68], [0,0,-4,-4,-4,0,0,-4,-4,67], [0,0,-5,-5,-5,-5,-5,-4,-4,-5], [0,0,-4,-4,-4,-4,-4,-4,-4,-3], [132,0,0,0,-2,0,-2,-2,0,0], [133,0,71,72,73,-3,75,76,-3,77], [0,-4,-3,-3,-3,-4,-3,-3,-3,-3], [0,0,0,0,-3,-4,-4,-4,-4,-4], [-4,0,-4,-4,-4,-4,74,-4,-4,-4], [0,0,0,-4,-4,-4,-4,0,-5,0], [0,-4,-3,-4,-3,-4,-4,-4,-4,0], [-4,-4,-4,-4,-4,-3,-4,0,-4,-4], [-4,-4,-3,-3,78,79,80,-4,-4,-4], [0,0,-3,-3,-3,-3,-4,-4,-4,-3], [-3,0,-4,-4,-4,-3,-3,-4,-4,-3], [-3,0,-4,-4,-4,-4,-3,-3,-4,-4], [134,0,82,87,94,96,98,111,112,113], [-4,0,-3,-4,83,-3,-4,-4,-3,84], [-3,0,-3,-3,-4,-4,-4,-4,-4,-3], [-3,0,85,-4,86,-4,-3,-4,-4,0], [-4,-3,-3,-3,-3,-3,-3,-3,-3,-3], [-4,-3,-3,-3,-4,-4,0,0,0,0], [0,0,-3,-4,-4,-4,88,89,91,92], [-3,0,-4,-4,-4,-4,-4,-4,-4,-4], [0,0,-4,-4,-4,-4,90,-3,-3,0], [-4,0,-4,-4,-4,-4,-3,-3,-3,-4], [0,0,-4,-4,-4,-4,0,-5,-5,0], [-3,0,-3,-3,-3,-3,93,-3,-3,-3], [0,0,-5,-3,0,-5,-3,-5,-5,0], [0,0,0,0,0,-4,-4,95,-4,-3], [0,0,-4,-4,-4,-4,-4,-5,-4,0], [0,97,-4,-4,-4,-4,-4,-4,-4,-4], [0,0,-5,0,-5,0,0,0,0,0], [0,0,-3,99,-3,101,103,105,108,109], [0,0,-4,-4,-4,-4,100,-4,-4,0], [0,0,-3,-3,-3,0,-4,0,-3,0], [0,0,-3,0,-4,102,-4,-4,0,0], [-4,0,-3,0,-4,0,0,0,-4,0], [-3,0,-4,-4,-4,-4,-4,-4,-4,104], [-4,-3,-4,-4,-4,-4,-4,-3,-3,-4], [0,0,106,107,-4,-4,-4,-4,-4,-4], [0,0,-3,-3,-3,-4,-3,-4,-3,0], [0,0,0,-4,-4,-4,-4,-3,-3,0], [-3,0,-4,-4,-4,-4,-4,-4,-4,-3], [-3,0,-4,-4,-3,-3,-4,-4,-4,110], [0,0,-4,-4,0,-3,0,-3,0,-3], [0,0,0,0,0,-4,0,-4,-3,-4], [-4,0,0,-4,-4,-4,-3,-4,-3,-4], [0,0,-4,-4,-4,-4,-4,-4,-4,-3], [135,0,115,116,117,118,119,120,121,123], [-4,0,-3,-3,-3,-3,-3,-3,-3,-3], [-4,0,-3,-3,-3,-3,-3,-3,-3,-3], [-4,0,-4,-4,-4,0,-4,-4,-4,-4], [-4,0,-4,0,-4,-4,-4,-4,-3,-4], [0,0,-3,-3,-4,-4,-4,-4,-4,-4], [0,0,-4,-4,-4,-3,0,-4,-4,-4], [122,0,-4,-4,-4,-4,-4,-4,-3,-3], [0,0,-5,-4,-4,-4,-4,-4,-4,-4], [-109,124,-3,125,128,-4,129,-4,-3,0], [0,0,-5,-5,0,0,0,0,0,0], [0,0,-4,126,127,-4,-4,-4,-4,0], [0,-3,-4,-4,-4,-4,-4,-4,-4,-4], [-4,-4,0,-3,0,-3,0,-3,0,-4], [-3,0,-4,-4,-4,-4,-4,-3,-3,-4], [0,0,-4,-4,-4,-4,-4,-4,-4,-5], [0,-106,-106,-106,-107,-106,-106,-106,-106,-106], [0,-105,-105,-105,-105,-105,-105,-105,-105,-105], [-108,0,0,0,0,0,0,0,0,0], [0,-102,-102,-102,-102,-102,-102,-102,-102,-102], [-104,-102,-102,-102,-102,-102,-102,-102,-102,-102], [0,-102,-102,-102,-102,-102,-102,-102,-102,-102] ] #//------------------------------------------------------------------------------- #// 電話番号のフォーマット&検証 ( phone_number ) #// --- validate_telephone/format_telephone の簡易インターフェース --- #// #// TelCode -- 半角文字列[ 0-9, -, (, ) ] #// 固定電話/携帯電話などの[ハイフン/括弧]編集 or 未編集電話番号 #// #// Action -- "V" : 電話番号の検証 #// "F1"〜"F6" : 電話番号の区切り編集( 2桁目が EditType の値 ) #// #// 返却値 #// Action= "V" -- 0: 検証エラー , 1:検証OK , 2:検証OK(電話番号が数字のみ) #// (Boolean 変換すると 0⇒False, 1/2⇒True になります) #// #// = "F1"〜"F6" -- 電話番号が正しい場合: EditType(2桁目)に従って編集した電話番号 #// 電話番号が誤っている場合: "Phone Error" #// #// 上記以外 -- "" (Boolean変換でFalse)で返ります。 #// #//------------------------------------------------------------------------------- def phone_number(tel_code = '', action = ''): # FormatTelephone/ValidateTelephone の返却値 result = init_telephone('Value') str_action = '' pattern_action = re.compile(r'^(([Ff][1-6])|[Vv])$') # "F1"〜"F6" or "V" if not (type(action) is str): return '' else: if (pattern_action.fullmatch(action) != None): str_action = action.upper() else: return '' if not (type(tel_code) is str): return '' else: pass if (str_action == "V"): result = validate_telephone(tel_code) if (result['ErrId'] == 0): return 1 # OK(Boolean変換でTrue) elif (result['ErrId'] == 8): return 2 # OK (電話番号が数字のみ, Boolean変換でTrue) else: return 0 # エラー(Boolean変換でFalse) else: result = format_telephone(tel_code, int(str_action[1]) ) if (result['ErrId'] == 0): return result['TelEdit'] else: return 'Phone Error' #//------------------------------------------------------------------------------- #// 返却値を受け取る変数に辞書オブジェクトの初期設定 ( init_telephone ) #// #// target -- "Value" or "Type" (左記以外 "Value" 扱い) #// #// 返却値 -- target = "Value" の場合、下記の辞書オブジェクト #// {'TelType':-1, 'EditType':9, 'TelEdit':'', 'ErrId':0} #// target = "Type" の場合、下記の連想配列 #// {'TelType':-1, 'SizeAll':0, 'Size1':0, 'Size2':0, 'Size3':0, 'ErrId':0} #//------------------------------------------------------------------------------- def init_telephone(target = 'Value'): target2 = '' if (type(target) is str): if (target.upper() == 'VALUE'): target2 = 'Value' elif (target.upper() == 'TYPE'): target2 = 'Type' else: target2 = 'Value' if (target2 == 'Value'): return {'TelType':-1, 'EditType':9, 'TelEdit':'', 'ErrId':0} else: return {'TelType':-1, 'SizeAll':0, 'Size1':0, 'Size2':0, 'Size3':0, 'ErrId':0} #//------------------------------------------------------------------------------- #// 電話番号の検証 ( validate_telephone ) #// #// tel_code -- 半角文字列[ 0-9, -, (, ) ] #// 固定電話/携帯電話などの[ハイフン/括弧]編集 #// #// 返却値 -- {TelType, EditType, TelEdit, ErrId} の辞書オブジェクト(要素名は大文字混じり) #// TelType 1:固定電話(10桁), 2:携帯電話(070/080/090,11桁), 3:着信課金(0120,10桁), #// 4:着信課金(0800,11桁), 5:IP電話(050,11桁), 6:M2M(020x,11桁,x≠4), #// 7:ポケベル(0204,11桁), 8:FMC(0600,11桁), 9:情報料徴収(0990,10桁), #// 10:統一番号(0570,10桁), -1:other #// #// EditType 1or4: 0AB-CDE-FGHJ, 2or5: 0AB(CDE)FGHJ, 3or6: (0AB)CDE-FGHJ, 9:other #// 携帯電話のみ、[3-4-4 桁]で区切る⇒1〜3 , [3-3-5 桁]で区切る⇒4〜6 #// #// TelEdit TelType/EditType で編集し直された電話番号(正しい編集結果) #// ErrId=0/1/3/5 : 同じパターンで編集し直された電話番号 #// 〃 =8 : ハイフン編集した電話番号 #// 〃 =2 : TelCode のまま(未使用局番なので正誤は判断しない) #// 〃 =4/6/9 : 空文字 #// #// ErrId 0:OK, 1:区切り位置不正, 2:未使用局番(固定電話), 3:市内局番1桁目が[0 or 1](固定電話), #// 4:引数不正([数字,ハイフン,括弧]以外がある or 編集パターン不正 or '0'始まりでない or 桁数不足), #// 5:引数不正(局番タイプに応じた桁数と不一致), #// 6:その他のエラー, 8:OK(数字のみ指定), 9:引数未定義(TelCode) #//------------------------------------------------------------------------------- def validate_telephone(tel_code = ''): # 返却値 result = init_telephone('Value') # format_telephone の返却値 result_format = init_telephone('Value') # 携帯電話(3-3-5桁区切り編集の再取得用) result_format2 = init_telephone('Value') str_tel_code = '' # Pythonには引数に型指定が無いのでチェック&変換する tel_number = '' # ハイフン,括弧除去(数字のみ) edit_type = 9 # 厳密なチェックは format_telephone の結果と比較して行なうので # 下記のパターンチェックでは桁数については曖昧で構わない。 pattern0 = re.compile(r'^0\d+$') # 0123456789 pattern1 = re.compile(r'^0\d+-\d+-\d+$') # 012-345-6789 pattern2 = re.compile(r'^0\d+\(\d+\)\d+$') # 012(345)6789 pattern3 = re.compile(r'^\(0\d+\)\d+-\d+$') # (012)345-6789 remove_pattern = re.compile(r'-|\(|\)') # ハイフン,括弧の除去用 if (type(tel_code) is str): str_tel_code = tel_code elif (type(tel_code) is int): # 数値の場合、先頭'0'が取れるので format_telephoneでエラーが返る str_tel_code = str(tel_code) else: result['ErrId'] = 9 return result if (pattern0.fullmatch(str_tel_code) != None): # (数字のみ) 0123456789 # 数字のみ指定 ⇒ 編集のみ行って比較検証は無し result_format = format_telephone(str_tel_code, 1) # ハイフン編集で固定 result['TelType'] = result_format['TelType'] result['EditType'] = 1 result['TelEdit'] = result_format['TelEdit'] # validate用のエラーコードに差替え if (result_format['ErrId'] == 0): result['ErrId'] = 8 # OK(数字のみ指定) elif (result_format['ErrId'] == 1): result['ErrId'] = 2 # 未使用局番(固定電話番号) elif (result_format['ErrId'] == 2): result['ErrId'] = 3 # 市内局番1桁目が[0 or 1](固定電話) elif (result_format['ErrId'] == 3): result['ErrId'] = 4; # 桁数不足(数字が10桁未満) elif (result_format['ErrId'] == 4): result['ErrId'] = 5; # 局番タイプに応じた桁数と不一致 else: result['ErrId'] = 6 # その他のエラー return result elif (pattern1.fullmatch(str_tel_code) != None): # edit_type:1 012-345-6789 edit_type = 1 result['EditType'] = 1 elif (pattern2.fullmatch(str_tel_code) != None): # edit_type:2 012(345)6789 edit_type = 2 result['EditType'] = 2 elif (pattern3.fullmatch(str_tel_code) != None): # edit_type:3 (012)345-6789 edit_type = 3 result['EditType'] = 3 else: # [数字,ハイフン,括弧]以外がある or 編集パターン不正 or '0'始まりでない result['ErrId'] = 4 result['TelEdit'] = str_tel_code return result # format_telephone 用に[ハイフン,括弧]を除去して「数字のみ」にする tel_number = re.sub(remove_pattern,'',str_tel_code) # ハイフン,括弧の除去 result_format = format_telephone(tel_number, edit_type) # format_telephone で編集し直した結果と比較して検証する # ErrId で返るのは # 0:OK, 1:未使用局番(固定電話), 2:市内局番1桁目が[0 or 1](固定電話) # 3:引数不正(TelCode: 数字が10桁未満), # 4:引数不正(TelCode: 局番タイプの桁数と不一致) # 下記状態は既にチェック済なので、その値が返ることは無い # 3:引数不正(TelCode: ['0'始まりの数字]以外) # 6:引数不正(EditType) # 9:引数未定義(TelCode/EditType) result['TelType'] = result_format['TelType'] result['TelEdit'] = result_format['TelEdit'] # validate用のエラーコードに差替え if (result_format['ErrId'] == 0): # format_telephoneでOK ⇒ 正しい電話番号 if (str_tel_code == result_format['TelEdit']): result['ErrId'] = 0 # OK (区切り位置も正しい) else: if (result_format['TelType'] == 2): # 携帯電話(070/080/090) # 携帯電話の場合、別の区切り方[3-3-5 桁]で再チェック result_format2 = format_telephone(tel_number, edit_type + 3) if (str_tel_code == result_format2['TelEdit']): # OK (3-3-5桁で一致) result['ErrId'] = 0 result['TelEdit'] = result_format2['TelEdit'] result['EditType'] = edit_type + 3 else: result['ErrId'] = 1 # 区切り位置不正 else: # 携帯電話 以外 result['ErrId'] = 1 # 区切り位置不正 elif (result_format['ErrId'] == 1): result['ErrId'] = 2 # 未使用局番(固定電話番号) result['TelEdit'] = tel_code # ResultFormat.TelEdit(=TelNumber)なので入力値に差し替える elif (result_format['ErrId'] == 2): result['ErrId'] = 3 # 市内局番1桁目が[0 or 1](固定電話) elif (result_format['ErrId'] == 3): result['ErrId'] = 4 # 桁数不足(数字が10桁未満) elif (result_format['ErrId'] == 4): result['ErrId'] = 5 # 局番タイプに応じた桁数と不一致 else: result['ErrId'] = 6 #その他のエラー return result #//------------------------------------------------------------------------------- #// 電話番号のハイフン編集 ( format_telephone ) #// #// tel_code -- 半角数字文字列[ 0-9 ], 10 or 11桁(先頭'0'固定) #// 固定電話/携帯電話などの電話番号 #// #// edit_type -- 数値 #// 1or4: 0AB-CDE-FGHJ , 2or5: 0AB(CDE)FGHJ , 3or6: (0AB)CDE-FGHJ #// 携帯電話のみ、[3-4-4 桁]で区切る⇒1〜3 , [3-3-5 桁]で区切る⇒4〜6 #// #// 返却値 -- {TelType, EditType, TelEdit, ErrId} の辞書オブジェクト(要素名は大文字混じり) #// TelType 1:固定電話(10桁), 2:携帯電話(070/080/090,11桁), 3:着信課金(0120,10桁), #// 4:着信課金(0800,11桁), 5:IP電話(050,11桁), 6:M2M(020x,11桁,x≠4), #// 7:ポケベル(0204,11桁), 8:FMC(0600,11桁), 9:情報料徴収(0990,10桁), #// 10:統一番号(0570,10桁), -1:other #// #// EditType 1or4: 0AB-CDE-FGHJ, 2or5: 0AB(CDE)FGHJ, 3or6: (0AB)CDE-FGHJ, 9:other #// #// TelEdit 編集された電話番号 #// ErrId=0/2/4 : 編集された電話番号 #// 〃 =1 : TelCode の内容のまま #// 〃 =3/6/9 : 空文字 #// #// ErrId 0:OK, 1:未使用局番(固定電話), 2:市内局番1桁目が[0 or 1](固定電話), #// 3:引数不正(TelCode: ['0'始まりの数字]以外 or 10桁未満), #// 4:引数不正(TelCode: 局番タイプに応じた桁数と不一致) #// 6:引数不正(EditType), 9:引数未定義(TelCode/EditType) #//------------------------------------------------------------------------------- def format_telephone(tel_code = '', edit_type = 0): # 返却値 result = init_telephone('Value') # get_type_telephone 返却値 result_Type = init_telephone('Type') str_tel_code = '' # Pythonには引数に型指定が無いのでチェック&変換する int_edit_type = 0 tel_pattern = re.compile(r'^0\d{9,}$') # '0'始まりの数字文字列(10桁以上) edit_type_pattern = re.compile(r'^[1-6]$') # '1' 〜 '6'(1文字) if (type(tel_code) is str): str_tel_code = tel_code elif (type(tel_code) is int): str_tel_code = str(tel_code) # 数値の場合、先頭'0'が取れるので次の判定でエラーで返る else: result['ErrId'] = 9 return result # ['0'始まりの数字文字列(10桁以上)]のチェック # (番号翻訳(get_type_telephone)後に完全な桁数チェックを行なう。ここでは10桁未満のみNG) if (tel_pattern.fullmatch(str_tel_code) == None): result['ErrId'] = 3 return result else: pass if (type(edit_type) is str): if (edit_type_pattern.fullmatch(edit_type) != None): int_edit_type = int(edit_type) # OK else: result['ErrId'] = 6 return result elif (type(edit_type) is int): if ((edit_type >= 1) and (edit_type <= 6)): int_edit_type = edit_type # OK else: result['ErrId'] = 6 return result else: result['ErrId'] = 6 return result result['EditType'] = int_edit_type result_type = get_type_telephone(str_tel_code) # 番号翻訳して電話番号の種別と桁区切り情報を取得する # ErrId で返るのは # 0:OK, 1:未使用局番(固定電話), 2:市内局番1桁目が[0 or 1](固定電話) # 下記状態は既にチェック済なので、その値が返ることは無い # 3:電話番号種別が不明(桁数不足で番号翻訳未了)← 10桁以上なので未了は無い # 8:引数不正(TelCode: ['0'始まりの数字]以外) # 9:引数未定義(TelCode) result['TelType'] = result_type['TelType'] result['ErrId'] = result_type['ErrId'] if (result_type['ErrId'] == 1): # 未使用局番(固定電話) result['TelEdit'] = str_tel_code else: # 0:OK or 2:市内局番1桁目が[0 or 1](固定電話) if (result_type['TelType'] == 2 and int_edit_type >= 4): # 携帯電話(070/080/090)で[3-3-5 桁区切り, 0x0-CDE-FGHJK]を指定された場合 result['TelEdit'] = _insert_separator(str_tel_code, int_edit_type, 3, 3) else: # 携帯電話(3-4-4桁区切り)を含め、他は返却値で区切りパターンが得られる # 固定電話では[市外局番桁数/市内局番桁数/加入者番号桁数(4)]が得られる if (result_type['Size2'] == 0): # 固定電話で、市内局番なし [ 0ABCDE-FGHJ ] (現在、この地域は存在しない) result['TelEdit'] = str_tel_code[0 : 6] + '-' + str_tel_code[6:] else: result['TelEdit'] = _insert_separator(str_tel_code, int_edit_type, result_type['Size1'], result_type['Size2']) if (len(str_tel_code) != result_type['SizeAll']): result['ErrId'] = 4 # 桁数エラー(局番タイプに応じた桁数と不一致) else: pass return result def _insert_separator(tel_code, edit_type, size1, size2): result = '' edit_code1 = tel_code[0 : size1] # 1st section :固定電話では市外局番(先頭'0') edit_code2 = tel_code[size1 : (size1 + size2)] # 2nd section :固定電話では市内局番 edit_code3 = tel_code[size1 + size2 :] # 3rd section :固定電話では加入者番号(末尾まで取り出す) if ((edit_type == 1) or (edit_type == 4)): # 0AB-CDE-FGHJ result = edit_code1 + '-' + edit_code2 + '-' + edit_code3 elif ((edit_type == 2) or (edit_type == 5)): # 0AB(CDE)FGHJ result = edit_code1 + '(' + edit_code2 + ')' + edit_code3 elif ((edit_type == 3) or (edit_type == 6)): # (0AB)CDE-FGHJ result = '(' + edit_code1 + ')' + edit_code2 + '-' + edit_code3 else: pass return result #//------------------------------------------------------------------------------- #// 電話番号タイプの取得 ( get_type_telephone ) #// #// tel_code -- 半角数字文字列(2桁以上, 先頭'0'固定) #// 固定電話/携帯電話などの電話番号(途中までの内容でも可) #// #// 返却値 -- {TelType, SizeAll, Size1, Size2, Size3, ErrId} の辞書オブジェクト(要素名は大文字混じり) #// TelType 1:固定電話(10桁), 2:携帯電話(070/080/090,11桁), 3:着信課金(0120,10桁), #// 4:着信課金(0800,11桁), 5:IP電話(050,11桁), 6:M2M(020x,11桁,x≠4), #// 7:ポケベル(0204,11桁), 8:FMC(0600,11桁), 9:情報料徴収(0990,10桁), #// 10:統一番号(0570,10桁), -1:other #// #// SizeAll ErrId=0/2 : TelType に応じた電話番号の桁数(10 or 11, Size1〜3の合計値) #// ErrId=1/3/8/9 : 0 #// #// Size1-3 ErrId=0/2 : TelType に応じた電話番号の区切り桁数(Size1 には先頭'0'含む) #// ErrId=1/3/8/9 : 0 #// (携帯電話(TelType=2)は[3-4-4 桁区切り]のみで返す) #// #// ErrId 0:OK, 1:未使用局番(固定電話), 2:市内局番1桁目が[0 or 1](固定電話), #// 3:電話番号種別が不明(桁数不足で番号翻訳未了) #// 8:引数不正(TelCode: ['0'始まりの数字]以外), 9:引数未定義(TelCode) #//------------------------------------------------------------------------------- def get_type_telephone(tel_code = ''): # 返却値 result = init_telephone('Type') str_tel_code = '' # Pythonには引数に型指定が無いのでチェック&変換する area_code_length = 0 city_code_length = 0 city_code1 = '' # 市内局番の1桁目 idx = 0 cnt = 0 num = 0 link_value = 0 tel_type = 0 tel_pattern = re.compile(r'^0\d+$') # '0'始まりの数字文字列(桁数制限なし) # ( 1)固定電話 10桁 [ 桁区切りは番号翻訳結果に拠る ] # ( 2)携帯電話 11桁 [ 0x0-CDEF-GHJK , 070/080/090 ] # ( 3)着信課金 10桁 [ 0120-DEF-GHJ ] # ( 4)着信課金 11桁 [ 0800-DEF-GHJK ] # ( 5)IP電話 11桁 [ 050-CDEF-GHJK ] # ( 6)M2M 11桁 [ 020-CDE-FGHJK ] # ( 7)ポケベル 11桁 [ 020-4DE-FGHJK ] # ( 8)FMC 11桁 [ 0600-DEF-GHJK ] # ( 9)情報料代理徴収 10桁 [ 0990-DEF-GHJ ] # (10)全国統一番号 10桁 [ 0570-DEF-GHJ ] # SizeInfo [SizeAll, Size1, Size2, Size3] size_info = [ [0,0,0,0], [10,0,0,0], [11,3,4,4], [10,4,3,3], [11,4,3,4], [11,3,4,4], [11,3,3,5], [11,3,3,5], [11,4,3,4], [10,4,3,3], [10,4,3,3] ]; if (type(tel_code) is str): str_tel_code = tel_code elif (type(tel_code) is int): str_tel_code = str(tel_code) # 数値の場合、先頭'0'が取れるので次の判定でエラーで返る else: result['ErrId'] = 9 return result # ['0'始まりの数字文字列(桁数制限なし)]のチェック if (tel_pattern.fullmatch(str_tel_code) == None): result['ErrId'] = 8 return result else: pass # ※ 番号翻訳テーブルをソースコード内に直に収録しているので # JSONファイルの読み込み処理は必要ない。 # 番号翻訳テーブルから局番情報(市外局番の桁数 or [携帯番号 等]のTelType情報)を取得する。 # [tel_code]の長さが[局番桁数 未満]も受け入れているので『番号翻訳 途中』でのループ終了(tel_Type= -1)もある。 idx = 0 tel_type = -1; area_code_length = 0; for cnt in range(1, min([6, len(str_tel_code)])): # 番号翻訳テーブルはA〜Eコードの5段(cnt=1〜5) num = int(str_tel_code[cnt : (cnt + 1)]) # 電話番号の2桁目以降(1桁目は'0')を順次取り出す link_value = area_code_array[idx][num] if (link_value == 0): # 番号翻訳 終了(固定電話 未使用局番) tel_type = 1 area_code_length = 0 break elif (link_value < 0): # 番号翻訳 終了 if (link_value > -100): # 固定電話の市外局番桁数(符号反転値) 実際の収録値[ -2 〜 -5 ] tel_type = 1 area_code_length = link_value * (-1) # 市外局番 桁数決定(先頭の "0" 含む) else: # 携帯電話 等のtel_type値(符号反転値 - 100) 実際の収録値[ -102 〜 -110 ] tel_type = (link_value * (-1)) - 100 break else: # プラス値 idx = link_value # 検索継続(収録値は NextIndex) # TelType に応じた桁区切りを設定する # 固定電話(tel_type=1)では市外局番桁数(area_code_length)に従って設定する # Size1 の値は[先頭'0'含む] result['TelType'] = tel_type if (tel_type == -1): # 電話番号種別が不明(桁数不足で番号翻訳未了) result['ErrId'] = 3 elif (tel_type == 1): # 固定電話 if (area_code_length == 0): # 未使用 局番 result['ErrId'] = 1 elif (area_code_length == 6): # 市内局番なし [ 0ABCDE-FGHJ ] (現在、この地域は存在しない) result['ErrId'] = 0 result['SizeAll'] = 10 result['Size1'] = 6 result['Size2'] = 0 result['Size3'] = 4 else: city_code_length = 6 - area_code_length # 10 - area_code_length - 4(加入者番号) if (len(str_tel_code) < (area_code_length + 1)): # [TelCode]が市内局番の桁位置までないので市内局番適否の判定不可⇒ OK で返す result['ErrId'] = 0 else: # format_telephone から呼ばれる場合は 10桁以上なので必ず判定可能 city_code1 = str_tel_code[area_code_length : (area_code_length + 1)] # 市内局番 1桁目 if (city_code1 == '0' or city_code1 == '1'): result['ErrId'] = 2 # 市内局番1桁目に0/1は割り当てられない else: result['ErrId'] = 0 # OK result['SizeAll'] = 10 result['Size1'] = area_code_length result['Size2'] = city_code_length result['Size3'] = 4 else: # tel_type = 2〜10, size_infoテーブルから桁情報を設定する result['ErrId'] = 0 #/ OK result['SizeAll'] = size_info[tel_type][0] result['Size1'] = size_info[tel_type][1] result['Size2'] = size_info[tel_type][2] result['Size3'] = size_info[tel_type][3] return result