2
0

More than 1 year has passed since last update.

【備忘録】Javaで日付時刻を文字列に変換

Posted at

初めに

2021年現在でも「Java 日付 文字列」などで検索するといまだにDateSimpleDateFormatが上位に出てくるので、java.time時代の参照すべきドキュメントと概要を備忘録として残す。

検証はOpenJDK11を使用していており、Oracleドキュメントのリンク先はJava17になっているが、基本的にはJava8から使えるはず。

日時オブジェクト

本記事ではJava8から導入されたjava.timeパッケージのオブジェクトで日時を保持する。

LocalDateTime now = LocalDateTime.now(); // 現在日時
LocalDateTime ldt = LocalDateTime.of(2021, 12, 10, 20, 30, 0); // 指定した日時

文字列に変換

toString

日時オブジェクトのtoStringメソッドを使用するとISO-8601暦体系になる。

LocalDateTime ldt1 = LocalDateTime.of(1999, 1, 1, 0, 0, 0);
System.out.println(ldt1); // -> "1999-01-01T00:00" ※秒が0の場合は省略される

LocalDateTime ldt2 = LocalDateTime.of(2021, 12, 31, 23, 59, 59);
System.out.println(ldt2); // -> "2021-12-31T23:59:59"

LocalDateTime ldt3 = LocalDateTime.of(2021, 12, 31, 23, 59, 59, 1200);
// 7つ目の引数はナノ秒
System.out.println(ldt3); // -> "2021-12-31T23:59:59.000001200"

DateTimeFormatter

または、Java11の日本語ドキュメントJava8の日本語ドキュメント

従来のSimpleDateFormatライクな指定をしたい場合はDateTimeFormatterを使用する。
SimpleDateFormat同様シンボル文字を表示桁数分重ねる形式をとる。

DateTimeFormatter year2fmtr = DateTimeFormatter.ofPattern("yy");
System.out.println(ldt1.format(year2fmtr)); // -> "99"
System.out.println(ldt2.format(year2fmtr)); // -> "21"

DateTimeFormatter year4fmtr = DateTimeFormatter.ofPattern("yyyy");
System.out.println(ldt1.format(year4fmtr)); // -> "1999"
System.out.println(ldt2.format(year4fmtr)); // -> "2021"

// DateTimeFormatterでは月は大文字でM
DateTimeFormatter month1fmtr = DateTimeFormatter.ofPattern("M");
System.out.println(ldt1.format(month1fmtr)); // -> "1"
System.out.println(ldt2.format(month1fmtr)); // -> "12"

DateTimeFormatter month2fmtr = DateTimeFormatter.ofPattern("MM");
System.out.println(ldt1.format(month2fmtr)); // -> "01"
System.out.println(ldt2.format(month2fmtr)); // -> "12"

// ※実行環境のロケールは日本
DateTimeFormatter month3fmtr = DateTimeFormatter.ofPattern("MMM");
System.out.println(ldt1.format(month3fmtr)); // -> "1月"
System.out.println(ldt2.format(month3fmtr)); // -> "12月"

事前定義されているフォーマッタを使用することも可能。

System.out.println(ldt2.format(DateTimeFormatter.ISO_DATE)); // -> "2021-12-31"

String.format

または、Java11の日本語ドキュメントJava8の日本語ドキュメント

String.formatの日付にはTemporalAccessorに適用することが可能。

// Formatterでは月は小文字でm
// "m","d"一文字で2桁表示を示す
System.out.println(String.format("test_%1$tY-%1$tm-%1$td.log", ldt2)); // -> "test_2021-12-31.log"

書式はDateTimeFormatterより複雑で%<インデックス>$t<パターン>で1セット。
オブジェクトと値をはめ込む位置が1:1の場合はとインデックス部分(<インデックス>$)は不要だが、大抵は1つの日時オブジェクトに対して年・月など2つ以上の位置にはめ込むので実質的にほぼ必須。

// OK
System.out.println(String.format("test_%tY.log", ldt2)); // -> "test_2021.log"
// NG
System.out.println(String.format("test_%tY-%tm-%td.log", ldt2));
// -> java.util.MissingFormatArgumentException: Format specifier '%tm'

注意点

String.formatは一般的に計算コストが高いので性能にシビアな環境や大量にループする中で使う場合は要注意。
※Java17で幾分改善されたらしい。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0