同じ日付の数値をコピーしたのに、別のExcelで約四年ずれる場合は、ブックの日付方式を確認します。Excelのシリアル値は基準日からの日数として扱う数値です。基準となる方式が違えば、同じ45000も別の日を表します。
XLSXには1900方式と1904方式があります。数値だけを別ブックへ移す前に、元と先の方式を確かめると、値の意味を取り違えずに済みます。
同じ数値を二つの方式で変換
次は既存帳票を使わず、シリアル値45000を両方式で変換する例です。その後、1904方式の架空ブックへ通常の日付を書き、保存後の方式と値を確認します。
from datetime import datetime
from io import BytesIO
from openpyxl import Workbook, load_workbook
from openpyxl.utils.datetime import (
from_excel, CALENDAR_WINDOWS_1900, CALENDAR_MAC_1904
)
serial = 45000
windows_day = from_excel(serial, epoch=CALENDAR_WINDOWS_1900)
mac_day = from_excel(serial, epoch=CALENDAR_MAC_1904)
print("同じ数値の日差:", (mac_day - windows_day).days)
book = Workbook()
book.epoch = CALENDAR_MAC_1904
book.active["A1"] = datetime(2026, 11, 1)
buffer = BytesIO()
book.save(buffer)
book.close()
check = load_workbook(BytesIO(buffer.getvalue()))
print("保存した方式の基準日:", check.epoch.date())
print("読み戻した日付:", check.active["A1"].value.date())
assert (mac_day - windows_day).days == 1462
assert check.epoch == CALENDAR_MAC_1904
assert check.active["A1"].value == datetime(2026, 11, 1)
check.close()
同じ数値から求めた日付には1462日の差が出ます。一方、日付として新しいブックへ保存した値は、その方式に従って2026-11-01として読み戻せます。Windows・Python 3.12.10・openpyxl 3.1.5で、この例を確認しました。
既存ブックのepochを変更して直すコードではありません。実ファイルではまずload_workbookで開き、book.epochを控えるところから始めます。
数値か日付型かを先に見る
openpyxlはセルの値と表示形式などに従って日付をPythonのdatetimeとして返すことがあります。すでにdatetimeになった値へ、さらにシリアル値用の変換を重ねないようにします。
生の数値を受け取った場合も、それが日付のシリアル値か、単なる件数や商品番号かは数値だけでは決まりません。列の定義と元の表示形式を確認してから変換します。
1462日を一律に足さない
日付のずれにはタイムゾーン、文字列の日月解釈、入力ミスなど別の原因もあります。約四年ずれたからといって、全行へ1462を加算する処理へ進まないでください。
1900方式にはExcelとの互換性のための歴史的な例外もあります。1900年2月29日は実在せず、Pythonのdatetimeでは表せません。古い日付を含む帳票へ、現在の業務日付で試した例をそのまま当てはめないようにします。
確認用のコピーで、基準の分かる日付を数件選びます。元ブックの方式、セルの元値、型、期待する日付を並べて比べると、方式の問題と別の入力不備を分けられます。
読み取りと保存の基本はopenpyxl入門、別ブックへ値を保存する流れはExcel保存の基本で補えます。
参考資料
openpyxlの日時公式資料を2026年11月1日に確認しました。
