Date and Time APIを触ってみた
JavaAdventCalendar2012の24日目。カレンダーなんで日付のです。24日とかただの日だし。12/24とか約分したら1/2だし。
ところでこれの答えわかります?*1
System.out.println(12/24);
準備とか
バージョン 0.7.0-alpha と書かれている通り、まだ出来てないとかなんとか。0.6.3ならダウンロードできるんだけど、チラチラ見てると幾らか変わってるので、GitHubから持ってきてビルドします。
clone して ant 叩いて build にできた threeten-0.7.0-alpha.jar を適当な場所に持ってって、クラスパスに通せば完了。
ざーっと使ってみる
- Instant - An instant on the time-line
- Duration - A duration of time
瞬間と期間っぽい。
Instant instant = Instant.now(); Duration duration = Duration.ofHours(-3); println(instant); // 2012-12-24T12:52:12.837Z println(duration); // PT-10800S DateTime dateTime = duration.doPlusAdjustment(instant); println(dateTime); // 2012-12-24T09:52:12.837Z
- LocalDate - A date, with no time nor zone-offset
- LocalTime - A time, with no date nor zone-offset
- LocalDateTime - A date-time, with no zone-offset
日付、時間、その組み合わせっと。OffsetDateとかZonedDateTimeとかもあるみたいなんだけど、とりあえず割愛。
LocalDate date = LocalDate.of(2012, Month.DECEMBER, 24); println(date); // 2012-12-24 printf("year: %s, monthValue: %s, dayOfMonth: %s%n", date.getYear(), date.getMonthValue(), date.getDayOfMonth()); // year: 2012, monthValue: 12, dayOfMonth: 24 println(date.withYear(2013)); // 2013-12-24 println(date.withMonth(11)); // 2012-11-24 println(date.withDayOfMonth(22)); // 2012-12-22 println(date.plusDays(7)); // 2012-12-31 println(date.plusDays(8)); // 2013-01-01 println(date.toEpochDay()); // 15698 println(date.atTime(12, 34)); // 2012-12-24T12:34 println(date.atTime(LocalTime.ofSecondOfDay(80000))); // 2012-12-24T22:13:20
Immutableなので、withとかplusとかしても値は変わりません。"Clear, explicit and expected" とか書いてる通り、素直に使える感じですね。
enum Monthとか、MonthValueの値が1-12だとか、地味に嬉しいところ。Timeも同じような感じで使えます。DateTimeはDateとTimeの両方の操作がほぼ全部できる感じでした。
DateTimeはDateとTimeをくっつけたもので、この3クラスは以下のようにくっつけたり剥がしたりできました。
LocalDateTime dateTime = LocalDateTime.of(2012, 12, 24, 11, 22, 33); println(dateTime); // 2012-12-24T11:22:33 LocalDate date = dateTime.getDate(); LocalTime time = dateTime.getTime(); println(date); // 2012-12-24 println(time); // 11:22:33 println(date.atTime(time)); // 2012-12-24T11:22:33 println(time.atDate(date)); // 2012-12-24T11:22:33
"Fluent API"ってのはこの辺かな。withとAdjusterを使うのとか。
LocalDate date = LocalDate.of(2012, Month.DECEMBER, 24); println(date.with(firstDayOfMonth())); // 2012-12-01 println(date.with(firstInMonth(FRIDAY))); // 2012-12-07 println(date.with(next(MONDAY))); // 2012-12-31 println(date.with(nextOrSame(MONDAY))); // 2012-12-24
いい感じだとは思う、けれどもstatic importが前提になるので、これまた既存のJavaコーディング規約との微妙な戦いをするはめになりますね。Adjusterとかは自分で作れるので、上手いこと使えば……
脱線
ところでWithAdjusterは1メソッドのインタフェースです。
public interface WithAdjuster { DateTime doWithAdjustment(DateTime dateTime); }
つまりLambda使えますね。
DateTime now = Instant.now(); println(now.with(it -> Duration.ofDays(10).doPlusAdjustment(it)));
嬉しさがわからない(真顔
実際この辺は三営業日後を取得したりとか*2、複雑な日付計算を押し込めてなんぼだろうし、Lambdaでやって嬉しいことはあまりなさそうな気がします。
感想
だいたい業務システムだと日付は日付で扱いたいときが多くて、素直に同じ日がequalsでtrueになってくれるだけでも、Dateはありがたいです。標準で使えるのがいいと思んです。ぶっちゃ業務でJoda-Timeとか見たことないです。
ビルドして出来たjarに javadoc に書かれてるクラスとかが普通に無かったりして、ほんのり触ってみた程度になりました。でもいい感じには思えました。少なくともDateやCalendarより扱いやすいのは間違いなさそうです。