119 lines
3.7 KiB
Python
119 lines
3.7 KiB
Python
# utils/name_splitter.py
|
||
from typing import Tuple
|
||
|
||
class NameSplitter:
|
||
"""
|
||
日本語の氏名を扱うユーティリティクラス
|
||
"""
|
||
|
||
def split_full_name(self, full_name: str) -> Tuple[str, str]:
|
||
"""
|
||
フルネームを姓と名に分割する
|
||
|
||
Args:
|
||
full_name: 分割する氏名(例: '山田 太郎' or '山田 太郎' or 'Yamada Taro')
|
||
|
||
Returns:
|
||
(姓, 名)のタプル。分割できない場合は(フルネーム, '')を返す
|
||
"""
|
||
if not full_name:
|
||
return ('', '')
|
||
|
||
try:
|
||
# 空白文字で分割(半角スペース、全角スペース、タブなど)
|
||
parts = full_name.replace(' ', ' ').split()
|
||
|
||
if len(parts) >= 2:
|
||
last_name = parts[0]
|
||
first_name = ' '.join(parts[1:]) # 名が複数単語の場合に対応
|
||
return (last_name.strip(), first_name.strip())
|
||
else:
|
||
# 分割できない場合は全体を姓とする
|
||
return (full_name.strip(), '')
|
||
|
||
except Exception:
|
||
return (full_name.strip(), '')
|
||
|
||
def join_name(self, last_name: str, first_name: str, format_type: str = 'ja') -> str:
|
||
"""
|
||
姓と名を結合して一つの文字列にする
|
||
|
||
Args:
|
||
last_name: 姓
|
||
first_name: 名
|
||
format_type: 出力形式 ('ja': 日本語形式, 'en': 英語形式)
|
||
|
||
Returns:
|
||
結合された氏名文字列
|
||
"""
|
||
last_name = last_name.strip()
|
||
first_name = first_name.strip()
|
||
|
||
if not last_name and not first_name:
|
||
return ''
|
||
|
||
if not first_name:
|
||
return last_name
|
||
|
||
if not last_name:
|
||
return first_name
|
||
|
||
if format_type == 'ja':
|
||
return f"{last_name} {first_name}" # 全角スペース
|
||
elif format_type == 'en':
|
||
return f"{first_name} {last_name}" # 英語形式:名 姓
|
||
else:
|
||
return f"{last_name} {first_name}" # デフォルト:半角スペース
|
||
|
||
def normalize_name(self, name: str) -> str:
|
||
"""
|
||
名前の正規化を行う
|
||
|
||
Args:
|
||
name: 正規化する名前文字列
|
||
|
||
Returns:
|
||
正規化された名前文字列
|
||
"""
|
||
if not name:
|
||
return ''
|
||
|
||
# 空白文字の正規化
|
||
name = ' '.join(name.split()) # 連続する空白を単一の半角スペースに
|
||
|
||
# 全角英数字を半角に変換
|
||
name = name.translate(str.maketrans({
|
||
' ': ' ', # 全角スペースを半角に
|
||
'.': '.',
|
||
',': ',',
|
||
'!': '!',
|
||
'?': '?',
|
||
':': ':',
|
||
';': ';',
|
||
}))
|
||
|
||
return name.strip()
|
||
|
||
def is_valid_name(self, name: str) -> bool:
|
||
"""
|
||
名前が有効かどうかをチェックする
|
||
|
||
Args:
|
||
name: チェックする名前文字列
|
||
|
||
Returns:
|
||
名前が有効な場合はTrue、そうでない場合はFalse
|
||
"""
|
||
if not name or not name.strip():
|
||
return False
|
||
|
||
# 最小文字数チェック
|
||
if len(name.strip()) < 2:
|
||
return False
|
||
|
||
# 記号のチェック(一般的でない記号が含まれていないか)
|
||
invalid_chars = set('!@#$%^&*()_+=<>?/\\|~`')
|
||
if any(char in invalid_chars for char in name):
|
||
return False
|
||
|
||
return True |