JavaのCalendarクラスの12の使い方とカスタマイズ術

JavaのCalendarクラスの使い方とカスタマイズJava
この記事は約27分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

皆さん、こんにちは!

Javaプログラミングで日付や時間を扱いたいと思ったことはありませんか?

そんなときに役立つのがJavaのCalendarクラスです。

でも、このクラスの機能は多く、どう使えばいいのか分からない、という方も多いでしょう。

この記事では、JavaのCalendarクラスについて、その基本的な使い方から応用テクニック、注意点まで、初心者から中級者まで理解できるように詳しく解説していきます。

まずは、Calendarクラスの基本から見ていきましょう。

●Calendarクラスの基本

○Calendarクラスとは

Calendarクラスとは、Javaで日時を扱うためのクラスです。

日付、時間、年、月、日、時、分、秒、ミリ秒といった時間に関する情報を取得したり、設定したりすることができます。

Javaのjava.utilパッケージに含まれていて、非常に多機能なので多くの場面で使われます。

○Calendarクラスのインスタンス作成方法

Calendarクラスのインスタンスを作成する方法は主に二つあります。

一つはgetInstanceメソッドを使用する方法、もう一つはnewキーワードを使用して直接インスタンスを作成する方法です。

□getInstanceメソッドを使用する方法

この方法は一般的で、簡単に使えます。

// getInstanceメソッドを使ってCalendarクラスのインスタンスを取得
Calendar calendar = Calendar.getInstance();

このコードで作成されたcalendarオブジェクトは、実行された瞬間の日時情報を保持しています。

短いコードで瞬間の日時情報を取得できるので、多くの場面で使用されます。

□newキーワードを使用する方法

これは少し特殊なケースで、通常はあまり使用されません。

getInstanceメソッドを使用する方がほとんどです。

ですが、知っておくと便利な場面もありますので、一応紹介しておきます。

// グレゴリオ暦(GregorianCalendar)を直接インスタンス化
Calendar calendar = new GregorianCalendar();

new GregorianCalendar()としていますが、このGregorianCalendarCalendarクラスのサブクラスです。

この方式で作成した場合も、実行された瞬間の日時情報を保持しています。

●基本的な使い方

プログラムで日時を扱う必要が出たとき、Calendarクラスは避けて通れない存在です。

基本的な使い方をしっかり押さえておけば、日時に関する様々な操作がスムーズに行えます。

さっそく具体的なサンプルコードと共に学びましょう。

○サンプルコード1:現在の日時を取得する

Calendarクラスで最もよく使われるのが、現在の日時を取得することです。

import java.util.Calendar;

public class Main {
    public static void main(String[] args) {
        // Calendarインスタンスの取得
        Calendar calendar = Calendar.getInstance();

        // 年、月、日、時、分、秒を取得
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;  // 月は0から始まるため、1を加算
        int day = calendar.get(Calendar.DATE);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int minute = calendar.get(Calendar.MINUTE);
        int second = calendar.get(Calendar.SECOND);

        // 現在日時の出力
        System.out.println(year + "年" + month + "月" + day + "日 " +
                           hour + "時" + minute + "分" + second + "秒");
    }
}

このコードでは、Calendarのインスタンスを作成した後、そのインスタンスのgetメソッドを用いて年、月、日、時、分、秒を取得しています。

取得した日時情報は、コンソールに出力されます。

コードを実行すると、例えば「2023年9月23日 12時34分56秒」といった形で現在の日時が出力されます。

○サンプルコード2:特定の日時を設定する

特定の日時を設定したい場合は、setメソッドを使用します。

import java.util.Calendar;

public class Main {
    public static void main(String[] args) {
        // Calendarインスタンスの取得
        Calendar calendar = Calendar.getInstance();

        // 2023年10月1日12時0分0秒に設定
        calendar.set(2023, Calendar.OCTOBER, 1, 12, 0, 0);

        // 年、月、日、時、分、秒を取得
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;  // 月は0から始まるため、1を加算
        int day = calendar.get(Calendar.DATE);
        int hour = calendar.get(Calendar.HOUR_OF_DAY);
        int minute = calendar.get(Calendar.MINUTE);
        int second = calendar.get(Calendar.SECOND);

        // 設定した日時の出力
        System.out.println(year + "年" + month + "月" + day + "日 " +
                           hour + "時" + minute + "分" + second + "秒");
    }
}

このコードを実行すると、設定した「2023年10月1日12時0分0秒」がコンソールに出力されます。

○サンプルコード3:曜日を取得する

日付から曜日を知りたい場面もあるでしょう。

それにもCalendarクラスは対応しています。

import java.util.Calendar;

public class Main {
    public static void main(String[] args) {
        // Calendarインスタンスの取得
        Calendar calendar = Calendar.getInstance();

        // 曜日を取得
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);

        // 曜日の出力
        String[] weekName = {"", "日", "月", "火", "水", "木", "金", "土"};
        System.out.println("今日は" + weekName[dayOfWeek] + "曜日です。");
    }
}

このコードを実行すると、「今日は○曜日です。」といった形で今日の曜日が出力されます。

特に、Calendar.DAY_OF_WEEKフィールドを用いて曜日を取得しています。

得られる値は1(日曜)から7(土曜)までの整数です。

●日時の計算方法

日時の加算や減算は、プログラムでよく行われる操作です。

Calendarクラスを使えば、日、週、月、年単位で簡単に日時の計算ができます。

今回は、その具体的な方法をサンプルコードと共にご紹介します。

○サンプルコード4:日時を加算する

特定の日時に何日後、何月後、何年後などの日時は何かを計算したいという場面がよくあります。

Calendarクラスのaddメソッドを使用することで、このような計算が可能です。

import java.util.Calendar;

public class Main {
    public static void main(String[] args) {
        // Calendarインスタンスの取得
        Calendar calendar = Calendar.getInstance();

        // 現在日時の出力(加算前)
        System.out.println("加算前: " + calendar.getTime());

        // 日時を加算(5日後、3ヶ月後、2年後)
        calendar.add(Calendar.DATE, 5);
        calendar.add(Calendar.MONTH, 3);
        calendar.add(Calendar.YEAR, 2);

        // 現在日時の出力(加算後)
        System.out.println("加算後: " + calendar.getTime());
    }
}

このコードでは、まず現在の日時を取得しています。

その後、addメソッドを使って、5日後、3ヶ月後、2年後の日時に加算しています。最後に加算後の日時を出力しています。

コードを実行すると、例えば加算前が「2023-09-23」とした場合、加算後は「2025-12-28」になることが確認できます。

○サンプルコード5:日時を減算する

日時の減算もまた、addメソッドを使いますが、減算したい数値をマイナスで指定します。

import java.util.Calendar;

public class Main {
    public static void main(String[] args) {
        // Calendarインスタンスの取得
        Calendar calendar = Calendar.getInstance();

        // 現在日時の出力(減算前)
        System.out.println("減算前: " + calendar.getTime());

        // 日時を減算(5日前、3ヶ月前、2年前)
        calendar.add(Calendar.DATE, -5);
        calendar.add(Calendar.MONTH, -3);
        calendar.add(Calendar.YEAR, -2);

        // 現在日時の出力(減算後)
        System.out.println("減算後: " + calendar.getTime());
    }
}

このコードでは、同様に現在日時を取得し、その後5日前、3ヶ月前、2年前に減算しています。減算後の日時も出力しています。

コードを実行すると、例えば減算前が「2023-09-23」の場合、減算後は「2021-06-18」となります。

●日時の比較方法

プログラミングにおいて日時の比較は非常に一般的な処理です。

スケジュール管理、データの有効期限チェックなど、多くの場面で使われます。

JavaのCalendarクラスでは、特定の日時が別の日時より前であるか、後であるか、それとも同じであるかを簡単に判断する方法があります。

ここでは、その具体的な実装について詳しく説明します。

○サンプルコード6:二つの日時を比較する

日時の比較にはcompareToメソッドを使用します。

このメソッドは、対象となるCalendarオブジェクトと引数で与えられた別のCalendarオブジェクトを比較して、結果を整数で返します。

import java.util.Calendar;

public class CompareDates {
    public static void main(String[] args) {
        // 2つのCalendarインスタンスを作成
        Calendar calendar1 = Calendar.getInstance();
        Calendar calendar2 = Calendar.getInstance();

        // calendar2の日付を5日後に設定
        calendar2.add(Calendar.DATE, 5);

        // 二つの日時を比較
        int result = calendar1.compareTo(calendar2);

        // 比較結果に基づいて処理
        if (result > 0) {
            System.out.println("calendar1の日時はcalendar2よりも未来です。");
        } else if (result < 0) {
            System.out.println("calendar1の日時はcalendar2よりも過去です。");
        } else {
            System.out.println("calendar1とcalendar2の日時は同じです。");
        }
    }
}

このコードでは、まず2つのCalendarインスタンスを作成しています。

そのうちの一つ(calendar2)の日付を5日後に設定しています。

その後、compareToメソッドを用いてcalendar1calendar2を比較し、結果をresultに保存しています。

最後に、その比較結果に基づいてメッセージを出力しています。

このコードを実行すると、”calendar1の日時はcalendar2よりも過去です。”と出力されます。

これはcalendar1が現在日時、calendar2が5日後の日時であり、calendar1calendar2よりも過去であるためです。

●フォーマットと出力

日時の取得や操作ができたら、次はそれをどう表示するかが問題になります。

プログラムで扱いやすい形式と、人が読みやすい形式は必ずしも一致しないため、フォーマットの調整が必要になる場面も多いです。

ここでは、JavaのCalendarクラスと併用可能なSimpleDateFormatクラスを用いて、日時のフォーマットとその出力方法について詳細に説明します。

○サンプルコード7:SimpleDateFormatを使って日時をフォーマットする

日時のフォーマットにはSimpleDateFormatクラスがよく用いられます。

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

public class DateFormatExample {
    public static void main(String[] args) {
        Calendar calendar = Calendar.getInstance();
        Date date = calendar.getTime();

        // SimpleDateFormatオブジェクトを作成
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");

        // 日時をフォーマット
        String formattedDate = sdf.format(date);

        // 出力
        System.out.println(formattedDate);
    }
}

このコードでは、CalendarクラスのインスタンスからDateオブジェクトを取得しています。

そしてSimpleDateFormatオブジェクトを作成し、そのformatメソッドで日時をフォーマットしています。

フォーマットの指定は”yyyy/MM/dd HH:mm:ss”となっており、年、月、日、時、分、秒をそれぞれ表示します。

このコードを実行すると、現在の日時が”yyyy/MM/dd HH:mm:ss”形式でコンソールに出力されます。

具体的には、”2023/09/23 12:34:56″のような形式で日時が表示されるでしょう(時刻部分は実行時のものとなるため、この値は仮のものです)。

○サンプルコード8:コンソールに出力する

Javaで最も簡単な出力方法は、System.out.printlnを使用することです。

このメソッドは非常に便利で、上のサンプルコード7でも用いられました。

しかし、実際のアプリケーションでは、ファイルへの出力やネットワーク越しの出力も必要とされる場合があります。

import java.io.FileWriter;
import java.io.IOException;

public class FileOutputExample {
    public static void main(String[] args) {
        String formattedDate = "2023/09/23 12:34:56";  // 仮の日時データ
        try (FileWriter fw = new FileWriter("output.txt")) {
            fw.write(formattedDate);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

このコードでは、FileWriterクラスを用いてテキストファイル(output.txt)に日時を出力しています。

ファイル出力は例外処理が必要ですので、try-catchブロックで囲んでいます。

このコードを実行すると、カレントディレクトリにoutput.txtというファイルが生成され、その中に”2023/09/23 12:34:56″という日時データが保存されます。

●時間帯とロケール

JavaのCalendarクラスでは、時差や地域に依存した情報を処理する際に「時間帯(Time Zone)」と「ロケール(Locale)」を設定することができます。

これらの設定は、国際化されたアプリケーションやサービスを開発する際に非常に有用です。

○サンプルコード9:時間帯を設定する

日本以外の時間帯で日時を取得したい場合、TimeZoneクラスを使用して設定することができます。

import java.util.Calendar;
import java.util.TimeZone;

public class TimeZoneExample {
    public static void main(String[] args) {
        // TimeZoneオブジェクトを作成
        TimeZone timeZoneNewYork = TimeZone.getTimeZone("America/New_York");

        // CalendarインスタンスにTimeZoneを設定
        Calendar calendar = Calendar.getInstance(timeZoneNewYork);

        // 時間帯に合わせた現在の時刻を出力
        System.out.println("New York Time: " + calendar.get(Calendar.HOUR_OF_DAY) + ":" + calendar.get(Calendar.MINUTE));
    }
}

このコードではTimeZoneクラスを用いてNew York(ニューヨーク)の時間帯を設定しています。

そして、Calendar.getInstance(timeZoneNewYork)でCalendarインスタンスを取得し、その時間帯に合わせた時刻を出力しています。

コードを実行すると、コンソールにはニューヨークの現在時刻が「New York Time: 〇〇:〇〇」の形式で表示されます。

こちらの〇〇は実行時のニューヨークの時間に依存します。

○サンプルコード10:ロケールを設定する

Localeクラスを用いて、地域に応じたカレンダー設定を行うことができます。

import java.util.Calendar;
import java.util.Locale;

public class LocaleExample {
    public static void main(String[] args) {
        // フランスのロケールを設定
        Locale localeFrance = Locale.FRANCE;

        // Calendarインスタンスにロケールを設定
        Calendar calendar = Calendar.getInstance(localeFrance);

        // フランスの曜日を出力
        System.out.println("Jour de la semaine en France: " + calendar.getDisplayName(Calendar.DAY_OF_WEEK, Calendar.LONG, localeFrance));
    }
}

このコードで行っているのは、フランスのロケールを設定してCalendarインスタンスを取得し、その後フランス語で現在の曜日を出力しています。

コードを実行すると、「Jour de la semaine en France: 〇〇」という形で、現在の曜日がフランス語で表示されます。

この〇〇は実行時の曜日(フランス語)になります。

●応用例

JavaのCalendarクラスは、基本的な日時操作から応用的な用途まで幅広く利用できます。

ここでは、実際のプロジェクトで役立つかもしれない応用例を2つご紹介します。

○サンプルコード11:カレンダーアプリの簡単なデモ

Javaを使ってシンプルなカレンダーアプリを作成する例をご覧ください。

import java.util.Calendar;

public class SimpleCalendarDemo {
    public static void main(String[] args) {
        // Calendarインスタンスを取得
        Calendar calendar = Calendar.getInstance();

        // 現在の年、月、日を取得
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1;  // 月は0から始まるため、+1する
        int day = calendar.get(Calendar.DAY_OF_MONTH);

        // 現在の年月日を表示
        System.out.println("今日の日付: " + year + "年" + month + "月" + day + "日");

        // 1週間後の日付を取得
        calendar.add(Calendar.WEEK_OF_YEAR, 1);
        year = calendar.get(Calendar.YEAR);
        month = calendar.get(Calendar.MONTH) + 1;
        day = calendar.get(Calendar.DAY_OF_MONTH);

        // 1週間後の日付を表示
        System.out.println("1週間後の日付: " + year + "年" + month + "月" + day + "日");
    }
}

上記のコードでは、まず現在の年月日を取得して出力しています。その後、1週間後の日付を計算し、それも出力しています。

このプログラムを実行すると、「今日の日付」と「1週間後の日付」がそれぞれ出力されます。

具体的な出力内容は、プログラムを実行した日によって異なります。

○サンプルコード12:タイマー機能の実装

次に、Calendarクラスを用いてタイマー機能を実装する例を見てみましょう。

import java.util.Calendar;
import java.util.Timer;
import java.util.TimerTask;

public class TimerDemo {
    public static void main(String[] args) {
        // Timerインスタンスを生成
        Timer timer = new Timer();

        // 5秒後に実行するタスクを設定
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                Calendar calendar = Calendar.getInstance();
                int hour = calendar.get(Calendar.HOUR_OF_DAY);
                int minute = calendar.get(Calendar.MINUTE);
                int second = calendar.get(Calendar.SECOND);

                System.out.println("タイマー発火: " + hour + "時" + minute + "分" + second + "秒");
            }
        }, 5000);
    }
}

このコードでは、JavaのTimerクラスを用いて5秒後にタイマーが発火するように設定しています。

タイマーが発火した際には、現在の時分秒を出力します。

このプログラムを実行すると、5秒後に「タイマー発火: 〇〇時〇〇分〇〇秒」と出力されます。

出力される時間はプログラムを実行した環境の現地時間に基づいています。

●注意点と対処法

JavaのCalendarクラスを使いこなす上で注意すべきポイントとその対処法をいくつか紹介します。

理解しておくことで、より効率的かつ安全なコーディングが可能となります。

○デプリケーションについて

JavaのAPIが更新される際、古いメソッドやクラスは時として非推奨(deprecated)とされます。

Calendarクラスにも非推奨とされているメソッドが存在します。

例えば、CalendarクラスのgetYear()メソッドは非推奨です。

代わりにget(Calendar.YEAR)を使うべきです。

import java.util.Calendar;

public class DeprecatedMethodExample {
    public static void main(String[] args) {
        Calendar calendar = Calendar.getInstance();
        // 非推奨のメソッドを使用する例(非推奨)
        // int year = calendar.getYear(); 

        // 推奨される方法
        int year = calendar.get(Calendar.YEAR);  
        System.out.println("現在の年:" + year);
    }
}

このコードは、非推奨のgetYear()メソッドを使わず、get(Calendar.YEAR)を使用して年を取得しています。

この変更により、将来的なJavaのバージョンアップで問題が起きにくくなります。

このプログラムを実行すると、システムの現在の年が出力されます。

例えば、実行年が2023年であれば「現在の年:2023」と表示されるでしょう。

○スレッドセーフについて

Calendarクラスのインスタンスはスレッドセーフではありません。

複数のスレッドから同時にアクセスする場合、データの不整合が生じる可能性があります。

この問題に対処する一つの方法は、synchronizedブロックを使用して排他制御を行うことです。

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

        synchronized(calendar) {
            // Calendarに対する操作
            calendar.add(Calendar.DATE, 1);
            System.out.println("明日の日付:" + calendar.getTime());
        }
    }
}

このサンプルコードでは、synchronizedブロックを使用してCalendarオブジェクトへのアクセスを同期化しています。

このようにして、複数のスレッドからCalendarインスタンスを安全に操作できます。

このコードを実行すると、システムの現在日時に1日加算した日付が出力されます。

例えば、今日が2023年9月24日であれば、「明日の日付:Sun Sep 25 00:00:00 JST 2023」と表示されます。

●カスタマイズ方法

JavaのCalendarクラスは多機能であるが、特定の要件に対応するためにカスタマイズすることも可能です。

○既存メソッドのオーバーライド

Javaでは、既存のクラスから新しいクラスを派生させることで、既存のメソッドをオーバーライド(上書き)することができます。

この手法を使えば、Calendarクラスの特定の動作を変更することができます。

import java.util.Calendar;
import java.util.GregorianCalendar;

public class CustomCalendar extends GregorianCalendar {
    @Override
    public int get(int field) {
        if (field == Calendar.MONTH) {
            return super.get(field) + 1;  // 月は1から12の値で返す
        }
        return super.get(field);
    }

    public static void main(String[] args) {
        Calendar cal = new CustomCalendar();
        System.out.println("カスタムした月:" + cal.get(Calendar.MONTH));
    }
}

このサンプルコードでは、GregorianCalendarCalendarクラスの具象クラス)を継承して新たなCustomCalendarクラスを作成しています。

get(int field)メソッドをオーバーライドして、月の値が1から12で返るようにしています(JavaのCalendarクラスでは通常0から11)。

このコードを実行すると、「カスタムした月:〇〇」と出力されます。ここでの〇〇は、1から12までの月の値です。

もし、実行時点で9月であれば「カスタムした月:9」と表示されるでしょう。

○独自のカレンダー機能の追加

既存の機能だけでは不足する場合、独自のメソッドを追加することもできます。

例えば、特定の日付が平日かどうかを判定する機能を追加したい場合、次のように実装できます。

public class CustomCalendarWithWeekday extends GregorianCalendar {
    // 平日かどうかを判定するメソッド
    public boolean isWeekday() {
        int dayOfWeek = this.get(Calendar.DAY_OF_WEEK);
        return dayOfWeek != Calendar.SATURDAY && dayOfWeek != Calendar.SUNDAY;
    }

    public static void main(String[] args) {
        CustomCalendarWithWeekday cal = new CustomCalendarWithWeekday();
        boolean isWeekday = cal.isWeekday();
        System.out.println("今日は平日か:" + isWeekday);
    }
}

このコードでは、isWeekday()という独自のメソッドをCustomCalendarWithWeekdayクラスに追加しています。

このメソッドは、その日が平日(土日以外)であればtrueを、そうでなければfalseを返します。

このコードを実行すると、「今日は平日か:true」または「今日は平日か:false」と表示されます。

もし実行日が平日であればtrueが、土日であればfalseが出力されるでしょう。

まとめ

この記事を通じて、JavaのCalendarクラスについて多くの側面を深く探求しました。

基本的な使い方から日時の計算、比較、そしてカスタマイズまで、幅広いトピックを網羅しました。

特にサンプルコードを多用することで、理論だけでなく実践的な知識も身につけることができたでしょう。

JavaのCalendarクラスは非常に強力で柔軟性があり、多くの日時処理タスクに対応可能です。

しかし、その強力さゆえに多くのメソッドやパラメータが存在するため、適切に使いこなすにはしっかりとした理解が必要です。

この記事が、その理解の一助となれば幸いです。