Pythonで西暦から和暦を求める方法

日本には「令和」「平成」「昭和」など複数の元号(年号)があり、年号の変わり目には計算が煩雑になりがちです。

本記事では、Pythonで任意の西暦年または日付を入力すると対応する元号と年(例:令和3年、平成12年、昭和45年など)を自動で返すプログラムを作成します。


プログラム設計のポイント

  1. 元号データの管理
    • 元号名ごとに開始日を datetime 型で保持する。
    • 辞書 gengou_data = {“令和”: datetime(2019,5,1), “平成”: datetime(1989,1,8), “昭和”: datetime(1926,12,25)}
  2. 判定アルゴリズム
    • 入力された日付(YYYY-MM-DD または西暦年のみ)を datetime に変換
    • 開始日の降順ソートで「もっとも最近の元号」から比較し、入力日 >= 開始日の最初のものを採用
    • 年数 = 入力年 – 開始年 + 1。1年目は「元年」と表記
  3. 入力検証
    • 整数以外の西暦年や、日付フォーマットの誤りをキャッチ
    • 元号開始前の日付はエラー扱い

サンプルコード(gengou_converter.py)

from datetime import datetime

def parse_date(date_str):
    """
    YYYY-MM-DD 形式または西暦年(YYYY)を受け取り、
    datetime オブジェクトを返す。
    """
    try:
        if '-' in date_str:
            return datetime.strptime(date_str, "%Y-%m-%d")
        else:
            year = int(date_str)
            return datetime(year, 1, 1)
    except Exception:
        raise ValueError("正しい日付形式(YYYY-MM-DD または YYYY)を入力してください。")

class GengouConverter:
    def __init__(self):
        # 元号名: 開始日
        self.gengou_data = {
            "令和": datetime(2019, 5, 1),
            "平成": datetime(1989, 1, 8),
            "昭和": datetime(1926, 12, 25),
        }

    def convert(self, date_str):
        """
        日付文字列を受け取り、対応する元号表記を返却。
        例: "2021-04-30" -> "令和3年4月30日"
        例: "1990" -> "平成2年1月1日"
        """
        dt = parse_date(date_str)
        # 元号を開始日順に新しいものからソート
        for name, start in sorted(self.gengou_data.items(), key=lambda x: x[1], reverse=True):
            if dt >= start:
                year = dt.year - start.year + 1
                year_str = '元' if year == 1 else str(year)
                # 月日情報がある場合は日付文字列に含める
                return f"{name}{year_str}年{dt.month}月{dt.day}日"
        raise ValueError("対応する元号が見つかりません。")

if __name__ == "__main__":
    converter = GengouConverter()
    date_input = input("西暦(YYYY-MM-DD または YYYY)を入力: ")
    try:
        result = converter.convert(date_input)
        print(result)
    except ValueError as e:
        print(f"エラー: {e}")

コード解説

  1. parse_date 関数
    • ハイフン区切りがあれば YYYY-MM-DD、なければ西暦年のみとみなす
    • フォーマットエラー時は ValueError を発生
  2. GengouConverter クラス
    • 初期化時に gengou_data 辞書を作成
    • convert メソッドでソートしながら適用元号を検索
    • 年数計算後、月日情報を含めた文字列を返却
  3. エラー処理
    • 入力形式、範囲外(元号開始前)などは例外で扱い、メッセージ出力

実行例

$ python gengou_converter.py
西暦(YYYY-MM-DD または YYYY)を入力: 2022-07-15
令和4年7月15日

$ python gengou_converter.py
西暦(YYYY-MM-DD または YYYY)を入力: 1989-01-07
昭和64年1月7日

$ python gengou_converter.py
西暦(YYYY-MM-DD または YYYY)を入力: 1989-01-08
平成元年1月8日

演習問題

以下の演習を通じて、さらに理解を深めましょう。

  1. 演習1: 旧暦(例:明治、大正)を追加し、gengou_data に組み込んでみてください。
  2. 演習2: 出力時に「西暦 → 元号」の変換履歴をリスト形式で返すメソッド history_convert(list_of_dates) を実装してみましょう。
  3. 演習3: GUIアプリ化し、Tkinter や PySimpleGUI を使って日付を入力できる簡易アプリを作成してみましょう。

演習問題の解答例

解答例1(旧暦追加)

辞書に以下を追加
# 明治:1868年1月25日から
"明治": datetime(1868, 1, 25),
# 大正:1912年7月30日から
"大正": datetime(1912, 7, 30),

解答例2(履歴メソッド)

def history_convert(self, date_list):
    results = []
    for d in date_list:
        try:
            results.append(self.convert(d))
        except ValueError:
            results.append("エラー")
    return results

解答例3(Tkinter GUI)

import tkinter as tk
from gengou_converter import GengouConverter

converter = GengouConverter()

root = tk.Tk()
root.title("元号コンバーター")

label = tk.Label(root, text="日付(YYYY-MM-DD または YYYY):")
entry = tk.Entry(root)
button = tk.Button(root, text="変換", command=lambda: result_label.config(text=converter.convert(entry.get())))
result_label = tk.Label(root, text="")

label.pack(); entry.pack(); button.pack(); result_label.pack()
root.mainloop()

まとめ

今回はPythonで「令和・平成・昭和」など複数の元号に対応する汎用的な変換ライブラリを作成しました。

元号データを辞書で管理し、開始日の比較で判定する方法は他の年号やカレンダー対応にも応用できます。

ぜひ演習問題にも取り組み、オリジナルの機能拡張に挑戦してみてください!