日時 API は Java 8 リリースの最大の特徴の1つです。Java は初めから日付と時刻に対する一貫したアプローチが欠けていましたが、Java 8 の日時 API はコアの Java API に歓迎される追加です。
なぜ新しい Java 日時 API が必要なのか?
Java 8 の日時 API を見る前に、なぜこれが必要なのかを見てみましょう。java の既存の日付および時刻関連クラスにはいくつかの問題があります。そのいくつかは次のとおりです:
- Java の日時クラスは一貫して定義されていません。java.util と java.sql パッケージの両方に Date クラスがあります。また、フォーマットおよび解析クラスは java.text パッケージに定義されています。
- java.util.Date には日付値と時刻値の両方が含まれていますが、java.sql.Date には日付値のみが含まれています。これを java.sql パッケージに含めるのは意味がありません。また、両方のクラスに同じ名前が付けられているため、これ自体が非常に悪い設計です。
- 時間、タイムスタンプ、フォーマット、および解析のための明確に定義されたクラスがありません。解析およびフォーマットの必要には java.text.DateFormat 抽象クラスがあります。通常、SimpleDateFormat クラスが解析およびフォーマットに使用されます。
- すべての日付クラスは変更可能であるため、スレッドセーフではありません。これは Java の日付およびカレンダークラスの最大の問題の1つです。
- 日付クラスは国際化を提供せず、タイムゾーンのサポートもありません。そのため、java.util.Calendar および java.util.TimeZone クラスが導入されましたが、これらも上記にリストされたすべての問題を抱えています。
Date および Calendar クラスに定義されたメソッドには他の問題もありますが、上記の問題が明確に示すように、Java には堅牢な日付時刻 API が必要でした。そのため、Joda Time が Java 日付時刻要件の質的な置き換えとして重要な役割を果たしました。
Java 8 日付時刻設計原則
Java 8 日付時刻 API は JSR-310 の実装です。この新しい日付時刻 API のいくつかの設計原則は次のとおりです:
-
不変性: 新しい日付時刻 API のすべてのクラスは不変であり、マルチスレッド環境に適しています。
-
関心の分離: 新しい API は、人間が読み取れる日付時刻とマシン時刻(Unix タイムスタンプ)を明確に分離します。Date、Time、DateTime、Timestamp、Timezone などのためにそれぞれ別のクラスを定義します。
-
明確さ: メソッドは明確に定義され、すべてのクラスで同じアクションを実行します。例えば、現在のインスタンスを取得するにはnow() メソッドがあります。これらのクラスには、それらのための別個のクラスを持つのではなく、format()メソッドとparse()メソッドが定義されています。
すべてのクラスはFactory Pattern とStrategy Pattern を使用しており、より良い処理が可能です。一度クラスのメソッドを使用すると、他のクラスとの作業も難しくありません。
-
ユーティリティ操作:すべての新しい日付時刻APIクラスには、プラス、マイナス、フォーマット、パース、日付/時刻の個別の部分を取得するなど、一般的なタスクを実行するメソッドが付属しています。
-
拡張可能:新しい日時APIはISO-8601カレンダーシステムで動作しますが、他の非ISOカレンダーとも使用できます。
日時APIパッケージ
Java 8の日時APIには、以下のパッケージが含まれています。
- java.time:これは新しいJava日時APIの基本パッケージです。すべての主要な基本クラスがこのパッケージの一部であり、LocalDate、LocalTime、LocalDateTime、Instant、Period、Durationなどが含まれます。これらのクラスはすべて不変でスレッドセーフです。ほとんどの場合、これらのクラスで一般的な要件を処理するのに十分です。
- java.time.chrono:このパッケージは非ISOカレンダーシステムの汎用APIを定義します。AbstractChronologyクラスを拡張して独自のカレンダーシステムを作成できます。
- java.time.format:このパッケージには、日付時刻オブジェクトのフォーマットおよび解析に使用されるクラスが含まれています。ほとんどの場合、java.timeパッケージの主要なクラスがフォーマットおよび解析メソッドを提供しているため、直接これらのクラスを使用する必要はありません。
- java.time.temporal:このパッケージには時間オブジェクトが含まれており、日付/時間オブジェクトに関連する特定の日付や時刻を求めるために使用できます。たとえば、月の最初や最後の日を求めるためにこれらを使用できます。これらのメソッドは常に「withXXX」の形式を持っているため、これらを簡単に特定することができます。
- java.time.zone パッケージ:このパッケージには、異なるタイムゾーンおよびそれらの規則をサポートするクラスが含まれています。
Java 8 日付時刻 API クラスの例
Java 日付時刻 API の重要な部分のほとんどを見てきました。今は、日付時刻 API の最も重要なクラスを例とともに見ていきましょう。
1. LocalDate
LocalDate は、デフォルトの形式 yyyy-MM-dd で日付を表す不変のクラスです。現在の日付を取得するために now() メソッドを使用できます。また、年、月、日の入力引数を提供して LocalDate インスタンスを作成することもできます。
このクラスは、特定のタイムゾーンで日付を取得するためにZoneIdを渡すnow()のオーバーロードメソッドを提供します。このクラスは、java.sql.Dateと同じ機能を提供します。
コメントでLocalDateメソッドの説明が提供されています。このプログラムを実行すると、次の出力が得られます。
2. LocalTime
LocalTimeは、人間が読みやすい形式の時間を表す不変のクラスです。デフォルトの形式はhh:mm:ss.zzzです。LocalDateと同様に、このクラスはタイムゾーンのサポートを提供し、時、分、秒を入力引数として渡してインスタンスを作成します。
出力:
3. LocalDateTime
LocalDateTimeは、デフォルトの形式であるyyyy-MM-dd-HH-mm-ss.zzzで日時を表す不変の日時オブジェクトです。LocalDateとLocalTimeの入力引数を取るファクトリーメソッドを提供し、LocalDateTimeインスタンスを作成します。
すべての例で、日付/時刻を作成するために無効な引数を提供した場合、java.time.DateTimeExceptionがスローされることがわかりました。これはRuntimeExceptionなので、明示的にキャッチする必要はありません。
私たちはまた、ZoneIdを渡すことで日付/時刻データを取得できることも確認しました。サポートされているZoneId値のリストをそのJavaDocから取得できます。上記のクラスを実行すると、以下の出力が得られます。
4. Instant
Instantクラスは、機械可読な時間形式で動作します。Instantは、UNIXタイムスタンプ形式で日付時刻を格納します。
出力:
Java 8 Date API ユーティリティ
ほとんどの日時の主要なクラスは、日数、週数、月数などのプラス/マイナスのユーティリティメソッドを提供します。日付を調整するためのTemporalAdjuster
および2つの日付間の期間を計算するためのその他のユーティリティメソッドもあります。
出力:
Java 8の日付の解析とフォーマット
日付を異なる形式にフォーマットして、次に文字列を解析して日時オブジェクトを取得することは非常に一般的です。
出力:
Javaの日付APIのレガシー日時サポート
ほとんどのアプリケーションでレガシーの日時クラスが使用されているため、後方互換性が必要です。そのため、レガシークラスを新しいクラスに変換したり、その逆を行うためのいくつかのユーティリティメソッドがあります。
出力:
レガシーのTimeZone
とGregorianCalendar
クラスのtoString()メソッドが非常に冗長で使いづらいことがわかります。
結論
I like this new Date Time API a lot. Some of the most used classes will be LocalDate and LocalDateTime. It’s very easy to work with the new classes. And, having similar methods that does a particular job makes it easy to find. It will take some time from moving legacy classes to new Date Time classes, but I believe it will be worth the time and effort.
Source:
https://www.digitalocean.com/community/tutorials/java-8-date-localdate-localdatetime-instant