Date and Time APIについて調べてみた その1

【前提条件】

[環境]
[参考資料]

Java8 APIドキュメント
http://docs.oracle.com/javase/jp/8/api/

JJUG 祝Java8Launch のスライド
Brand new Date and Time API(@さん)
http://www.slideshare.net/btnrouge/jdk8-threeten

【概要】

今回からDate and Time APIです。

Date and Time APIはJava8から新しく追加された
日付操作のためのAPIです。

【日付情報に関するクラス】

日付情報で基本となるクラスは下記の3つです。

  • java.time.LocalDate
  • java.time.LocalTime
  • java.time.LocalDateTime

LocalDateは日付、LocalTimeは時刻、
LocalDateTimeは日付と時刻を保持するクラスです。

上記のクラスはタイムゾーンの情報を持たないため、
タイムゾーンを意識する場合は下記のクラスを使います。

  • java.time.OffsetDateTime
  • java.time.ZonedDateTime

上記の2つのクラスとLocalDateTimeクラスとで
基本的なメソッドに関しては使い方は変わらないです。

【現在時刻の取得】

現在時刻の取得は各クラスのnowメソッドを使います。
nowメソッドはいくつかのメソッドシグネチャを持ちます。

[サンプルコード1]

まずはパラメータなしのパターンです。

    public static void sampleNow01() {

        System.out.println(LocalDate.now());
        System.out.println(LocalTime.now());
        System.out.println(LocalDateTime.now());
    }

パラメータなしの場合は
システムのデフォルトタイムゾーンの現在時刻が設定された
オブジェクトを生成します。

生成されたオブジェクト自体にはタイムゾーンの情報は持ちません。

[実行結果1]
2014-06-07
15:45:30.944
2014-06-07T15:45:30.944

今日の時刻を元に結果が出力されていることがわかります。
(エントリを登録する前に実行していることもわかってしまいますね)

LocalDateTimeの出力形式はISO8601の時刻表記で、
日付と時刻が「T」でつなげられています。

[サンプルコード2]

つづいてパラメータを指定するパターンです。

    public static void sampleNow02() {

        System.out.println(LocalDateTime.now(Clock.systemUTC()));
        System.out.println(LocalDateTime.now(Clock.systemDefaultZone()));

        System.out.println(LocalDateTime.now(ZoneId.of("Asia/Tokyo")));
        System.out.println(LocalDateTime.now(ZoneId.of("America/Los_Angeles")));
    }

前半の2つはjava.time.Clockクラスのオブジェクトを指定するパターンです。
サンプルではUTCとデフォルトのタイムゾーンを指定しています。

後半の2つはjava.time.ZoneIdクラスのオブジェクトを指定するパターンです。
サンプルでは東京とロサンゼルスのタイムゾーンを指定しています。

[実行結果2]
2014-06-07T06:58:57.134
2014-06-07T15:58:57.155
2014-06-07T15:58:57.155
2014-06-06T23:58:57.157

デフォルタイムゾーンと東京を指定結果が同じで、
それ以外のタイムゾーンを指定した場合は違う結果が表示されます。

【特定時刻の取得】

特定時刻の取得は各クラスのofメソッドを使用します。

[サンプルコード]
    public static void sampleOf() {
        
        final LocalDate date1 = LocalDate.of(2014, 5, 10);
        final LocalDate date2 = LocalDate.of(2012, Month.JULY, 24);

        System.out.println(date1);
        System.out.println(date2);

        final LocalTime time1 = LocalTime.of(22, 30, 12, 123);
        final LocalTime time2 = LocalTime.of(13, 11);
        System.out.println(time1);
        System.out.println(time2);

        final LocalDateTime dateTime1 = LocalDateTime.of(1986, 12, 16, 11, 45, 52, 123_456_789);
        final LocalDateTime dateTime2 = LocalDateTime.of(date1, time1);
        final LocalDateTime dateTime3 = LocalDateTime.of(date2, time2);

        System.out.println(dateTime1);
        System.out.println(dateTime2);
        System.out.println(dateTime3);
    }

LocalDate#ofメソッドの場合は年・月・日を指定します。
月にはintかjava.time.Monthオブジェクトを指定します。
intの指定は1〜12で指定します。

LocalTime#ofメソッドの場合は時・分・秒・ナノ秒を指定します。
時・分に関しては必ず指定する必要がありますが、
秒・ナノ秒に関しては省略することが出来ます。

LocalDateTime#ofメソッドの場合は年〜ナノ秒までを指定するか、
LocalDateオブジェクトとLocalTimeオブジェクトを指定します。

[実行結果]
2014-05-10
2012-07-24
22:30:12.000000123
13:11
1986-12-16T11:45:52.123456789
2014-05-10T22:30:12.000000123
2012-07-24T13:11

それぞれ指定された値が出力されているのがわかります。

出力フォーマットを指定していない場合、
時刻の指定で省略されたパラメータ部分は出力されないようです。

【まとめ】

Java8から日付のみ、時刻のみが扱えるようになりました。

今まで日付だけ欲しい場合はDateクラスを
時刻だけ欲しい場合はint-intで格納していましたが、
Date and Time APIを使えば純粋な日付・時刻が設定できそうです。

ORMでDate and Time APIが対応されるようになれば、
DBでの日付型、時刻型とあわせるのも楽になりそうですね。

しかし、Dateクラスとは互換性がないので、
過去のバージョンから移行して、既存のソースを変更する場合には
使用できません。

Java8で新規にコードを書く場合は使いましょうと言うことで。