Calendarの使い方
java.util.Calendarのまとめ。Java SE 8よりDate And Time APIに変換するため、Instantの出力が可能になる。またCalendar.Builderが追加された。
Java | Java SE 8 |
概要

CalendarはJavaにおける日時クラス。Dateとは異なりタイムゾーンまで保持する。また日時計算も可能。各地域のカレンダーの違いにより実装クラスを作ることが可能でいくつか存在する。和暦を扱えるJapaneseImperialCalendarもその一つだがパッケージプライベートになっている。よって基本的にはGregorianCalendarが使われることが多い。
Date And Time APIの登場により、そちらへ徐々に移行されると考えられる。ただベースの時間体系が全く異なり直接の相互変換もできないため、非推奨にならず維持はされていく可能性が高い(あくまで予想)。
主な特徴は次の通り。
-
Dateと異なりタイムゾーンも保持している。
-
日時計算が可能。デフォルトでは非厳密モード。
-
月はインデックスになっているので要注意。
基本的な使い方
生成
カレンダーはファクトリメソッドがあるのでそちらから生成するのが基本。デフォルトのタイムゾーンおよびロケールで現在日時になる。
Calendar calendar = Calendar.getInstance();
Java SE 8 よりCalendar.Builderが追加された。いわゆるビルダーパターンなっている。うれしいことに和暦を扱えるカレンダーもこれまでより簡単に作ることができるようになった。
Calendar calendar = new Calendar.Builder().setCalendarType("japanese")
.build();
カレンダーフィールド
get()、set()、add()、roll()等でカレンダーの各フィールドを指定するのにint値を受け取る。この値はCalendarクラスのフィールド値にstaticで定義されている。
API仕様にも定義されているがAPI仕様はアルファベット順になって見づらいため、次のページにまとめた。
-
参考: Calendarフィールド値一覧
非厳密モードと厳密モード
Calendarでは年、月、日、時、分などの各フィールドを個別に設定可能なので、操作上は簡単に矛盾した値(例えば9月31日)を設定できる。そのとき、非厳密モードと厳密モードで動作が異なる。
非厳密モードでは9月31日を設定すると10月1日として再計算する。厳密モードでは例外になる。デフォルトは非厳密モードで、setLenient()により設定する。非厳密モードの再計算時の解釈はAPI仕様を確認する。
フィールドの取得・設定
get()で取得してset()で設定する。set()についてはあり得ない値を設定する場合は、再計算に注意する。
メソッド | 概要 |
---|---|
get(int field) |
指定されたフィールドを取得する。 |
set(int field,int amount) |
指定されたフィールドにamountを設定する。 |
フィールドの加算・減算
add()、roll()を使う。両方とも加算・減算をするメソッドであるが繰り上がりかたの仕様が異なる。
メソッド | 概要 |
---|---|
add() |
フィールドに指定されたamount追加する。 |
roll() |
大きいフィールドを変更せずにフィールドに指定されたamount追加する。 |
メソッド | 9月30日+1日を計算する |
---|---|
add() |
結果:10月1日 |
roll() |
結果:9月1日 |
比較
equals()による比較は実装クラスによって変更される可能性があるため、時間の比較であればcompareTo()を使う。compareTo()の比較ではミリ秒単位で行われる。
Date And Time APIへの変換
Java SE 8よりDate And Time APIが導入され、Date/CalendarもInstantを介してではあるが変換が可能になっている。詳しい変換方法は次のページにまとめた。
Tips
月末日を求める
月末日は月によって異なり閏年かどうかによっても変わるので、手計算では求めるのが難しい。なのでフィールドの最大値を取得するgetActualMaximum()をうまく利用する。
Calendar calendar = new GregorianCalendar(2012, Calendar.FEBRUARY, 10);
//日付フィールドの最大値を取得する。2012年はうるう年なので「29」になる
int endDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
Appendix A: 参考
Appendix B: 改訂履歴
-
v1.0, 2016-08-02: 初稿