PythonでExcelの日付を正しく読み込む手順|文字列や数値になった日付の直し方
PythonでExcelの日付を正しく読み込む手順を、pandasのto_datetimeで日付に直し、直せなかった行を一覧にして確かめる流れで解説します。文字列や数値(シリアル値)になった日付の直し方を、架空のデータで試した結果とあわせて紹介します。
本記事はプロモーションを含みます。紹介する情報は、実際の成果や効果を保証するものではありません。
目次
この記事でわかること
- Excelの日付が、Pythonで文字列や数字として読み込まれる理由
- pandasのto_datetimeで、文字列と数字の日付を日付に直す手順
- 日付にできなかった行を一覧にして確かめる方法
- 架空のデータで試してわかった、つまずきやすいところ
Excelの表をPythonで読み込むと、日付の列が日付にならず、「2026/09/02」のような文字列や「46268」のような数字のまま読み込まれることがあります。そのまま並べ替えたり月ごとに集計したりすると、正しい結果になりません。この記事では、pandasで日付に直し、直せなかった行を確かめてから保存する手順を紹介します。
pandasの使い方は、pandas 3.0.6の公式の資料で確かめた内容です。コードは、架空の注文の一覧で実際に動かして確かめました。
先に結論: 直せなかった行を一覧にしてから保存する
先に結論を書くと、日付の列をいったん元の値のまま読み込み、文字列と数字をそれぞれ日付に直し、直せなかった行を一覧にして確かめてから、別のファイルに保存します。 読み込んだExcelには手を加えません。
| 作業 | 担当 |
|---|---|
| 書式を決める | 人 |
| 日付に直す | Python |
| 直せない行の一覧 | Python |
| 一覧を確かめる | 人 |
Excelの日付が数字になる理由
Microsoftの説明では、Excelは日付を計算に使えるように、連続したシリアル値として持っています。初期の設定では1900年1月1日がシリアル値の1で、2008年1月1日は39448です。セルに日付の表示形式が付いていれば日付に見えますが、表示形式が外れていると数字のまま見えます。
また、手で入力した「2026/09/02」が、日付ではなく文字列としてセルに入っていることもあります。1つの列に、本物の日付・文字列・数字が混ざっていると、pandasはその列を日付にせず、元の値のまま読み込みます。
pandasの公式の資料では、read_excelで標準と違う日付を扱うときは、読み込んだ後にto_datetimeを使うように書かれています。
例にする注文の一覧
この記事では、次のような架空の注文の一覧(orders.xlsx)を例にします。注文番号・注文日・金額の3つの列があり、注文日の列に、いろいろな形の値が混ざっています。
- 本物の日付: セルに日付として入っている値
- 文字列の日付: 「2026/09/02」のように文字で入っている値
- 数字の日付: 46268 のように、シリアル値のまま入っている値
- 日付でない値: 「未定」や、書き方の違う「2026-09-05」、空のセル
手順: 日付に直して、直せなかった行を確かめる
次のコードは、orders.xlsx を読み、注文日の列を日付に直して、直せなかった行を表示します。そのうえで、直した表を orders_dates.xlsx に保存します。orders.xlsx そのものには手を加えない作りです。
# 注文日の列を、文字列と数字(シリアル値)の両方から日付に直す
import pandas as pd
orders = pd.read_excel("orders.xlsx", dtype={"注文日": object})
raw = orders["注文日"]
num = pd.to_numeric(raw, errors="coerce")
text = pd.to_datetime(raw.where(num.isna()), format="%Y/%m/%d",
errors="coerce")
serial = pd.to_datetime(num, unit="D", origin="1899-12-30")
orders["注文日"] = text.fillna(serial)
bad = orders[orders["注文日"].isna() & raw.notna()]
print("日付にできなかった行:", len(bad))
print(bad)
orders.to_excel("orders_dates.xlsx", index=False)
- dtype={"注文日": object}: pandasの資料では、objectを指定すると、Excelに入っている値をそのまま残して読み込むとしています
- to_numeric(..., errors="coerce"): 数字にできるものだけを数字にし、数字にできないものは空(NaN)にします。pandasの資料では、coerceを指定すると、変換できない値はNaNになるとしています
- format="%Y/%m/%d": 文字列の日付の書式です。pandasの資料では、formatは日付を読み取るための書式で、"%d/%m/%Y"のように書くとしています
- errors="coerce"(to_datetime): pandasの資料では、coerceを指定すると、日付にできない値はNaTになるとしています。NaTは、日付が無いことを表す値です
- unit="D", origin="1899-12-30": 数字を、起点の日からの日数として日付に直す指定です。pandasの資料では、originは基準の日付で、数字はその日からのunitの数として扱うとしています
最後の bad は、注文日がNaTになったのに、元の値は空ではなかった行です。つまり、何かが入っていたのに日付にできなかった行です。
架空のデータで試した結果
架空の7行の注文の一覧で試すと、本物の日付2行・文字列の日付1行・数字の日付1行の、あわせて4行が日付になりました。数字の46268は2026年9月3日になりました。日付にできなかった行は2行で、「未定」と、書き方の違う「2026-09-05」でした。空のセルの行は、一覧に入りませんでした。元の orders.xlsx は変わりませんでした。
起点の1899年12月30日が正しいかは、Microsoftの説明にある例で確かめました。このコードの式で、39448は2008年1月1日に、40729は2011年7月5日になり、どちらもMicrosoftの説明と同じでした。検証は作業PCで行い、pandasは3.0.6、openpyxlは3.1.5、Pythonは3.12.10を使いました。
直せなかった行を確かめる
一覧に出た行は、元のExcelを開いて、次のどれに当たるかを確かめます。
- まだ決まっていない: 「未定」のように、日付がまだ無い行です。空のままにするか、決まってから入れます
- 書き方が違う: 「2026-09-05」のように、決めた書式と違う行です。元のExcelで書き方をそろえるか、書式を足して読み直します
- 入力の誤り: 打ち間違いで、ありえない日付になっている行です。元の資料で正しい日付を確かめます
確かめた結果、直す必要があれば、orders_dates.xlsx ではなく元のファイルを直してから、もう一度コードを実行します。
Pythonで直すかの判断
迷ったときは、「同じ形の表を、くり返し読み込むか」で決めます。毎月届く表を読み込むなら、Pythonで直す手順を決めておくと、毎回同じ確かめ方ができます。一度だけで行数も少ないなら、Excelで書き方をそろえるほうが早いこともあります。
Excelの表を毎月まとめて扱うときの選び方は、Excelの複数ファイルを1つにまとめる方法で紹介しています。
つまずきやすいところ
- 数字をそのまま日付にする: to_datetimeに数字をそのまま渡すと、日付になりません。架空のデータで試すと、46268は1970年1月1日の直後の時刻として読まれました。unitとoriginを指定します
- 起点を指定しない: unit="D" だけでoriginを指定しないと、1970年1月1日が起点になります。pandasの資料では、originの初期の設定は1970年1月1日です。架空のデータでも、46268は2096年9月4日になりました
- 日付にできない値で止まる: pandasの資料では、errorsの初期の設定はraiseで、日付にできない値があると例外を出します。架空のデータでも、「未定」が混ざると止まりました
- 日と月の順番: 書式を指定しないと、「01/09/2026」は1月9日として読まれました。dayfirst=True を指定すると9月1日になりました。日が先の書き方の表では、formatで書式を決めます
- 書式を推測させる: pandasの資料では、format="mixed" は値ごとに書式を推測する指定で、危うさがあるとしています。書式はできるだけ決めて指定します
- 1904年の日付システム: Microsoftの説明では、古いMac版のExcelでは1904年1月1日を起点にする日付システムが使われていて、2つの差は1,462日です。直した日付が4年ほどずれていたら、日付システムを確かめます
まとめ
- Excelの日付は、文字列やシリアル値の数字のまま読み込まれることがあります
- 日付の列は元の値のまま読み込み、文字列はformat、数字はunitとoriginを指定して日付に直します
- errors="coerce" で日付にできない値をNaTにし、直せなかった行を一覧にして確かめます
- 直した表は別のファイルに保存し、元のファイルは書き換えません
同じ表の中の重複を確かめる手順はPythonでExcelの重複データを見つける手順、件数と合計を出す手順はPythonでCSVを集計する手順で紹介しています。
よくある質問
Excelの日付が、Pythonで46268のような数字になるのはなぜですか?
Excelは日付を連続したシリアル値という数字で持っているためです。Microsoftの説明では、初期の設定では1900年1月1日がシリアル値の1です。数字のまま読み込まれたときは、日付に直す必要があります。
日付にできない値があると、エラーで止まりますか?
pandasのto_datetimeは、初期の設定では、日付にできない値があると例外を出して止まります。errors="coerce" を指定すると、その値はNaTになり、あとで一覧にして確かめられます。
「01/09/2026」は、1月9日と9月1日のどちらとして読まれますか?
書式を指定しないと、月が先として1月9日と読まれました(架空のデータで確かめた結果)。日が先の書き方のときは、formatで書式を指定するか、dayfirstを指定します。
元のExcelのファイルは書き換わりますか?
この記事のコードは、直した表を別のファイル(orders_dates.xlsx)に保存し、元のorders.xlsxには手を加えません。架空のデータで試したときも、元のファイルは変わりませんでした。
Macで作ったExcelのファイルでも、同じ方法でよいですか?
古いMac版のExcelでは、1904年を起点にする日付システムが使われていることがあります。Microsoftの説明では、2つの日付システムの差は1,462日です。直した日付が4年ほどずれていたら、日付システムを確かめます。