こんにちわ、みけです。
前回に引き続き、Java8のDate and Time APIについて書いていきます。
今回はZonedDateTime
について書きます。
ZonedDateTime
クラス
ZonedDateTime
クラスは日時情報に加えて、時差情報をもつクラスです。
最初、よくわからずLocalDateTime
だけを触っていたのですが、
時差などを扱っているうちに、
どちらかといえば、こちらのクラスのほうが便利だなと感じるようになりました。
(ただし、時差を考慮しない場合はこの限りではない)
では実際に動かしてみます。
@RunWith(Enclosed.class) public class DateTimeTest { private static final Object LOCK = new Object(); //ゾーン情報なしのフォーマット private static final DateTimeFormatter withoutZone = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"); //ゾーン情報ありのフォーマット private static final DateTimeFormatter withZone = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss Z"); //東京 private static final ZoneId ASIA_TOKYO = ZoneId.of("Asia/Tokyo"); //グリニッジ private static final ZoneId GMT = ZoneId.of("GMT"); //複数のクラスでSystem.out.printlnしてたらうまく出力できなかったので、ここで一元的に出力してる private synchronized static void log(Queue<Output> outputs) { while (outputs.size() > 0) { synchronized (LOCK) { System.out.println(outputs.poll()); } } } //コンソール出力用にフォーマットするクラス private static class Output { final String message; final String className; final String methodName; private Output(String message, String className, TestName testName) { this.message = message; this.className = className; this.methodName = testName.getMethodName(); } @Override public String toString() { return className + " - " + message + " <- " + methodName; } } /** * ZonedDateTimeを動かしてみる */ public static class ZonedDateTimeTest { //このクラスの名前 private static final String CLASS = ZonedDateTimeTest.class.getSimpleName(); //現在時刻(秒まで) - デフォルトタイムゾーンが使われる private static final ZonedDateTime NOW = ZonedDateTime.now().truncatedTo(ChronoUnit.SECONDS); //現在時刻(秒まで) - 東京の時刻 private static final ZonedDateTime NOW_IN_ASIA_TOKYO = ZonedDateTime.now(ASIA_TOKYO).truncatedTo(ChronoUnit.SECONDS); //現在時刻(秒まで) - グリニッジの時刻 private static final ZonedDateTime NOW_IN_GMT = ZonedDateTime.now(GMT).truncatedTo(ChronoUnit.SECONDS); //ログ出力用 private static final Queue<Output> QUEUE = new ConcurrentLinkedQueue<>(); //テスト名出力用 @Rule public TestName testName = new TestName(); @Test public void zonedDateTimeは日時と時差情報を持つ() { QUEUE.offer(new Output(withoutZone.format(NOW), CLASS, testName)); } @Test public void zonedDateTimeは日時と時差情報を持つのでもちろんゾーンも出力できる() { QUEUE.offer(new Output(withZone.format(NOW), CLASS, testName)); } @Test public void ゾーンを指定してzonedDateTimeを取得_指定無しの場合は実行中のマシンのゾーンに合わせる() { QUEUE.offer(new Output(withZone.format(NOW_IN_ASIA_TOKYO), CLASS, testName)); assertThat(withZone.format(NOW).equals(withZone.format(NOW_IN_ASIA_TOKYO)), is(true)); } @Test public void ゾーンを指定してzonedDateTimeを取得() { QUEUE.offer(new Output(withZone.format(NOW_IN_GMT), CLASS, testName)); } @Test public void ゾーンが違うので時刻が違うけど同じ時刻() { QUEUE.offer(new Output(withoutZone.format(NOW_IN_ASIA_TOKYO), CLASS, testName)); QUEUE.offer(new Output(withoutZone.format(NOW_IN_GMT), CLASS, testName)); assertThat(NOW_IN_GMT.isEqual(NOW_IN_ASIA_TOKYO), is(true)); } //ログを一気に出力 @AfterClass public static void outputMessages() { log(QUEUE); } } }
出力結果
ZonedDateTimeTest - 2014/09/05 18:14:28 +0900 <- ゾーンを指定してzonedDateTimeを取得_指定無しの場合は実行中のマシンのゾーンに合わせる ZonedDateTimeTest - 2014/09/05 09:14:28 +0000 <- ゾーンを指定してzonedDateTimeを取得 ZonedDateTimeTest - 2014/09/05 18:14:28 +0900 <- zonedDateTimeは日時と時差情報を持つのでもちろんゾーンも出力できる ZonedDateTimeTest - 2014/09/05 18:14:28 <- zonedDateTimeは日時と時差情報を持つ ZonedDateTimeTest - 2014/09/05 18:14:28 <- ゾーンが違うので時刻が違うけど同じ時刻 ZonedDateTimeTest - 2014/09/05 09:14:28 <- ゾーンが違うので時刻が違うけど同じ時刻
最初のテストzonedDateTimeは日時と時差情報を持つ
はZonedDateTime
が
時刻と時差をもっているというのに、時刻しか出力していないので、
何かありがたさがわからないような結果になっています。
次のテストzonedDateTimeは日時と時差情報を持つのでもちろんゾーンも出力できる
は、
結果をゾーン付きで出力しています。
LocalDateTime
クラスではこの書式で例外が発生していたのに対して、
ZonedDateTime
は時差の情報を持つので、このフォーマットで出力できます。
3つ目のテストゾーンを指定してzonedDateTimeを取得_指定無しの場合は実行中のマシンのゾーンに合わせる
では、ZonedDateTime.now
とZonedDateTime.now(ASIA_TOKYO)
の結果を比べています。
僕のマシーンは東京の設定をしているので、
デフォルトタイムゾーンは東京になっています。
したがって、ZonedDateTime.now
とZonedDateTime.now(ASIA_TOKYO)
の比較結果は
等しいという事になっています。
4つ目のテストゾーンを指定してzonedDateTimeを取得
では、GMT
での時刻を出力しています。
東京の時刻に比べて、9時間遅い時刻が時差(+0:00)で出力されています。
最後のテストゾーンが違うので時刻が違うけど同じ時刻
では、
ZonedDateTime.now(ASIA_TOKYO)
とZonedDateTime.now(GMT)
との比較をしています。
この二つをゾーンなしフォーマットで出力すると、全然違う時刻ですが、
実際に比べてみると等しい時刻であるということがわかります。
以上。
次回は文字列から日付を取得する方法について書きます。