Java
2022.01.19
JavaのCalendarクラスの使い方!add・setメソッドで日付操作
2023.11.15

1.JavaのCalendarクラスとは?

Calendarクラスは、Javaにおいて日付や時刻を操作するために利用するクラスです。

特定の日付を指定して操作を行なったり、○日後や○ヶ月後といった計算をしたりと、日時に関するさまざまな操作や計算が可能です。

①Dateクラスとの違いは?

Calendarと同様に、日付を取り扱うクラスとして「Date」クラスが存在します。


Dateは現在時刻取得することは得意ですが、「2000年4月1日」といった特定の日付を指定できません。(厳密には生成できるのですが、国際化に対応していないなどの問題があり、Java8で非推奨となりました。)


Dateを用いるメリットはほぼないと言えますが、インスタンス生成の速度はCalendarよりDateの方が高速に動作します。


そのため、Dateはミリ秒までを含む日時をタイムスタンプとしてデータベースに保存するような場合によく利用します。


DateとCalendarを使い分ける場合、


・現在日時を利用したい場合にはDate

・日付を指定し、複雑な日時計算をしたい場合にはCalendar

というように覚えましょう。

2.Calendarクラスの基本的な使い方


ここでは、Calandarクラスの基本的な使い方を紹介します。

①Calendarインスタンスの生成

まずは、本日の日付でインスタンスを生成する方法から紹介します。

import java.util.Calendar;

public class Main {
    public static void main(String[] args) throws Exception {
        
        // インスタンスを生成
        Calendar calendar = Calendar.getInstance();
    }
}

Calendarクラスのインスタンスを作成するには、以下のコードを作成します。

Calendar calendar = Calendar.getInstance();

newを利用してインスタンスを生成していないことに注意しましょう。

日付を指定しての生成

次に、日付を指定するようにコードを修正してみましょう。


Calendarクラスはインスタンス生成時に日付を指定できません。よって、インスタンス生成後、以下のようにsetメソッドを利用して日付を設定します。

import java.util.Calendar;

public class Main {

    public static void main(String[] arg) {

        Calendar calendar = Calendar.getInstance();
        // 日付を指定
        calendar.set(2020, 11, 20);

        // フォーマットを変更して表示
        System.out.println(String.format("%d年%d月%d日",
                calendar.get(Calendar.YEAR),
                calendar.get(Calendar.MONTH)+1,
                calendar.get(Calendar.DAY_OF_MONTH)));
    }
}

これを実行すると、以下のように表示されます。

2020年12月20日





3.Calendarクラスのメソッドの使い方


基本的な使い方を学んだところで、先ほど登場したメソッドについて詳しく解説していきます。

①getメソッドで日時を取得する

getメソッドは、calendarに設定している年や月といった情報を取得するために利用します。

たとえば、「年」を取得するには以下のようなコードを書きます。

int year = calendar.get(Calendar.YEAR);

取得できるフィールド一覧

getメソッドの引数として指定できる内容は、Calendarクラスの中で定数として定義されています。

これらの定数を指定することで、その内容を取得できるので、Calendarを使う際には以下の項目と内容を覚えておきましょう。

フィールド名取得できる値
YEAR
MONTH月(1月=0ではじまり、12月=11まで)
DATE
DAY_OF_WEEK曜日(日曜=0ではじまり、土曜=6まで)
HOUR_OF_DAY時間(24時間表記)
AM_PM午前(0)か午後(1)
HOUR時間(12時間表記)
MINUTE
SECOND
MILLISECONDミリ秒

②setメソッドで日時を設定する

setメソッドを使うことで、特定の日付を指定できます。

日付だけでなく、時間を含む指定も可能です。

Calendar calendar = Calendar.getInstance();

// 日付を指定する
calendar.set(2020, 9, 15);

// 時間を含めて指定する
calendar.set(2020, 9, 15, 10, 15, 30);

また、特定の値を書き換えることも可能です。


例として、時刻の部分を0に変えることで、本日の0時を生成するコードを見てみましょう。


第一引数に変更する項目を指定し、第二引数に変更したい値である「0」を代入します。

// 時間
calendar.set(Calendar.HOUR, 0);
// 分
calendar.set(Calendar.MINUTE, 0);
// 秒
calendar.set(Calendar.SECOND, 0);
// ミリ秒
calendar.set(Calendar.MILLISECOND, 0);

③addメソッドで日付を加算/減算する

日付の計算をしたい場合は「add」メソッドを利用します。


例として、「指定日付の1週間後」を計算したい場合のサンプルコードを見てみましょう。

Calendar calendar = Calendar.getInstance();

// 日付を指定する(2020/10/15)
calendar.set(2020, 9, 15);

// 1週間後を取得
calendar.add(Calendar.DATE, 7);

System.out.println(String.format("%d年%d月%d日",
        calendar.get(Calendar.YEAR),
        calendar.get(Calendar.MONTH)+1,
        calendar.get(Calendar.DAY_OF_MONTH)));

これを実行すると以下のように出力されます。

2020年10月22日

逆に、「1週間前」を指定する場合には「-7」を指定することで減算されます。

Calendar calendar = Calendar.getInstance();

// 日付を指定する(2020/10/15)
calendar.set(2020, 9, 15);

// 1週間後を取得
calendar.add(Calendar.DATE, -7);

System.out.println(String.format("%d年%d月%d日",
        calendar.get(Calendar.YEAR),
        calendar.get(Calendar.MONTH)+1,
        calendar.get(Calendar.DAY_OF_MONTH)));

実行結果

2020年10月8日

月またぎやうるう年の計算は?

Calendarクラスは、月をまたぐ場合や、うるう年を含む場合も正常に計算してくれます。

Calendar calendar = Calendar.getInstance();

// うるう年の2/28
calendar.set(2020, 1, 28);

calendar.add(Calendar.DATE, 1);

// フォーマットを変更して表示
System.out.println(String.format("%d年%d月%d日",
        calendar.get(Calendar.YEAR),
        calendar.get(Calendar.MONTH)+1,
        calendar.get(Calendar.DAY_OF_MONTH)));

// うるう年ではない2/28
calendar.set(2021, 1, 28);

calendar.add(Calendar.DATE, 1);

// フォーマットを変更して表示
System.out.println(String.format("%d年%d月%d日",
        calendar.get(Calendar.YEAR),
        calendar.get(Calendar.MONTH)+1,
        calendar.get(Calendar.DAY_OF_MONTH)));

これを実行すると、以下のように表示されます。

2020年2月29日
2021年3月1日

Calendarを利用して日付を計算すれば、年や月ごとの日数を考慮する必要がありません。


アラーム機能やカレンダー機能を実装する場合に活用できるテクニックなので、ぜひ覚えておきましょう。

4.日付の形式を指定する方法

calendarに設定されている日付を表示する場合、毎回getメソッドを使うのは面倒です。


その場合には、SimpleDateFormatを利用することで、フォーマット指定した日付取得が可能です。

import java.util.Calendar;
import java.text.SimpleDateFormat;

public class Main {
    public static void main(String[] args) throws Exception {
        
        Calendar calendar = Calendar.getInstance();

        // 2020/11/15 9:31
        calendar.set(2020, 10, 15, 9, 31);
        SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 HH:mm");

        System.out.println(format.format(calendar.getTime()));
    }
}

これを実行すると、以下のように出力されます。

2020年11月15日 09:31

このように、SimpleDateFormatを指定することで、自在なフォーマットで出力できるようになります。

よく使うフォーマット

フォーマットの表示でよく利用する内容を紹介します。

フォーマット出力例説明
yyyy/MM/dd2021/10/15西暦年月日
HH:mm9:31時刻(24時間表示)
a hh:mmAM 09:31時刻(12時間表記)
yyyy/MM/dd HH:mm:ss:SSS2020/11/15 09:31:51:581ミリ秒まで含んだ日時


たとえば、年であれば「yyyy」、月であれば「MM」といったように、表示したい項目に対する単語が設定されています。


これらの単語を組み合わせることで、自由に日付フォーマットを設定可能です。


利用できる単語は公式リファレンスに載っていますので、利用する際には参考にしてください。
https://docs.oracle.com/javase/jp/8/docs/api/java/text/SimpleDateFormat.html



5.Calendar型とDate型の変換方法


Calendar型とDate型の変換方法について紹介します。


Calendarクラスには、Date型と相互変換を容易に行うためのメソッドが用意されています。

①Calendar型からDate型へ変換

Calendar型からDate型へ変換する場合には、getTime()メソッドを利用します。

Date date = calendar.getTime();

②Date型からCalendar型へ変換

Date型からCalendar型に変換するには、setTime()メソッドを利用します。

Date date = new Date();

Calendar calendar = Calendar.getInstance();
calendar.setTime(date);



6.Calendarクラスを使用する際の注意点


最後に、Calendarクラスを利用する上での注意点を紹介します。

①「月」の値は0〜11で指定する

Calendarクラスを使う際の注意点として、月は0から始まることに気をつけましょう。
1月は0、2月は1、そして12月は11として扱われます。


Calendarに関するバグのよくある報告例として、

「11月までは問題なく動いていたが、12月になった途端にエラーになった。」

ということがあります。


Calendarで日付を指定する際に-1をし忘れたため、「存在しない日付指定」としてエラーとなってしまうのです。


特に、ユーザーが入力した内容からCalendarのインスタンスを生成しようとした場合、-1の計算を忘れると予期しないエラーが発生します。

境界値チェックをしっかりと!

このようなバグは見落とす場合が多く、また発見が難しいです。
そのため、テストをしっかりとして漏れがないことを確認することが大事です。


テストの観点として、「境界値」をしっかりとテストすることを心がけると良いでしょう。


日付に関するプログラムを作る場合、以下のことを忘れずにテストしましょう。


・月またぎ(月末が30日と31日のパターン)をテスト

・年またぎ(12月と次の1月で年が変わるパターン)をテスト

・うるう年の2/29をテスト

これらを加味してテストすることで、もし実装に問題があってもテストで間違いに気づけます。

②今後はDateTime APIという新しい日付処理が主流になる

日時を取り扱うクラスとして、DateやCalendarは古くから使われてきたAPIです。しかし、DateやCalendarには使いにくい点が多く、問題も多数存在しました。


Java8からは日時を取り扱うための新しいクラスとして、「DateTime API」が登場しました。


DateTime APIは、DateやCalendarの弱点を克服した新しい機能であり、


・「日付のみ」や「時刻のみ」を取り扱える
・スレッドセーフである
・タイムゾーンに対応している

といったように、DateとCalendarの両方のメリットを兼ね備えています。

// Dateと同様に、現在時刻を取得できる
LocalDateTime now = LocalDateTime.now();

// Calendarと同様に、日付を指定してインスタンスを生成
// (この場合、2025/10/14 16:45:59 を生成)
LocalDateTime date = LocalDateTime.of(2025, 10, 14, 16, 45, 59);

// 1週間後の日付を生成(元のnowの日付は変わらない)
LocalDateTime nextWeek = now.plusDays(7);

今でも多くの現場でCalendarクラスが利用されていますが、新しいバージョンのJavaではこのDateTime APIの利用が推奨されています。

そのため、今後はDateやCalendarからDateTmie APIへの移行が活発になることが予想されます。


Javaをマスターする上では、それぞれのメリットや利用方法をしっかりと押さえておきましょう。





この記事をシェア