10.

Javaエラー: Unparseable date

編集
この記事の要点
  • java.text.ParseException: Unparseable dateSimpleDateFormat のパターンと入力文字列が一致しないとき発生
  • 原因 ①: パターン記号のミス(YYYYyyyymmMM など)
  • 原因 ②: 入力に余計な空白・改行・タイムゾーンが含まれる
  • 原因 ③: ロケール依存(曜日 / 月の言語)
  • Java 8+ は SimpleDateFormat より DateTimeFormatter 推奨

 

エラーの状況

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
Date d = sdf.parse("2026/05/15");  // パターンとフォーマットが不一致
// → java.text.ParseException: Unparseable date: "2026/05/15"

SimpleDateFormat はパターン(yyyy-MM-dd)に厳密に従って文字列をパースします。入力文字列がパターンに合わないと ParseException

パターン記号の落とし穴

記号意味よくあるミス
yyyy年(4 桁)YYYY は week-year(ISO 週ベース、年末年始でずれる)
MM月(数字 01-12)mm は分
ddDD は年間通日(1-366)
HH時(24h 00-23)hh は 12h(00-11)
mmMM は月
ssSS はミリ秒(実は SSS が標準)
SSSミリ秒3 桁固定
aAM/PMロケール依存
zタイムゾーン名JST
Zタイムゾーンオフセット+0900

原因と対処

原因 1: パターンと入力フォーマットが一致しない

// 間違い: パターンは - 区切りなのに入力は / 区切り
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
sdf.parse("2026/05/15");  // 失敗

// 修正
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
sdf.parse("2026/05/15");  // 成功

原因 2: 入力に余分な文字(空白・改行・タブ)

String input = " 2026-05-15 \n";
sdf.parse(input);  // 失敗

// 修正
sdf.parse(input.trim());

原因 3: タイムゾーンや AM/PM が含まれる

// 入力: "2026-05-15 14:30:00 JST"
// パターン: "yyyy-MM-dd HH:mm:ss"  → JST 部分でエラー

// 修正
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
sdf.parse("2026-05-15 14:30:00 JST");

原因 4: ロケール依存(英語 vs 日本語の曜日・月名)

// 入力: "May 15, 2026" を日本語環境でパース → 失敗
SimpleDateFormat sdf = new SimpleDateFormat("MMM dd, yyyy");
sdf.parse("May 15, 2026");  // 日本ロケールだと「5月」を期待してしまう

// 修正: ロケールを明示
SimpleDateFormat sdf = new SimpleDateFormat("MMM dd, yyyy", Locale.ENGLISH);
sdf.parse("May 15, 2026");  // 成功

原因 5: 厳密モード(lenient)の罠

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
sdf.parse("2026-13-99");  // デフォルトでは lenient = true なので、自動補正してパース成功
// 「13 月 99 日」→「2027-04-08」相当に解釈されてしまう

// 厳密モードに
sdf.setLenient(false);
sdf.parse("2026-13-99");  // ParseException

Java 8 以降は DateTimeFormatter を使う(推奨)

SimpleDateFormatスレッドセーフではないなどの問題があり、Java 8+ では java.time.format.DateTimeFormatter が推奨です。

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
try {
    LocalDate date = LocalDate.parse("2026-05-15", formatter);
    System.out.println(date);
} catch (DateTimeParseException e) {
    System.err.println("パース失敗: " + e.getMessage());
}

// ISO 形式 (yyyy-MM-dd) なら formatter 不要
LocalDate date = LocalDate.parse("2026-05-15");

// 日時の場合
LocalDateTime dt = LocalDateTime.parse("2026-05-15T14:30:00");

// タイムゾーン付き
ZonedDateTime zdt = ZonedDateTime.parse("2026-05-15T14:30:00+09:00[Asia/Tokyo]");

SimpleDateFormat vs DateTimeFormatter 比較

項目SimpleDateFormatDateTimeFormatter
スレッドセーフ× 不可○ イミュータブル
パッケージjava.textjava.time.format
パース例外ParseException (checked)DateTimeParseException (unchecked)
タイムゾーン面倒明確
不変オブジェクト×
推奨度レガシー○ Java 8+

関連記事

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. java.lang.NoSuchMethodError
  2. java.lang.ClassCastException: java.util.Date cannot be cast to java.sql.Date
  3. java.lang.UnsupportedClassVersionError
  4. version less than X.X is not supported.
  5. パッケージ~は存在しません
  6. org.apache.jasper.JasperException: ...The jsp:param action must not be...
  7. java.io.FileNotFoundException: ファイル名 (許可がありません)
  8. java.sql.SQLException: Cannot convert value 'YYYY-MM-DD ...' from column n(YYYY-MM-DD ...) to TIMESTAMP.
  9. 警告: この文字は、エンコーディング[文字コード]にマップできません
  10. java.text.ParseException: Unparseable date
  11. Unsupported major.minor version 52.0
  12. エンティティ" ... "への参照は';'デリミタで終了する必要があります。
  13. java.math.BigDecimal cannot be cast to java.lang.String