1. 概要

Java 8では、DateおよびTimeに新しいAPIが導入され、古いjava.util.Dateおよびjava.util.Calendarの欠点に対処しています。 ]。

このチュートリアルでは、既存のDateおよびCalendar APIの問題から始めて、新しいJava 8 DateおよびTimeAPIはそれらに対処します。

また、 LocalDate LocalTime など、java.timeパッケージの一部である新しいJava8プロジェクトのコアクラスのいくつかについても見ていきます。 LocalDateTime ZonedDateTime Period durationおよびそれらがサポートするAPI。

2. 既存の日付/時間APIに関する問題

  • スレッドセーフDateクラスとCalendarクラスはスレッドセーフではないため、開発者はデバッグが難しい同時実行性の問題の問題に対処し、追加の書き込みを行う必要があります。スレッドセーフを処理するコード。 それどころか、Java8で導入された新しいDateおよびTime APIは不変でスレッドセーフであるため、開発者はその同時実行性の頭痛の種を取り除きます。
  • APIの設計と理解のしやすさDateおよびCalendar APIは、日常の操作を実行するための不適切なメソッドで設計されていません。 新しいDate / Time APIはISO中心であり、日付、時刻、期間、および期間について一貫したドメインモデルに従います。 最も一般的な操作をサポートするさまざまなユーティリティメソッドがあります。
  • ZonedDateとTime–開発者は古いAPIでタイムゾーンロジックを処理するために追加のロジックを作成する必要がありましたが、新しいAPIでは、タイムゾーンの処理はLocalと[ X201X] ZonedDate / TimeAPI。

3. LocalDate LocalTime 、およびLocalDateTimeを使用する

最も一般的に使用されるクラスは、 LocalDate LocalTime 、およびLocalDateTimeです。 それらの名前が示すように、それらはオブザーバーのコンテキストからのローカルの日付/時刻を表します。

これらのクラスは主に、コンテキストでタイムゾーンを明示的に指定する必要がない場合に使用します。 このセクションの一部として、最も一般的に使用されるAPIについて説明します。

3.1. LocalDateの操作

The LocalDate を表す時間のないISO形式(yyyy-MM-dd)の日付。 誕生日や給料日などの日付を保存するために使用できます。

現在の日付のインスタンスは、システムクロックから作成できます。

LocalDate localDate = LocalDate.now();

また、ofメソッドまたはparseメソッドを使用して、特定の日、月、年を表すLocalDateを取得できます。

たとえば、これらのコードスニペットは、2015年2月20日のLocalDateを表します。

LocalDate.of(2015, 02, 20);

LocalDate.parse("2015-02-20");

LocalDate は、さまざまな情報を取得するためのさまざまなユーティリティメソッドを提供します。 これらのAPIメソッドのいくつかを簡単に見てみましょう。

次のコードスニペットは、現在のローカル日付を取得し、1日を追加します。

LocalDate tomorrow = LocalDate.now().plusDays(1);

この例では、現在の日付を取得し、1か月を差し引きます。 列挙型を時間単位として受け入れる方法に注意してください。

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();

うるう年に日付が発生するかどうかをテストできます。たとえば、現在の日付は次のとおりです。

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 と、の始まりを表すLocalDateを取得します。それぞれ月(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 は、日付のない時刻を表します。

LocalDate と同様に、システムクロックから、またはparseおよびofメソッドを使用して、LocalTimeのインスタンスを作成できます。

ここで、一般的に使用されるAPIのいくつかを簡単に見ていきます。

現在のLocalTimeのインスタンスは、システムクロックから作成できます。

LocalTime now = LocalTime.now();

午前6時30分を表すLocalTimeを作成できます 文字列表現を解析することによって:

LocalTime sixThirty = LocalTime.parse("06:30");

のファクトリメソッドを使用して、LocalTimeを作成することもできます。 このコードは、午前6時30分を表すLocalTimeを作成します ファクトリメソッドを使用する:

LocalTime sixThirty = LocalTime.of(6, 30);

文字列を解析し、「plus」APIを使用して文字列に時間を追加することにより、LocalTimeを作成しましょう。 結果は、午前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 は、日付と時刻の組み合わせを表すために使用されます。これは、日付と時刻の組み合わせが必要な場合に最も一般的に使用されるクラスです。

このクラスはさまざまな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 when we need to deal with time-zone-specific date and time. The ZoneId is an identifier used to represent different zones. There are about 40 different time zones, and the ZoneId represents them as follows.

Here, we create a Zone for Paris:

ZoneId zoneId = ZoneId.of("Europe/Paris");

そして、すべてのゾーンIDのセットを取得できます。

Set<String> allZoneIds = ZoneId.getAvailableZoneIds();

LocalDateTimeは特定のゾーンに変換できます。

ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, zoneId);

ZonedDateTime は、タイムゾーン固有の日時を取得するためのparseメソッドを提供します。

ZonedDateTime.parse("2015-05-03T10:15:30+01:00[Europe/Paris]");

タイムゾーンを操作する別の方法は、ResetDateTimeを使用することです。 OffsetDateTime は、オフセットを使用した日時の不変表現です。 このクラスは、すべての日付と時刻のフィールドをナノ秒の精度で格納し、UTC/グリニッジからのオフセットも格納します。

OffSetDateTime インスタンスは、ZoneOffsetを使用して作成できます。 ここでは、午前6時30分を表すLocalDateTimeを作成します。 2015年2月20日:

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. 期間および期間の使用

期間クラスは、年、月、日で表した時間の量を表し、期間クラスは、秒とナノ秒で表した時間の量を表します。

5.1. 期間の操作

Period クラスは、特定の日付の値を変更したり、2つの日付の差を取得したりするために広く使用されています。

LocalDate initialDate = LocalDate.parse("2007-05-10");

Period を使用して、Dateを操作できます。

LocalDate finalDate = initialDate.plus(Period.ofDays(5));

Period クラスには、 getYears getMonths getDays などのさまざまなゲッターメソッドがあり、Periodから値を取得します。物体。

たとえば、日数の差を取得しようとすると、int値5が返されます。

int five = Period.between(initialDate, finalDate).getDays();

ChronoUnit.between を使用して、日、月、年などの特定の単位で2つの日付の間の期間を取得できます。

long five = ChronoUnit.DAYS.between(initialDate, finalDate);

このコード例は5日を返します。

Durationクラスを見ていきましょう。

5.2. 期間の操作

Periodと同様に、DurationクラスTimeを処理するために使用されます。

午前6時30分のLocalTimeを作成しましょう 次に、30秒の期間を追加して、LocalTimeを午前6時30分30秒にします。

LocalTime initialTime = LocalTime.of(6, 30, 0);

LocalTime finalTime = initialTime.plus(Duration.ofSeconds(30));

デュレーションまたは特定のユニットとして、2つの瞬間の間のデュレーションを取得できます。

まず、 durationクラスのbetween()メソッドを使用して、finalTimeinitialTimeの時間差を見つけ、その差を返します。すぐに:

long thirty = Duration.between(initialTime, finalTime).getSeconds();

2番目の例では、 ChronoUnitクラスのbetween()メソッドを使用して、同じ操作を実行します。

long thirty = ChronoUnit.SECONDS.between(initialTime, finalTime);

次に、既存の日付カレンダーを新しい日付/時間に変換する方法を見ていきます。

6. 日付およびカレンダーとの互換性

Java 8は、 toInstant()メソッドを追加しました。これは、既存のDateおよびCalendarインスタンスを新しいDateandTimeAPIに変換するのに役立ちます。

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);

次に、日付時間のフォーマットに移りましょう。

7. 日付および時間フォーマット

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[X85X]のいずれかの書式設定スタイルを渡すことができます。

たとえば、これにより、2015年1月25日06:30:00のLocalDateTimeを表す出力が得られます。

localDateTime
  .format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
  .withLocale(Locale.UK));

Java8コア日付/時間APIで利用可能な代替案を見てみましょう。

8. バックポートと代替オプション

8.1. ThreeTenプロジェクトの使用

Java7またはJava6からJava8への移行を進めており、日時APIを使用したい組織の場合、ThreeTenプロジェクトはバックポート機能を提供します。

開発者は、このプロジェクトで利用可能なクラスを使用して、新しいJava 8 DateおよびTimeAPIと同じ機能を実現できます。 そして、Java 8に移行すると、パッケージを切り替えることができます。

ThreeTenプロジェクトのアーティファクトは、 Maven CentralRepositoryにあります。

<dependency>
    <groupId>org.threeten</groupId>
    <artifactId>threetenbp</artifactId>
    <version>1.3.1</version>
</dependency>

8.2. 城田タイムライブラリー

Java 8 DateおよびTimeライブラリのもう1つの代替手段は、Joda-Timeライブラリです。 実際、Java 8 Date / Time APIは、Joda-Timeライブラリの作成者(Stephen Colebourne)とOracleが共同で主導しています。 このライブラリは、Java 8 Date / Timeプロジェクトでサポートされているほとんどすべての機能を提供します。

アーティファクトは、 Maven Central で、以下のpom依存関係をプロジェクトに含めることで見つけることができます。

<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.9.4</version>
</dependency>

9. 結論

Java 8は、開発を容易にするための一貫したAPI設計を備えた豊富なAPIセットを提供します。

上記の記事のコードサンプルは、 Java 8 Date / Timegitリポジトリにあります。