Excelの日付が「46317」のような数字になる理由と、ほかのツールに渡すときに日付を壊さない方法

Excelの日付が急に数字で表示されたり、別のファイルにコピーしたら4年ずれたりするのは、日付の正体が「シリアル値」という数値だからです。Microsoftの公式ドキュメントをもとに、仕組みと、CSVやPythonに渡すときの注意点を整理しました。
この記事が答える問い
Excelで管理している売上表や顧客リストを、別のツールに取り込んだり、プログラムで読み込んだりしたとき、日付の列が「46317」のような数字になってしまうことがあります。別のブックにコピーしたら、日付がちょうど4年ずれていた、という相談もよく聞きます。
どちらも、Excelの日付の正体を知っていれば原因が分かります。この記事では、Microsoftの公式ドキュメントをもとに仕組みを整理し、ほかのツールに日付を渡すときに壊さない方法をまとめます。
結論
- Excelの日付は、内部では**「シリアル値」という数値**で記録されている。日付に見えるのは表示形式のおかげ
- 日付が4年(正確には1,462日)ずれるのは、1900年日付システムと1904年日付システムが混ざったとき
- プログラムでシリアル値を日付に戻すときは、1899年12月30日を起点にすると、1900年3月1日以降の日付が正しく変換できる
- ほかのツールに渡すときは、「YYYY-MM-DD」の文字列にしておくのがいちばん安全
Excelの日付の正体は「シリアル値」
Microsoftのドキュメントによると、Excelに日付を入力すると、日付は**開始日から経過した日数を表す数値(シリアル値)**に変換されます。たとえば「2011年7月5日」は、シリアル値40729として記録されます。
画面に「2011/7/5」と表示されるのは、セルに日付の表示形式が付いているからです。表示形式が外れたり、表示形式の情報を持たないツールに値だけが渡されたりすると、中身の数値がそのまま見えます。記事タイトルの「46317」は、この記事を書いた2026年10月22日のシリアル値です。
時刻も同じ仕組みです。TIMEVALUE関数の説明では、時刻は0から0.99988426までの小数で表され、0:00:00から23:59:59までを表すとされています。つまり「46317.5」は、2026年10月22日の12時です。
日付が4年ずれる理由:2つの日付システム
Excelには、1900年日付システムと1904年日付システムの2つがあります。
| 日付システム | 開始日 | 2011年7月5日のシリアル値 |
|---|---|---|
| 1900年日付システム | 1900年1月1日 | 40729 |
| 1904年日付システム | 1904年1月1日 | 39267 |
ドキュメントでは、新しいバージョンのExcelはすべて1900年日付システムで日付を計算し、古いバージョンのExcel for Macでは1904年日付システムが使われていたと説明されています。2つの差は**1,462日(4年と1日)**です。
同じ数値でも、どちらのシステムで読むかで日付が4年と1日ずれます。古いMacで作られたブックのデータを扱うときや、日付が「ちょうど4年ずれている」ときは、まずこの設定を疑います。設定は、Windows版ではブックごとに[ファイル]→[オプション]→[詳細設定]の「1904年日付システムを使用する」で確認できます。
なお、ドキュメントでは、別のブックへ日付をコピーするときは通常は自動で変換される一方、グラフの一部としてコピーされた日付は変換されず、約4年ずれるため手動で直す必要がある、とも書かれています。
なぜ起点が「1899年12月30日」なのか
1900年日付システムの開始日は1900年1月1日なので、起点は1899年12月31日のように思えます。ところが、プログラムで変換するときは1899年12月30日を起点にするのが一般的です。
理由は、Excelが1900年を閏年として扱っているためです。Microsoftのドキュメントによると、これは当時の表計算ソフトLotus 1-2-3との互換性のためで、実際には存在しない1900年2月29日がExcelには存在します。そのぶん、1900年3月1日以降の日付は1日ずれているため、起点を1日前に置くと計算が合います。
実際に、Pythonで1899年12月30日に40729日を足すと、ドキュメントの例と同じ2011年7月5日になります。
from datetime import datetime, timedelta
def excel_serial_to_datetime(serial: float) -> datetime:
# 1900年日付システム、1900年3月1日以降の日付が前提
return datetime(1899, 12, 30) + timedelta(days=serial)
print(excel_serial_to_datetime(40729)) # 2011-07-05 00:00:00
print(excel_serial_to_datetime(46317.5)) # 2026-10-22 12:00:00
pandasを使う場合は、to_datetime の unit と origin を指定します。
import pandas as pd
pd.to_datetime([40729, 46317.5], unit="D", origin="1899-12-30")
# DatetimeIndex(['2011-07-05 00:00:00', '2026-10-22 12:00:00'], ...)
どちらのコードも、手元で実行して結果を確認しています。1904年日付システムのブックから来た値なら、起点を1904年1月1日にする必要があります。
ほかのツールに日付を渡すときのルール
シリアル値は、Excelの中では便利ですが、ほかのツールとの受け渡しでは誤解のもとになります。受け渡しのルールとして、次の点を決めておくと安全です。
- 日付は「YYYY-MM-DD」の文字列で渡す:数値のまま渡すと、受け取る側が起点や日付システムを知っている必要がある
- 時刻が必要なら「YYYY-MM-DD HH:MM:SS」で、タイムゾーンも決める:小数部分の時刻は、見た目では気づきにくい
- 受け取ったデータに5桁の数字の日付があったら、シリアル値を疑う:4万台の数字なら、2009年〜2036年ごろの日付の可能性が高い
- 日付が4年ずれていたら、1904年日付システムを疑う
Excel側で文字列にするなら、TEXT関数で =TEXT(A2,"yyyy-mm-dd") のように表示形式を指定して変換できます。
チェックリスト
- 日付の列に、5桁の数字が混ざっていないか
- 日付が4年ずれていないか(1904年日付システムのブックが混ざっていないか)
- プログラムで変換するとき、起点を1899年12月30日にしているか
- 時刻を含む値の小数部分を、切り捨てていないか
- 受け渡しの形式を「YYYY-MM-DD」の文字列に決めているか
まとめ
Excelの日付が数字になるのは、壊れたのではなく、中身のシリアル値が見えているだけです。日付が4年ずれるのも、日付システムの違いという理由があります。
仕組みが分かれば、対処は難しくありません。Excelの中ではシリアル値、外に出すときは「YYYY-MM-DD」の文字列。この切り替えを受け渡しのルールとして決めておくと、日付のトラブルはほとんど防げます。
参考資料

Kwangmo Yang
Freelance Developer & Translator · Based in Osaka, Japan
大阪を拠点に、AI業務自動化、Web・ツール開発、日韓の言語サービスを手がけています。
プロフィールを見る

