SimpleDateFormatとDateTimeFormatterの違いってなんだ??

SimpleDateFormatとDateTimeFormatterの違いってなんだ??

自分がこの前書いた記事で、SimpleDateFormatとDateTimeFormatterを使用した。
どちらも日付時刻フォーマッターで、一体何が違うのか把握できていなかったので、調べてみた。

インスタンス生成の違い

newするか、用意されているメソッドを使用するかの違いがある。

SimpleDateFormatの場合

SimpleDateFormatのインスタンス生成は、newして生成する。
スレッドセーフではない。
そのため、マルチスレッド処理の場合、使用する直前で毎回インスタンスを生成することが必要。

SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");

DateTimeFormatterの場合

DateTimeFormatterのインスタンス生成は、ofPatternメソッドで生成する。
スレッドセーフ。
SimpleDateFormatと違って、マルチスレッド処理のとき、使うたびにインスタンスを生成するということが必要ない。

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss.SSS");

parse(解析)

StringをSimpleDateFormatとDateTimeFormatterを使って変換してみる。

SimpleDateFormatの場合

String → Dateに変換する処理。
parseメソッドにString型を引数として渡すのみ。
ParseExceptionの例外処理が必要だけど、下の例では省略。

SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
Date date = sdf.parse("2018/05/14 12:34:56.123");
// Mon May 14 12:34:56 UTC 2018
System.out.println(date);

DateTimeFormatterの場合

String → TemporalAccessorに変換する処理。

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss.SSS");
TemporalAccessor ta = dtf.parse("2018/05/14 12:34:56.123");
// {},ISO resolved to 2018-05-14T12:34:56.123
System.out.println(ta);

TemporalAccessorってなに…?ってなった。出力結果も"ISO resolved to ~~"とかついている。
LocalDateTimeの親インターフェースらしい。他にもLocalDate, LocalTime, ZonedDateTimeの親にあたる。
なので、こんなことが可能。
※ 自分で書いておいて「だからなに…?」ってなっていますが、備忘録として記載。

TemporalAccessor tAccessor = LocalDateTime.of(2018, 5, 14, 12, 34, 56);

DateTimeFommaterでparseする場合、LocalDateTimeのparseメソッドが使用されているパターンが多いと思われる。
下のようになる。こちらのほうが使用頻度高そうなので覚えておきたい。
(String → LocalDateTimeに変換する処理。)

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss.SSS");
LocalDateTime date = LocalDateTime.parse("2018/05/14 12:34:56.123", dtf);
// 2018-05-14T12:34:56.123
System.out.println(date);

format(整形)

SimpleDateFormatとDateTimeFormatterをその名の通りフォーマットしてみる。

SimpleDateFormatの場合

Date→Stringに変換する処理。
formatメソッドにjava.util.Date型を引数として渡す。

SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS");
Date date = sdf.parse("2018/05/14 12:34:56.123");
// Mon May 14 12:34:56 UTC 2018
System.out.println(date);

String str = sdf.format(date);
// 2018/05/14 12:34:56.123
System.out.println(str);

DateTimeFormatterの場合

formatメソッドにTemporalAccessorを引数として渡す。

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss.SSS");
LocalDateTime date = LocalDateTime.parse("2018/05/14 12:34:56.123", dtf);
// 2018-05-14T12:34:56.123
System.out.println(date);

String str = dtf.format(date);
// 2018/05/14 12:34:56.123
System.out.println(str);

まとめ

だらだらと書いてしまったが、わかったことをまとめると、

SimpleDateFormat DateTimeFormatter
java.util.Dateへの変換 TemporalAccessorへの変換(LocalDateTime, LocalDate, LocalTime, ZonedDateTimeなど)
インスタンス生成 new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS") DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss.SSS")
スレッドセーフ? ×
parse dtf.parse(str)
java.util.Dateになる。
dtf.parse(str)
TemporalAccessorになる。
LocalDateTimeなどのparseメソッドのほうが使いやすい。
format sdf.format(date) dtf.format(TemporalAccessor)

Javaの日付/時刻の扱いはやっぱり難しい。
PHPはこんなに難しくなったような気がする。
(日付/時刻を扱ったことがあまりないからそう思っているだけかも…)

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.