1. DateTimeFormatter: 何で、何のために使うのか
実際のプログラムでは、日付はコードの中だけで完結することはほとんどありません。通常は次のことが必要になります:
- 文字列に変換してコンソール、画面、またはファイルに出力する(例: "01.06.2025 14:30")。
- 文字列をパースし、ユーザーが入力したりファイルから来た文字列を日付/時刻オブジェクトに戻す。
そのために Java には強力で使いやすいツール — クラス java.time.format.DateTimeFormatter があります。
DateTimeFormatter は、時間のオブジェクト(LocalDate、LocalDateTime、ZonedDateTime、Instant など)と文字列の間の「翻訳者」だと言えます。できること:
- 日付/時刻オブジェクトを、必要な形式の文字列に変換する(format — フォーマット)。
- 文字列を、日付/時刻オブジェクトに変換する(parse — パース)。
2. 標準フォーマッタ: 手早く簡単に
Java には、最も一般的な ISO 形式(日時の国際標準)をカバーする標準フォーマッタのセットが用意されています。
代表的なものは次のとおりです:
| フォーマッタ | 文字列の例 | 説明 |
|---|---|---|
|
2025-06-01 | 日付のみ(年-月-日) |
|
14:30:00 | 時刻のみ(時:分:秒) |
|
2025-06-01T14:30:00 | タイムゾーンなしの日時 |
|
2025-06-01T14:30:00+03:00[Europe/Minsk] | 日付・時刻・タイムゾーン |
標準フォーマッタの使用例
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class FormatterDemo {
public static void main(String[] args) {
LocalDate date = LocalDate.now();
// 日付を文字列にフォーマット
String text = date.format(DateTimeFormatter.ISO_LOCAL_DATE);
System.out.println(text); // 例: 2025-06-01
// 文字列を日付にパース
LocalDate parsed = LocalDate.parse("2025-06-01", DateTimeFormatter.ISO_LOCAL_DATE);
System.out.println(parsed); // 2025-06-01
}
}
たとえ話
もし Java がコーヒー店なら、標準フォーマッタは「アメリカーノ」「ラテ」「エスプレッソ」のようなもの。速くて標準的ですが、ときには特別な一杯が欲しくなります!
3. カスタムパターン: DateTimeFormatter.ofPattern
標準形式では足りないことがあります。たとえば "01.06.2025 14:30" のように出力したくて、"2025-06-01T14:30:00" では困る場合です。そのときは、メソッド DateTimeFormatter.ofPattern(String pattern) で自分のパターンを作成できます。
パターンの構文
パターンでは次の文字を使います:
- y — 年(yyyy — 2025)
- M — 月(MM — 06)
- d — 日(dd — 01)
- H — 時(24 時間形式、HH — 14)
- m — 分(mm — 30)
- s — 秒(ss — 00)
パターン例
| パターン | 結果例 |
|---|---|
|
01.06.2025 |
|
2025/06/01 |
|
01.06.2025 14:30 |
|
2025-06-01 14:30:00 |
|
1 iyunya 2025(ロシア語ロケールの場合) |
例: 日付と時刻のフォーマット
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class CustomFormatDemo {
public static void main(String[] args) {
LocalDateTime dt = LocalDateTime.of(2025, 6, 1, 14, 30);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
String text = dt.format(formatter);
System.out.println(text); // 01.06.2025 14:30
}
}
例: 文字列を日付にパース
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class ParseDemo {
public static void main(String[] args) {
String input = "01.06.2025 14:30";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
LocalDateTime dt = LocalDateTime.parse(input, formatter);
System.out.println(dt); // 2025-06-01T14:30
}
}
注意: パターンは文字列と完全に一致していなければなりません。文字列に秒が含まれるなら、パターンに :ss を追加してください。
4. フォーマット: 日付/時刻を文字列にする
全体の流れ
- 必要なオブジェクト(LocalDate、LocalDateTime、ZonedDateTime など)を作成する。
- フォーマッタを作成または選択する。
- オブジェクトで format(DateTimeFormatter) を呼び、文字列を得る。
例: 日付をさまざまな形式で出力
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class MultiFormatDemo {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, 6, 1);
// 標準のISO
System.out.println(date.format(DateTimeFormatter.ISO_LOCAL_DATE)); // 2025-06-01
// カスタム形式
DateTimeFormatter rusFormat = DateTimeFormatter.ofPattern("dd.MM.yyyy");
System.out.println(date.format(rusFormat)); // 01.06.2025
// 英語スタイル
DateTimeFormatter usFormat = DateTimeFormatter.ofPattern("MM/dd/yyyy");
System.out.println(date.format(usFormat)); // 06/01/2025
}
}
時刻のフォーマット
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
public class TimeFormatDemo {
public static void main(String[] args) {
LocalTime time = LocalTime.of(14, 30, 5);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
System.out.println(time.format(formatter)); // 14:30:05
}
}
5. パース: 文字列を日付/時刻にする
全体の流れ
- 文字列を取得する(例: ユーザーから)。
- 文字列と同じパターンでフォーマッタを作る。
- 静的メソッド parse() またはフォーマッタの parse() を呼ぶ。
例: 日付のパース
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class ParseDateDemo {
public static void main(String[] args) {
String input = "01.06.2025";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
LocalDate date = LocalDate.parse(input, formatter);
System.out.println(date); // 2025-06-01
}
}
例: 日付と時刻のパース
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class ParseDateTimeDemo {
public static void main(String[] args) {
String input = "01.06.2025 14:30";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
LocalDateTime dateTime = LocalDateTime.parse(input, formatter);
System.out.println(dateTime); // 2025-06-01T14:30
}
}
6. パースエラーの処理
パースは曲者です。文字列がパターンに合わないと、Java は例外 DateTimeParseException をスローします。これは、たとえばユーザーが誤った日付を入力したときなどに普通に起こり得ます。
例: パース時のエラー処理
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
public class ParseErrorDemo {
public static void main(String[] args) {
String input = "32.13.2025"; // 不正な日付
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
try {
LocalDate date = LocalDate.parse(input, formatter);
System.out.println(date);
} catch (DateTimeParseException ex) {
System.out.println("パースエラー: " + ex.getMessage());
}
}
}
重要: ユーザー入力を扱う場合は、必ずこの種のエラーを処理しましょう!
7. 実践: ユーザー向けに日付を変換する
たとえば学習用アプリで、ユーザーが "dd.MM.yyyy" 形式で誕生日を入力し、プログラムは "yyyy/MM/dd" 形式と曜日を表示する、という課題があるとします.
例
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Scanner;
public class BirthdayFormatDemo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("生年月日を入力してください (dd.MM.yyyy): ");
String input = scanner.nextLine();
DateTimeFormatter inputFormat = DateTimeFormatter.ofPattern("dd.MM.yyyy");
DateTimeFormatter outputFormat = DateTimeFormatter.ofPattern("yyyy/MM/dd");
try {
LocalDate birthday = LocalDate.parse(input, inputFormat);
String formatted = birthday.format(outputFormat);
System.out.println("変換後の日付: " + formatted);
System.out.println("曜日: " + birthday.getDayOfWeek()); // 例: SATURDAY
} catch (DateTimeParseException ex) {
System.out.println("エラー: 日付の形式が正しくありません!");
}
}
}
8. ローカライズ: 言語がフォーマットに与える影響
DateTimeFormatter を使うと、数字の並びを変えるだけでなく、月名や曜日なども出力できます。その際、ロケール(言語と地域)が考慮されます。
例: ロシア語で月名を表示
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class LocaleDemo {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, 6, 1);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d MMMM yyyy", new Locale("ru"));
System.out.println(date.format(formatter)); // 1 iyunya 2025
}
}
例: 英語ロケール
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class LocaleEnDemo {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, 6, 1);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d MMMM yyyy", Locale.ENGLISH);
System.out.println(date.format(formatter)); // 1 June 2025
}
}
コツ: 月名や曜日を特定の言語で表示したい場合は、ロケールを明示的に指定しましょう!
9. 日付のフォーマットとパースでよくあるミス
エラー 1: パターンと文字列の不一致。
文字列が "01.06.2025 14:30" なのに、パターンが "dd.MM.yyyy" の場合、パースは失敗します。パターンは文字列と正確に一致させてください。
エラー 2: パターン記号の取り違え。
MM は月、mm は分です。もし "dd.mm.yyyy" と書くと、Java は分を意味すると解釈してエラーになります。月には常に大文字の M を使いましょう。
エラー 3: パース時の例外を未処理のままにする。
DateTimeParseException を捕捉しないと、ユーザーの誤入力でプログラムが突然終了する可能性があります。必ずこの種のエラーを処理してください。
エラー 4: 文字の月名などを使うのにロケールを指定しない。
月名を文字で出すパターン(MMMM)などを使うのにロケールを指定しないと、Java は既定の言語(例: 英語)を使う場合があります。必要なロケールを明示的に設定しましょう。
エラー 5: 古いクラス(SimpleDateFormat、Date)を新しいプロジェクトで使う。
覚えておきましょう: 現代的なコードでは java.time と DateTimeFormatter を使います。
GO TO FULL VERSION