ホーム › 日付・時刻 › D-10: 複数フォーマットの日付解析
D-10: 複数フォーマットの日付解析
外部システムや手入力で受け取る日付文字列は、フォーマットが統一されていないことがよくあります。 このページでは ISO 形式・スラッシュ区切り・8桁数字・英語表記・和暦など、複数のフォーマットをまとめて解析するパターンを解説します。
対応する日付フォーマット
| 入力例 | フォーマット | 用途 |
|---|---|---|
| 2024-04-01 | ISO_LOCAL_DATE(yyyy-MM-dd) | 標準的なAPI・DBのデータ |
| 2024/04/01 | yyyy/MM/dd | 日本のシステムや手入力 |
| 20240401 | yyyyMMdd | バッチ・ファイル名によく使われる |
| Apr 1, 2024 | MMM d, yyyy(英語) | 英語圏のドキュメント・API |
| 令和6年4月1日 | GGGGy年M月d日(和暦) | 官公庁書類・レガシーシステム |
すべて同じ日付(2024年4月1日)を表しています。どのフォーマットが来ても LocalDate に変換できるメソッドを実装します。
サンプルコード
よくあるミス・注意点
⚠️ 和暦のパースには Chronology と Locale の両方が必要
「令和6年4月1日」を解析するには withChronology(JapaneseChronology.INSTANCE) と withLocale(Locale.JAPANESE) の両方を設定する必要があります。 片方だけだと「令」が認識されずに解析が失敗します。
// NG: Locale だけでは「令和」が認識されない
DateTimeFormatter.ofPattern("GGGGy年M月d日")
.withLocale(Locale.JAPANESE); // Chronology が抜けている
// OK: withChronology と withLocale の両方を設定する
DateTimeFormatter.ofPattern("GGGGy年M月d日")
.withChronology(JapaneseChronology.INSTANCE)
.withLocale(Locale.JAPANESE);📌 フォーマットの試行順序を意識する
例えば yyyyMMdd を yyyy/MM/dd より前に試すと、 数字8桁は両方にマッチする可能性があります。 より具体的(一致しにくい)なフォーマットを先に試し、曖昧なものは後回しにしましょう。
📌 DateTimeFormatter は再利用可能・スレッドセーフ
DateTimeFormatter は SimpleDateFormat と異なりスレッドセーフです。 static final で定数として定義して使い回せます。 フォーマットの一覧リストも static final にするのがベストプラクティスです。
テストする観点
- 5種類のフォーマットがそれぞれ同じ日付(例: 2024-04-01)に解析されるか
- 和暦の元号をまたぐ日付(2019-04-30 = 平成31年4月30日、2019-05-01 = 令和元年5月1日)が正しく解析されるか
- うるう年(2024-02-29)が正しく解析されるか
- サポート外のフォーマット(例: "01/04/2024")で
IllegalArgumentExceptionがスローされるか - 空文字列・null が渡されたときにどのような例外が発生するか