2014年3月にリリースされたJava 8では、その前まで日時を扱っていたjava.util.Dateやjava.util.Calendarなどとは異なる、まったく新しい日時を扱うAPIとしてDate-Time API が追加されました。本連載では、このDate-Time APIについて一般的な業務システムを構築する際に必要な情報について簡単に見ていきます。
前回の「ImmutableでスレッドセーフになったJavaの新しい日時APIの基礎知識」では、Date-Time APIの概要や、Java 8より前の旧日時APIから何が改善されたのかに加え、新しく追加されたさまざまなクラスについて解説しました。今回はJava 8より導入されたDate-Time APIで何ができるのかを探るため、用意されているメソッドについて見ていき、実際にどのように使うのかを見ていきます。
また、旧日時APIとの変換については次回の連載で説明する予定です。
※この連載ではJava 8より追加されたjava.timeパッケージ以下のAPIを「Date-Time API」と呼んでいき、それより前のjava.util.Dateなどの日時のAPIを「旧日時API」と呼んでいきます。また、実行環境のタイムゾーンは日本になっています。
Date-Time APIには旧日時APIにはなかった多くのメソッドが用意されています。そして、それらのほとんどは、メソッド名もしくはメソッド名の最初の数文字(prefix)で処理の内容を表すようになっているため、メソッド名を見ただけで、そのメソッドがどのような処理をするのかが容易に想像がつくようになっています。
それでは、それらの名称が表す処理の内容について見ていきましょう。
メソッド名 / prefix | static / インスタンス | 概要 |
---|---|---|
now | static | 実行時の日付や時刻の情報を持ったインスタンスを生成するメソッド |
of | static | このメソッドの引数の情報が設定されたインスタンスを生成するメソッド |
この中のnowメソッドは引数に何も設定しないと、実行しているシステムのタイムゾーンから実行時の日時が設定されたインスタンスが設定され、引数にZoneIdを設定すると、そのタイムゾーンでの日時が設定されます。
下記のサンプルではタイムゾーンなどの情報を持たないシンプルな日付と時刻を持つLocalDateTimeにシステムのデフォルト時(日本時間)での現在時刻を設定したものとロサンゼルスでの現在時刻を設定したものを生成しています。このLocalDateTime自体はタイムゾーンの情報は持ちませんが、設定された日付と時刻はnowメソッドで指定したタイムゾーンのものが設定されていることに注目してください。
// 実行環境のデフォルト LocalDateTime localDateTime1 = LocalDateTime.now(); System.out.println("localDateTime1=" + localDateTime1); // タイムゾーン設定 LocalDateTime localDateTime2 = LocalDateTime.now(ZoneId.of("America/Los_Angeles")); System.out.println("localDateTime2=" + localDateTime2);
localDateTime1=2014-11-16T14:07:54.675 localDateTime2=2014-11-15T21:07:54.691
また、引数にClockクラスを渡すnowメソッドもあります。このClockは実行環境で使われている時計の代わりに、任意の時計を設定できるクラスです。このClockには実行環境のデフォルトの時計を設定できるのはもちろん、特定のタイムゾーンの時計や特定の固定時刻を設定可能です。そして、この性質を利用してテストを簡易化できます。
例えば、さまざまな国で実行されているアプリケーションの場合、実行している場所での時計を現在時刻として使っているとします。そこで、開発現場からさまざまなタイムゾーンでのテストをする場合に、どこのタイムゾーンの現在時刻かをアプリ側で簡単に変えられないと、実行環境の時計を変えてテストを行うなどしなくてはいけません。
しかしClockを使っている場合、通常時はClockに実行環境のデフォルトの時計を設定しておき、テストの際はテスト対象のタイムゾーンに変えたClockを設定することで、別の地域でのテストをシミュレーションできます。また、特定の時間でのイベントをテストする場合、Clockに別の時刻を設定することにより特定の時間でのテストも可能です。
それでは、Clockを引数にして渡すとnowメソッドがどのようになるのか見てみましょう。
// システムのデフォルト Clock clock = Clock.systemDefaultZone(); LocalDateTime localDateTime1 = LocalDateTime.now(clock); System.out.println("localDateTime1=" + localDateTime1); Thread.sleep(1000); // 1秒ほど待つ // 同じClockのインスタンスを使っていてもfixedメソッドで時間の固定化がされていない場合、時間は進みます LocalDateTime localDateTime2 = LocalDateTime.now(clock); System.out.println("localDateTime2=" + localDateTime2); Thread.sleep(1000); // 1秒ほど待つ // タイムゾーン(ZoneId)を指定した時計。マシンのタイムゾーンでないタイムゾーンを指定する場合に使います。 Clock zonedClock = Clock.system(ZoneId.of("America/Los_Angeles")); //指定したタイムゾーンでの現在時刻を取得します LocalDateTime zonedCllockLocalDateTime = LocalDateTime.now(zonedClock); System.out.println("zonedCllockLocalDateTime =" + zonedCllockLocalDateTime); Thread.sleep(1000); // 1秒ほど待つ // UTCからの時差(オフセット)を指定した時計。 Clock offsetClock = Clock.offset(clock, Duration.ofHours(8)); //指定したオフセットでの現在時刻を取得します LocalDateTime offsetClockLocalDateTime = LocalDateTime.now(offsetClock); System.out.println("offsetClockLocalDateTime =" + offsetClockLocalDateTime); Thread.sleep(1000); // 1秒ほど待つ // fixedメソッドで特定の時間を指定した場合(日時は固定されます) Instant instant = Instant.parse("2014-01-01T00:00:00Z"); Clock fixedClock = Clock.fixed(instant, ZoneId.systemDefault()); // 日本では+09:00の時差があります。 LocalDateTime fixedClockLocalDateTime1 = LocalDateTime.now(fixedClock); System.out.println("fixedClockLocalDateTime1=" + fixedClockLocalDateTime1); Thread.sleep(1000); // 1秒ほど待つ // fixedClock は固定のものなので同じ時刻になります LocalDateTime fixedClockLocalDateTime2 = LocalDateTime.now(clock); System.out.println("fixedClockLocalDateTime2=" + fixedClockLocalDateTime2);
localDateTime1=2014-11-27T09:38:34.078 localDateTime2=2014-11-27T09:38:35.078 zonedClockLocalDateTime=2014-11-26T16:38:36.084 offsetClockLocalDateTime=2014-11-27T00:38:37.267 fixedClockLocalDateTime1=2014-01-01T09:00 fixedClockLocalDateTime2=2014-01-01T09:00
実際に稼働するシステムでClockを使う場合は、例えば一つのClockを引数に使ってnowメソッドを呼び出せるようにしておき、初期化時に外部ファイルなどでそのClockを簡単に変えられる仕組みを用意しておくと、現在時刻を変えて簡単にテストを行えるようになります。
Copyright© 2015 ITmedia, Inc. All Rights Reserved.