Java 8 Date / Time APIの概要
1. 概要
Java 8では、古いjava.util.Dateとjava.util.Calendarの欠点に対処するために、DateとTimeに新しいAPIが導入されました。
この記事の一部として、既存のDateおよびCalendar APIの問題から始めて、新しいJava 8DateおよびTimeAPIがそれらにどのように対処するかについて説明しましょう。
また、LocalDate、LocalTime, LocalDateTime, ZonedDateTime, Period, Duration、およびそれらでサポートされているAPIなどのjava.timeパッケージの一部である新しいJava8プロジェクトのコアクラスのいくつかについても見ていきます。
参考文献:
2. 既存のDate /TimeAPIの問題
-
Thread Safety –DateクラスとCalendarクラスはスレッドセーフではないため、開発者は同時実行の問題をデバッグするのが難しいという頭痛の種に対処し、スレッドセーフを処理するための追加コードを作成する必要があります。 それどころか、Java 8で導入された新しいDateおよびTime APIは不変でスレッドセーフであるため、開発者は並行性の問題を解消できます。
-
APIs Design and Ease of Understanding –DateおよびCalendar APIは、日常の操作を実行するための不適切なメソッドを使用して設計されていません。 新しいDate/Time APIはISO中心であり、日付、時刻、期間、および期間について一貫したドメインモデルに従います。 最も一般的な操作をサポートするさまざまなユーティリティメソッドがあります。
-
ZonedDate and Time –開発者は古いAPIでタイムゾーンロジックを処理するために追加のロジックを作成する必要がありましたが、新しいAPIでは、タイムゾーンの処理はLocalおよびZonedDate /Timeで実行できます。 ■API。
3. LocalDate、LocalTime、およびLocalDateTimeを使用する
最も一般的に使用されるクラスは、LocalDate、LocalTime、およびLocalDateTimeです。 名前が示すように、オブザーバーのコンテキストからローカルの日付/時刻を表します。
これらのクラスは主に、コンテキストでタイムゾーンを明示的に指定する必要がない場合に使用されます。 このセクションの一部として、最も一般的に使用されるAPIについて説明します。
3.1. LocalDateの操作
LocalDateはa date in ISO format (yyyy-MM-dd) without timeを表します。
誕生日や給料日などの日付を保存するために使用できます。
現在の日付のインスタンスは、次のようにシステムクロックから作成できます。
LocalDate localDate = LocalDate.now();
特定の日、月、年を表すLocalDateは、「of」メソッドまたは「parse」メソッドを使用して取得できます。 たとえば、以下のコードスニペットは、2015年2月20日のLocalDateを表しています。
LocalDate.of(2015, 02, 20);
LocalDate.parse("2015-02-20");
LocalDateは、さまざまな情報を取得するためのさまざまなユーティリティメソッドを提供します。 これらのAPIメソッドのいくつかを簡単に見てみましょう。
次のコードスニペットは、現在のローカル日付を取得し、1日を追加します。
LocalDate tomorrow = LocalDate.now().plusDays(1);
この例では、現在の日付を取得し、1か月を差し引きます。 時間単位としてenumを受け入れる方法に注意してください。
LocalDate previousMonthSameDay = LocalDate.now().minus(1, ChronoUnit.MONTHS);
次の2つのコード例では、日付「2016-06-12」を解析し、曜日と月をそれぞれ取得します。 戻り値に注意してください。最初のオブジェクトはDayOfWeekを表し、2番目のintは月の序数を表します。
DayOfWeek sunday = LocalDate.parse("2016-06-12").getDayOfWeek();
int twelve = LocalDate.parse("2016-06-12").getDayOfMonth();
date年に日付が発生するかどうかをテストできます。 この例では、現在の日付がうるう年かどうかをテストします。
boolean leapYear = LocalDate.now().isLeapYear();
日付と別の日付の関係は、別の日付の前または後に発生するように決定できます。
boolean notBefore = LocalDate.parse("2016-06-12")
.isBefore(LocalDate.parse("2016-06-11"));
boolean isAfter = LocalDate.parse("2016-06-12")
.isAfter(LocalDate.parse("2016-06-11"));
日付の境界は、特定の日付から取得できます。 次の2つの例では、指定された日付の1日の始まり(2016-06-12T00:00)を表すLocalDateTimeと、月の始まり(2016- 06-01)それぞれ:
LocalDateTime beginningOfDay = LocalDate.parse("2016-06-12").atStartOfDay();
LocalDate firstDayOfMonth = LocalDate.parse("2016-06-12")
.with(TemporalAdjusters.firstDayOfMonth());
それでは、現地時間でどのように機能するかを見てみましょう。
3.2. LocalTimeの操作
LocalTimeはtime without a dateを表します。
LocalDateと同様に、LocalTimeのインスタンスは、システムクロックから、または「解析」および「of」メソッドを使用して作成できます。 以下の一般的に使用されるAPIのいくつかを簡単に見てください。
現在のLocalTimeのインスタンスは、次のようにシステムクロックから作成できます。
LocalTime now = LocalTime.now();
以下のコードサンプル,では、文字列表現を解析することにより、午前6時30分を表すLocalTimeを作成します。
LocalTime sixThirty = LocalTime.parse("06:30");
ファクトリメソッド「of」を使用して、LocalTimeを作成できます。 たとえば、次のコードは、ファクトリメソッドを使用して午前6時30分を表すLocalTimeを作成します。
LocalTime sixThirty = LocalTime.of(6, 30);
次の例では、文字列を解析してLocalTimeを作成し、「plus」APIを使用して文字列に1時間を追加します。 結果は、午前7時30分を表すLocalTimeになります。
LocalTime sevenThirty = LocalTime.parse("06:30").plus(1, ChronoUnit.HOURS);
以下のような時間、分、秒などの特定の時間単位を取得するために使用できるさまざまなゲッターメソッドが利用できます。
int six = LocalTime.parse("06:30").getHour();
特定の時間が別の特定の時間の前か後かを確認することもできます。 以下のコードサンプルは、結果が真になる2つのLocalTimeを比較します。
boolean isbefore = LocalTime.parse("06:30").isBefore(LocalTime.parse("07:30"));
1日の最大時間、最小時間、正午時間は、LocalTimeクラスの定数によって取得できます。 これは、特定の期間内にデータベースクエリを実行してレコードを検索するときに非常に便利です。 たとえば、次のコードは23:59:59.99を表します。
LocalTime maxTime = LocalTime.MAX
それでは、LocalDateTimeに飛び込みましょう。
3.3. LocalDateTimeの操作
LocalDateTimeは、a combination of date and timeを表すために使用されます。
これは、日付と時刻の組み合わせが必要なときに最も一般的に使用されるクラスです。 このクラスはさまざまなAPIを提供しますが、最も一般的に使用されるものをいくつか見ていきます。
LocalDateTimeのインスタンスは、LocalDateおよびLocalTime:と同様にシステムクロックから取得できます。
LocalDateTime.now();
以下のコードサンプルは、ファクトリ「of」および「parse」メソッドを使用してインスタンスを作成する方法を説明しています。 結果は、2015年2月20日午前6時30分を表すLocalDateTimeインスタンスになります。
LocalDateTime.of(2015, Month.FEBRUARY, 20, 06, 30);
LocalDateTime.parse("2015-02-20T06:30:00");
日、月、年、分などの特定の時間単位の加算と減算をサポートするユーティリティAPIがあります。 以下のコードサンプルは、「プラス」および「マイナス」メソッドの使用法を示しています。 これらのAPIは、LocalDateおよびLocalTime:の対応するAPIとまったく同じように動作します
localDateTime.plusDays(1);
localDateTime.minusHours(2);
日付および時刻クラスに類似した特定の単位を抽出するゲッターメソッドが利用可能です。 上記のLocalDateTimeのインスタンスが与えられると、以下のコードサンプルは2月を返します。
localDateTime.getMonth();
4. ZonedDateTimeAPIの使用
Java 8 provides ZonedDateTime # [.typ]#タイムゾーン固有の日時を処理する必要がある場合。 ZoneIdは、さまざまなゾーンを表すために使用される識別子です。 約40の異なるタイムゾーンがあり、ZoneIdは次のようにそれらを表すために使用されます。
このコードスニペットでは、パリのZoneを作成します。
ZoneId zoneId = ZoneId.of("Europe/Paris");
すべてのゾーンIDのセットは、次のようにして取得できます。
Set allZoneIds = ZoneId.getAvailableZoneIds();
LocalDateTimeは、特定のゾーンに変換できます。
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zoneId);
ZonedDateTimeは、タイムゾーン固有の日時を取得するためのparseメソッドを提供します。
ZonedDateTime.parse("2015-05-03T10:15:30+01:00[Europe/Paris]");
タイムゾーンを操作する別の方法は、OffsetDateTimeを使用することです。 OffsetDateTimeは、オフセット付きの日時の不変表現です。 このクラスは、UTC /グリニッジからのオフセットと同様に、すべての日付および時刻フィールドをナノ秒の精度で保存します。
OffSetDateTimeインスタンスは、ZoneOffsetを使用して以下のように作成できます。 ここでは、2015年2月20日の午前6時30分を表すLocalDateTimeを作成します。
LocalDateTime localDateTime = LocalDateTime.of(2015, Month.FEBRUARY, 20, 06, 30);
次に、ZoneOffsetを作成し、localDateTimeインスタンスを設定することにより、時間に2時間を追加します。
ZoneOffset offset = ZoneOffset.of("+02:00");
OffsetDateTime offSetByTwo = OffsetDateTime
.of(localDateTime, offset);
2015-02-20 06:30 +02:00のlocalDateTimeがあります。 次に、PeriodクラスとDurationクラスを使用して日付と時刻の値を変更する方法に移りましょう。
5. PeriodおよびDurationの使用
Periodクラスは、年、月、日で表した時間の量を表し、Durationクラスは、秒とナノ秒で表した時間を表します。
5.1. Periodの操作
Periodクラスは、特定の日付の値を変更したり、2つの日付の差を取得したりするために広く使用されています。
LocalDate initialDate = LocalDate.parse("2007-05-10");
Dateは、次のコードスニペットに示すように、Periodを使用して操作できます。
LocalDate finalDate = initialDate.plus(Period.ofDays(5));
Periodクラスには、Periodオブジェクトから値を取得するためのgetYears, getMonthsやgetDaysなどのさまざまなゲッターメソッドがあります。 次のコード例では、日数で差を取得しようとすると、intの値5が返されます:
int five = Period.between(initialDate, finalDate).getDays();
2つの日付の間のPeriodは、ChronoUnit.between:を使用して、日、月、年などの特定の単位で取得できます。
long five = ChronoUnit.DAYS.between(initialDate, finalDate);
このコード例は5日間を返します。 続けて、Durationクラスを見てみましょう。
5.2. Durationの操作
Period,と同様に、Duration classはTime.の処理に使用されます。次のコードでは、午前6時30分のLocalTimeを作成し、30秒の期間を追加して作成します。 06:30:30 amのLocalTime:
LocalTime initialTime = LocalTime.of(6, 30, 0);
LocalTime finalTime = initialTime.plus(Duration.ofSeconds(30));
2つの瞬間の間のDurationは、Durationまたは特定の単位として取得できます。 最初のコードスニペットでは、Durationクラスのbetween()メソッドを使用して、finalTimeとinitialTimeの時間差を見つけ、その差を秒単位で返します。
long thirty = Duration.between(initialTime, finalTime).getSeconds();
2番目の例では、ChronoUnitクラスのbetween()メソッドを使用して、同じ操作を実行します。
long thirty = ChronoUnit.SECONDS.between(initialTime, finalTime);
次に、既存のDateとCalendarを新しいDate /Time.に変換する方法を見ていきます。
6. DateおよびCalendarとの互換性
Java 8は、次のコードスニペットのように、既存のDateおよびCalendarインスタンスを新しいDate Time APIに変換するのに役立つtoInstant()メソッドを追加しました。
LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
LocalDateTime.ofInstant(calendar.toInstant(), ZoneId.systemDefault());
LocalDateTimeは、以下のようにエポック秒から作成できます。 以下のコードの結果は、2016-06-13T11:34:50を表すLocalDateTimeになります。
LocalDateTime.ofEpochSecond(1465817690, 0, ZoneOffset.UTC);
それでは、DateとTimeのフォーマットに移りましょう。
7. DateおよびTimeのフォーマット
Java 8は、DateおよびTimeを簡単にフォーマットするためのAPIを提供します。__
LocalDateTime localDateTime = LocalDateTime.of(2015, Month.JANUARY, 25, 6, 30);
以下のコードは、ISO日付形式を渡してローカル日付をフォーマットします。 結果は2015-01-25になります。
String localDateString = localDateTime.format(DateTimeFormatter.ISO_DATE);
DateTimeFormatterは、さまざまな標準フォーマットオプションを提供します。 以下のように、カスタムパターンをformatメソッドに提供することもできます。これにより、LocalDateが2015/01/25として返されます。
localDateTime.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
書式設定オプションの一部として、SHORT、LONG、またはMEDIUMのいずれかとして書式設定スタイルを渡すことができます。 以下のコードサンプルは、2015年1月25日06:30:00のLocalDateTimeを表す出力を提供します。
localDateTime
.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM))
.withLocale(Locale.UK);
Java 8 CoreDate /TimeAPIで利用可能な代替手段を見てみましょう。
8. バックポートと代替オプション
8.1. ProjectThreetenの使用
Java7またはJava6からJava8に移行する途中で、日付と時刻のAPIを使用したい組織の場合、プロジェクトthreetenはバックポート機能を提供します。 開発者は、このプロジェクトで利用可能なクラスを使用して、新しいJava 8DateおよびTime APIと同じ機能を実現でき、Java 8に移行すると、パッケージを切り替えることができます。 プロジェクトthreetenのアーティファクトは、maven central repositoryにあります。
org.threeten
threetenbp
1.3.1
8.2. ジョーダタイム図書館
Java 8DateおよびTimeライブラリのもう1つの代替方法は、Joda-Timeライブラリです。 実際、Java 8Date Time APIは、Joda-Timeライブラリの作成者(Stephen Colebourne)とOracleが共同で主導しています。 このライブラリは、Java 8Date Timeプロジェクトでサポートされているほとんどすべての機能を提供します。 アーティファクトは、プロジェクトに以下のpom依存関係を含めることにより、maven centralで見つけることができます。
joda-time
joda-time
2.9.4
9. 結論
Java 8は、開発を容易にするための一貫したAPI設計を備えた豊富なAPIセットを提供します。
上記の記事のコードサンプルは、Java 8 Date/Timegitリポジトリにあります。