( 本記事の目次 )
Date and Time APIの基本
JDK1.0から提供されているjava.util.Date
クラスは、日付を年、月、日、時、分、秒の値として解釈し、さらに、文字列で表現された日付データを構文解析して、Date
オブジェクトとして扱える機能がありました。しかし、国際化対応がなされていなかったり、機能が限られていたりしました。そのため、JDK1.1では、日付と時刻を様々な方法で表すjava.util.Calendar
クラスや、サマータイムなど他の調整を表すjava.util.TimeZone
クラス、フォーマット(書式化)を行うjava.text.DateFormat
クラスが追加されました。
しかし、それでもいくつか問題が残りました。たとえば、java.util.Date
クラスはスレッドセーフでないため、マルチスレッド環境下で使用する際には実装レベルで制御する必要がありました。また、Date
クラスのAPI設計には不備があり、多くのメソッドが非推奨となっています。
それらの不具合を改善するため、Java SE 8でDate and Time APIが導入されました。このAPIは、java.time
パッケージとして提供されています。
Date and Time APIの主な特徴は以下のとおりです。
- 日付、時間、日付/時間のためのクラスが個別に提供されている
- Date and Time APIの各クラスは不変オブジェクト(イミュタブル)となるため、マルチスレッド環境下でも安全に使用できる
- 日時演算のためのAPIが充実している
java.time
パッケージには多くのクラスが含まれていますが、ここでは出題頻度の高いクラス(表2)について解説します。
クラス名 | 説明 |
---|---|
LocalDate | 日付(年-月-日として表示されることが多い)を表す不変オブジェクト |
LocalTime | LocalTimeは、時間(時-分-秒として表示されることが多い)を表す不変オブジェクト |
LocalDateTime | 日付/時間(年-月-日-時-分-秒として表示されることが多い)を表す不変オブジェクト |
Period | 期間を扱う。期間とは日付ベース間隔(「2年3か月と4日」など)である |
各オブジェクト生成のためのメソッド
LocalDate
、LocalTime
、LocalDateTime
の各クラスのコンストラクタにはprivate
修飾子が付与されているため、new
演算子によるインスタンス化はできません。そのかわりに、各クラスに共通で用意されているメソッドを使用してオブジェクトを生成します。ここではLocalDate
クラスのメソッドを紹介します(表3)。
メソッド名 | 説明 |
---|---|
static LocalDate now() | 現在の日付からLocalDateのオブジェクトを取得する |
static LocalDate of(int year,int month,int dayOfMonth) | 年、月、日からLocalDateのオブジェクトを取得する |
static LocalDate parse(CharSequence text) | 2007-12-03などのテキスト文字列からLocalDateのオブジェクトを取得する |
各メソッドを使用したサンプルコードは次のとおりです(Sample1.java)。
import java.time.LocalDate; public class Sample1 { public static void main(String[] args) { LocalDate dateNow = LocalDate.now(); LocalDate dateOf = LocalDate.of(2015, 10, 1); LocalDate dateP = LocalDate.parse("2015-10-01"); System.out.println("LocalDate.now : " + dateNow); System.out.println("LocalDate.of : " + dateOf); System.out.println("LocalDate.parse : " + dateP); } }
LocalDate.now : 2015-11-16 LocalDate.of : 2015-10-01 LocalDate.parse : 2015-10-01
5行目はnow()
メソッドを使用して、現在の日付からLocalDate
オブジェクトを作成しています。また、6行目ではof()
メソッドを使用しています。なお、引数で指定した値が不適切な場合(範囲外である場合)、実行時にDateTimeException
例外が発生します。たとえば、6行目を範囲外にした場合の実行時エラーは次のとおりです。
(現行) 6. LocalDate dateOf = LocalDate.of(2015, 10, 1); //LocalDate dateOf = LocalDate.of(2015, 10, 01); //1を01としてもOK (修正後) //10月は31までであるため、32は範囲外 6. LocalDate dateOf = LocalDate.of(2015, 10, 32);
Exception in thread "main" java.time.DateTimeException: Invalid value for DayOfMonth (valid values 1 - 28/31): 32 at java.time.temporal.ValueRange.checkValidValue(ValueRange.java:311) at java.time.temporal.ChronoField.checkValidValue(ChronoField.java:703) at java.time.LocalDate.of(LocalDate.java:268) at Sample1.main(Sample1.java:6)
また、7行目ではparse()
メソッドを使用しています。日付はハイフン(-
)で区切ります。また、LocalTime
クラスやLocalDateTime
クラスでもparse()
メソッドは提供されており、時刻はコロン(:
)で区切ります。
now()
、of()
、parse()
の各メソッドは、各クラスごとにオーバーロードされています。様々な引数のパターンがあるので、APIで確認してください。