本ページはプロモーションが含まれています

Java入門

Javaでカレンダーを作る方法|祝日対応のサンプルコード付き

CATEGORY
REV.
DRAWN BY
TOM
SHEETS
7枚
Calendar(祝日対応のカレンダーを作る)

トム

SESで約8年、環境を変えられないもどかしさの中にいました。32歳で自社開発企業に転職し、今はClaude Codeと自動化で、仕事も時間も組み直している途中です。
・Javaバックエンドエンジニア(Java歴12年以上)
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎
詳細なプロフィール

𝕏

Javaでカレンダーを作るときに押さえるのは、「1日が何曜日か」と「その月が何日まであるか」の2つだけです。

LocalDateならgetDayOfWeek()とlengthOfMonth()で両方を取得でき、for文1つで曜日のそろったカレンダーを表示できます。

年月を入力して表示する基本コード、授業や課題で指定されやすいCalendarクラス版、振替休日・国民の休日まで判定する祝日対応版を、実際に動かした出力結果付きで紹介します。

この記事でわかること

  • 年月を入力してカレンダーを表示するコード(LocalDate版)
  • 1日の曜日に合わせて日付をずらすfor文の考え方
  • 課題でよく使うCalendarクラス版の書き方と注意点
  • 春分の日・振替休日・国民の休日まで含めた祝日の判定方法
  • 内閣府の祝日CSVを読み込んで祝日を管理する方法

Javaでカレンダーを表示する仕組み

コードを書く前に、カレンダー表示の流れを整理します。

やることは「1日の曜日の分だけ空白を出す」「1日から月末までfor文で数字を出す」「土曜日まで出したら改行する」の3つです。

カレンダーを表示する処理の流れ
1
INPUT / 入力年・月を入力する
2
1日の曜日と月の日数を取得するgetDayOfWeek() と lengthOfMonth()
3
1日の曜日の分だけ空白を出すループの前に1回だけ。日曜始まりなら火曜は空白2マス
4
FOR / 1日〜月末for文で日付を出力し、土曜日まで出したら改行する改行の判定は (day + offset) % 7 == 0
5
月末まで出したらカレンダー完成
NOTE祝日対応版では、手順4で日付を出すときに祝日と日曜日を赤色で表示します。

完成イメージと必要な機能

今回作るカレンダーの仕様は次の3つです。

ポイント

  • 入力した年・月のカレンダーを表示する
  • 日曜始まりで曜日の見出しを付ける
  • 1日の曜日に合わせて日付の位置をずらす

2026年9月を指定すると、次のように表示されるのがゴールです。

2026年9月のカレンダー
 日 月 火 水 木 金 土
        1  2  3  4  5
  6  7  8  9 10 11 12
 13 14 15 16 17 18 19
 20 21 22 23 24 25 26
 27 28 29 30

CalendarクラスとLocalDateどちらで作る?

Javaの標準ライブラリで日付を扱うクラスは、古いCalendarクラスと、Java 8で追加されたLocalDateの2つが代表的です。

結論として、指定がなければLocalDateを選んでください。まずは両方で今日の日付を取得して、書き方の違いを比べます。

Calendarクラスで日付を取得する

Calendarクラスはjava.utilパッケージにある日付クラスで、get()に定数を渡して年・月・日を取り出します。

import java.util.Calendar;

public class CalendarExample {
    public static void main(String[] args) {
        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 + "日");
    }
}

2026年9月24日に実行した結果です。

今日の日付: 2026年9月24日

Calendar.MONTHは0始まり(1月=0)なので、表示するときは+1が必要です。

LocalDateで日付を取得する

LocalDateは、Java 8で追加された日付専用のクラスです。

年・月・日を1始まりで扱い、一度作ると値が変わらないイミュータブル(不変)な設計です。

あわせて読む
import java.time.LocalDate;

public class LocalDateExample {
    public static void main(String[] args) {
        LocalDate today = LocalDate.now(); // 今日の日付を取得
        System.out.println("今日の日付: " + today);
        System.out.println(today.getYear() + "年" + today.getMonthValue() + "月" + today.getDayOfMonth() + "日");
    }
}
今日の日付: 2026-09-24
2026年9月24日

LocalDateはコードが短く、月の0始まりも気にしなくて済みます。

あわせて読む

CalendarクラスとLocalDateの違い

両者の違いを表にまとめます。

項目CalendarクラスLocalDate
導入バージョンJava 1.1Java 8
月の扱い0始まり(1月=0)1始まり(1月=1)
可変性ミュータブル(値が変わる)イミュータブル(値が変わらない)
スレッドセーフ非スレッドセーフスレッドセーフ
位置づけ旧API(新規コードでは避ける)Java 8以降の標準API

Calendarクラスは月が0始まりでバグを生みやすく、値を書き換えられるため意図しない変更も起こります。2026年9月時点の最新LTSはJava 25で、LocalDateはJava 8以降のどのバージョンでも標準で使えます。

既存コードがCalendarを使っている場合は、LocalDate.ofInstant(cal.toInstant(), cal.getTimeZone().toZoneId())(Java 9以降)でLocalDateに変換できます。Calendarのタイムゾーンを引き継ぐ書き方で、ZoneId.systemDefault()を渡すと、Calendarが別のタイムゾーンのときに日付がずれます。新しく書く部分だけLocalDateにして、境目で変換するのが現実的な移行方法です。

後半の祝日カレンダーではLocalDateをMapのキーに使います。LocalDateは値ベースでequals・hashCodeが実装されているため、同じ年月日なら別インスタンスでも正しく一致します。

古いDateクラスは値を書き換えられるため、HashMapのキーに登録した後で値が変わると、そのキーで検索できなくなります。

あわせて読む

LocalDateでカレンダーを表示する(年月入力版)

ここからが本題です。キーボードから年と月を入力し、その月のカレンダーを表示するプログラムを作ります。

サンプルコード(CalendarApp.java)

そのままコピーしてCalendarApp.javaとして保存すれば動きます。Java 8以降で動作し、Java 23で実行を確認しました。

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.Scanner;

public class CalendarApp {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // 年と月を入力してもらう
        System.out.print("年を入力してください: ");
        int year = scanner.nextInt();
        System.out.print("月を入力してください: ");
        int month = scanner.nextInt();
        scanner.close();

        // 1〜12以外の月はLocalDate.ofで例外になるため先にチェックする
        if (month < 1 || month > 12) {
            System.out.println("月は1〜12で入力してください");
            return;
        }
        printCalendar(year, month);
    }

    public static void printCalendar(int year, int month) {
        LocalDate firstDay = LocalDate.of(year, month, 1); // 月の1日
        int lastDay = firstDay.lengthOfMonth();            // 月の日数(28〜31)
        DayOfWeek startDay = firstDay.getDayOfWeek();      // 1日の曜日

        System.out.println(year + "年" + month + "月のカレンダー");
        System.out.println(" 日 月 火 水 木 金 土");

        // getValue()は月曜=1〜日曜=7。% 7で日曜=0〜土曜=6に変換する
        int offset = startDay.getValue() % 7;
        for (int i = 0; i < offset; i++) {
            System.out.print("   "); // 1日の曜日まで空白で埋める
        }

        for (int day = 1; day <= lastDay; day++) {
            System.out.printf("%3d", day);
            if ((day + offset) % 7 == 0) { // 土曜日まで出力したら改行
                System.out.println();
            }
        }
        System.out.println();
    }
}

ポイント

  1. ユーザーが年と月を入力
  2. LocalDateを使って月初めの日付を取得
  3. その月の最終日を計算
  4. 曜日に合わせて空白を出力
  5. 日付を整列して表示

for文で曜日をずらす仕組み

カレンダー表示でつまずきやすいのは、1日を正しい曜日の列に置く処理です。

getDayOfWeek().getValue()は月曜=1〜日曜=7を返します。これを% 7すると日曜=0、月曜=1…土曜=6になり、日曜始まりの列番号として使えます。

2026年9月1日は火曜日なのでoffsetは2です。先に空白を2マス分出してから「1」を出力すると、火曜の列にそろいます。

改行の判定は(day + offset) % 7 == 0です。空白の数と日付を足した合計が7の倍数になった位置が土曜日の列なので、そこで改行します。

2026年9月を出力するfor文の動き(offset = 2)
ROW / 行
出力するもの
(day + offset) % 7
1行目日 月 火 水 木 金 土
空白×2 → 1〜5空白2マスで、1日が火曜の列にそろう
(5 + 2) % 7 = 0 → 改行
2行目
6〜12
(12 + 2) % 7 = 0 → 改行
3行目
13〜19
(19 + 2) % 7 = 0 → 改行
4行目
20〜26
(26 + 2) % 7 = 0 → 改行
5行目
27〜30
lengthOfMonth() = 30 まで出して終了
NOTE9月1日は火曜なので getValue() = 2、offset = 2 % 7 = 2。結果が0にならない日は改行せず、同じ行に続けて出力します。0になる5日・12日・19日・26日が土曜の列です。

実行結果

2026と9を入力したときの実際の出力です。

年を入力してください: 2026
月を入力してください: 9
2026年9月のカレンダー
 日 月 火 水 木 金 土
        1  2  3  4  5
  6  7  8  9 10 11 12
 13 14 15 16 17 18 19
 20 21 22 23 24 25 26
 27 28 29 30

うるう年もlengthOfMonth()が自動で判定します。2024年2月を指定すると、29日まで表示されます。

2024年2月のカレンダー
 日 月 火 水 木 金 土
              1  2  3
  4  5  6  7  8  9 10
 11 12 13 14 15 16 17
 18 19 20 21 22 23 24
 25 26 27 28 29

月に13を入力すると「月は1〜12で入力してください」と表示して終了します。

コンソールではなくウィンドウにカレンダーを出したいときは、Swingで画面を作ります。SwingとJavaFXのどちらで作るかはJava GUI開発入門で比べています。

よくあるエラーと対処法

カレンダー作りでつまずきやすいのは次の3点です。

  • Calendar.MONTHが0始まり: Calendarクラスでは1月が0、12月が11です。表示時に+1を忘れると月がずれます。LocalDateなら1始まりなのでこの問題は起きません。
  • DayOfWeek.getValue()の戻り値: LocalDateのgetDayOfWeek().getValue()は月曜=1、日曜=7を返します。日曜始まりのカレンダーにするには% 7で変換が必要です。
  • 存在しない日付の指定: LocalDate.of(2024, 13, 1)のように範囲外の月を指定するとDateTimeExceptionが発生します。サンプルコードでは、LocalDate.of()を呼ぶ前に月の範囲をチェックしています。

Calendarクラスでカレンダーを作る場合

授業や課題でCalendarクラスを使うよう指定されることもあります。考え方はLocalDate版と同じで、「1日の曜日」と「月の日数」の取り方だけが変わります。

import java.util.Calendar;

public class CalendarClassApp {
    public static void main(String[] args) {
        int year = 2026;
        int month = 9; // 表示したい月(1〜12)

        Calendar cal = Calendar.getInstance();
        cal.clear();
        cal.set(year, month - 1, 1); // MONTHは0始まりなので-1する

        int lastDay = cal.getActualMaximum(Calendar.DAY_OF_MONTH); // 月の日数
        int offset = cal.get(Calendar.DAY_OF_WEEK) - 1;             // 日曜=1〜土曜=7 を 0〜6 に

        System.out.println(year + "年" + month + "月のカレンダー");
        System.out.println(" 日 月 火 水 木 金 土");
        for (int i = 0; i < offset; i++) {
            System.out.print("   ");
        }
        for (int day = 1; day <= lastDay; day++) {
            System.out.printf("%3d", day);
            if ((day + offset) % 7 == 0) {
                System.out.println();
            }
        }
        System.out.println();
    }
}

実行すると、LocalDate版と同じ2026年9月のカレンダーが表示されます。

2026年9月のカレンダー
 日 月 火 水 木 金 土
        1  2  3  4  5
  6  7  8  9 10 11 12
 13 14 15 16 17 18 19
 20 21 22 23 24 25 26
 27 28 29 30

LocalDate版との違いは次の3点です。

処理CalendarクラスLocalDate
月の指定cal.set(year, month - 1, 1)(0始まり)LocalDate.of(year, month, 1)
1日の曜日get(Calendar.DAY_OF_WEEK)(日曜=1〜土曜=7)getDayOfWeek().getValue()(月曜=1〜日曜=7)
月の日数getActualMaximum(Calendar.DAY_OF_MONTH)lengthOfMonth()

Calendar.DAY_OF_WEEKは日曜=1なので、1を引くだけで日曜始まりの列番号になります。一方、MONTHは0始まりのためmonth - 1を忘れると翌月のカレンダーが出てしまいます。

祝日に対応したカレンダーを作る

祝日を色分けできると、カレンダーは一気に実用的になります。

日本の祝日は、日付が決まっている固定祝日、第N月曜日になるハッピーマンデー、年ごとに日付が変わる春分の日・秋分の日、さらに振替休日と国民の休日の組み合わせでできています。

祝日データを用意する3つの方法

Javaの標準ライブラリには日本の祝日を返す機能がありません。祝日データは自分で用意します。

方法向いている用途注意点
自前で計算する学習・課題・オフライン環境祝日法が改正されたらコードを直す
内閣府の祝日CSVを読み込む業務システム・正確さ重視収録は翌年分まで。2月ごろ更新される見込み(公式は随時更新とだけ案内)
祝日ライブラリを使う(jollydayなど)多国対応が必要なシステム依存ライブラリの更新が必要

ここではまず、自前の計算で全祝日を判定するコードを作ります。そのあとで内閣府CSVを読み込む方法も紹介します。

全祝日を計算するサンプルコード

固定祝日とハッピーマンデーに加え、春分の日・秋分の日、振替休日、国民の休日まで計算します。祝日と日曜日は赤色で表示し、カレンダーの下にその月の祝日名を並べます。

あわせて読む
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class HolidayCalendar {
    public static void main(String[] args) {
        printCalendar(2026, 9);
    }

    /** 祝日を赤色にしたカレンダーと、その月の祝日一覧を表示する */
    public static void printCalendar(int year, int month) {
        Map<LocalDate, String> holidays = getHolidays(year);
        LocalDate firstDay = LocalDate.of(year, month, 1);
        int offset = firstDay.getDayOfWeek().getValue() % 7;

        System.out.println(year + "年" + month + "月のカレンダー");
        System.out.println(" 日 月 火 水 木 金 土");
        for (int i = 0; i < offset; i++) {
            System.out.print("   ");
        }
        for (int day = 1; day <= firstDay.lengthOfMonth(); day++) {
            LocalDate date = firstDay.withDayOfMonth(day);
            if (holidays.containsKey(date) || date.getDayOfWeek() == DayOfWeek.SUNDAY) {
                System.out.printf("\u001B[31m%3d\u001B[0m", day); // 祝日・日曜は赤色
            } else {
                System.out.printf("%3d", day);
            }
            if ((day + offset) % 7 == 0) {
                System.out.println();
            }
        }
        System.out.println();

        // その月の祝日を一覧表示(TreeMapなので日付順に並ぶ)
        for (Map.Entry<LocalDate, String> e : holidays.entrySet()) {
            if (e.getKey().getMonthValue() == month) {
                System.out.println(e.getKey().getDayOfMonth() + "日: " + e.getValue());
            }
        }
    }

    /** 指定した年の祝日・休日を日付順のMapで返す(2020・2021年の五輪特例には非対応) */
    public static Map<LocalDate, String> getHolidays(int year) {
        Map<LocalDate, String> h = new TreeMap<>();

        // 固定祝日
        h.put(LocalDate.of(year, 1, 1), "元日");
        h.put(LocalDate.of(year, 2, 11), "建国記念の日");
        h.put(LocalDate.of(year, 2, 23), "天皇誕生日");
        h.put(LocalDate.of(year, 4, 29), "昭和の日");
        h.put(LocalDate.of(year, 5, 3), "憲法記念日");
        h.put(LocalDate.of(year, 5, 4), "みどりの日");
        h.put(LocalDate.of(year, 5, 5), "こどもの日");
        h.put(LocalDate.of(year, 8, 11), "山の日");
        h.put(LocalDate.of(year, 11, 3), "文化の日");
        h.put(LocalDate.of(year, 11, 23), "勤労感謝の日");

        // ハッピーマンデー(第N月曜日)
        h.put(nthMonday(year, 1, 2), "成人の日");
        h.put(nthMonday(year, 7, 3), "海の日");
        h.put(nthMonday(year, 9, 3), "敬老の日");
        h.put(nthMonday(year, 10, 2), "スポーツの日");

        // 春分の日・秋分の日(1980〜2099年に使える近似式)
        h.put(LocalDate.of(year, 3, equinoxDay(year, 20.8431)), "春分の日");
        h.put(LocalDate.of(year, 9, equinoxDay(year, 23.2488)), "秋分の日");

        addSubstituteHolidays(h);
        addCitizensHolidays(h);
        return h;
    }

    /** 指定月の第N月曜日を返す */
    static LocalDate nthMonday(int year, int month, int n) {
        return LocalDate.of(year, month, 1)
                .with(TemporalAdjusters.dayOfWeekInMonth(n, DayOfWeek.MONDAY));
    }

    /** 春分・秋分の日付を近似式で求める(基準値: 春分20.8431 / 秋分23.2488) */
    static int equinoxDay(int year, double base) {
        return (int) (base + 0.242194 * (year - 1980) - (year - 1980) / 4);
    }

    /** 振替休日: 祝日が日曜なら、その後の最も近い「祝日でない日」を休日にする */
    static void addSubstituteHolidays(Map<LocalDate, String> h) {
        for (LocalDate date : new ArrayList<>(h.keySet())) { // 走査中の追加を避けるためコピー
            if (date.getDayOfWeek() == DayOfWeek.SUNDAY) {
                LocalDate next = date.plusDays(1);
                while (h.containsKey(next)) {
                    next = next.plusDays(1);
                }
                h.put(next, "振替休日");
            }
        }
    }

    /** 国民の休日: 前日と翌日が祝日の平日を休日にする(例: 2026年9月22日) */
    static void addCitizensHolidays(Map<LocalDate, String> h) {
        List<LocalDate> found = new ArrayList<>();
        for (LocalDate date : h.keySet()) {
            LocalDate mid = date.plusDays(1);
            if (!h.containsKey(mid) && h.containsKey(mid.plusDays(1))
                    && mid.getDayOfWeek() != DayOfWeek.SUNDAY) {
                found.add(mid);
            }
        }
        for (LocalDate d : found) {
            h.put(d, "国民の休日");
        }
    }
}

2026年9月を表示した実際の出力です(ブログ上では色を再現できないため、ターミナルで赤色になる数字を太字にしています)。

2026年9月のカレンダー
日 月 火 水 木 金 土
      1  2  3  4  5
  6  7  8  9 10 11 12
 13 14 15 16 17 18 19
 20 21 22 23 24 25 26
 27 28 29 30
21日: 敬老の日
22日: 国民の休日
23日: 秋分の日

2026年9月は、敬老の日(21日)と秋分の日(23日)にはさまれた22日が「国民の休日」になり、19日の土曜日から23日まで5連休になります(日曜の20日から数えると4連休です)。

このコードの計算結果は、内閣府の祝日CSVの2022〜2027年分と照合し、全日付が一致することを確認しています。

祝日カレンダーのコード解説

getHolidays()は、指定した年の祝日をMap<LocalDate, String>で返すメソッドです。TreeMapを使っているので、祝日一覧が日付順に並びます。

  • 固定祝日: 元日・天皇誕生日・山の日など10日はLocalDate.of()でそのまま登録します。
  • ハッピーマンデー: 成人の日・海の日・敬老の日・スポーツの日はTemporalAdjusters.dayOfWeekInMonth(n, DayOfWeek.MONDAY)で「第n月曜日」を求めます。
  • 春分の日・秋分の日: 天文計算で決まるため、1980〜2099年の範囲で使える近似式で日付を出します。
  • 振替休日: 祝日が日曜日なら、その後で最も近い「祝日でない日」を休日にします。
  • 国民の休日: 前日と翌日がどちらも祝日の日を休日にします。

振替休日の処理では、keySet()をArrayListにコピーしてから走査しています。元のMapを直接回しながらput()するとConcurrentModificationExceptionが発生するためです。

赤色表示には\u001B[31mというANSIエスケープシーケンス(ターミナルで文字に色を付ける特殊コード)を使い、\u001B[0mで元の色に戻します。Windowsのコマンドプロンプトなど色に対応しない環境では、記号がそのまま表示されることがあります。

計算方式の注意点

  • 春分の日・秋分の日は、国立天文台の計算をもとに前年2月1日の官報で正式に決まります。近似式は将来の日付を保証しません
  • 2020年・2021年は東京オリンピック・パラリンピックに合わせて海の日・スポーツの日・山の日が移動したため、このコードの結果とは一致しません
  • 天皇誕生日を2月23日としているため、2019年以前の年には使えません

内閣府の祝日CSVを読み込む方法

正確さを優先するなら、内閣府が公開している「国民の祝日」についてのページからCSVを取得する方法が確実です。

2026年9月時点のCSV(syukujitsu.csv)には1955年から2027年までの祝日・休日が収録されています。内閣府は更新時期を「随時」としか示していませんが、現行のCSVは2026年2月2日に更新されたもので、2028年分も春分・秋分の日が官報で公表される2027年2月以降に掲載されると見込まれます。

中身は「2026/9/21,敬老の日」のような2列の形式で、文字コードはShift_JISです。振替休日と国民の休日は、名称が「休日」と記載されています。

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

public class CsvHolidayLoader {
    public static void main(String[] args) throws IOException {
        Map<LocalDate, String> holidays = load("syukujitsu.csv");
        System.out.println("読み込んだ件数: " + holidays.size());

        // 2026年9月の祝日を表示
        for (Map.Entry<LocalDate, String> e : holidays.entrySet()) {
            LocalDate d = e.getKey();
            if (d.getYear() == 2026 && d.getMonthValue() == 9) {
                System.out.println(d + " " + e.getValue());
            }
        }
    }

    /** 内閣府の祝日CSV(Shift_JIS)を読み込み、日付→祝日名のMapを返す */
    public static Map<LocalDate, String> load(String path) throws IOException {
        // 日付は「2026/9/21」のようにゼロ埋めなしなので y/M/d で解釈する
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("y/M/d");
        List<String> lines = Files.readAllLines(Paths.get(path), Charset.forName("Shift_JIS"));

        Map<LocalDate, String> holidays = new TreeMap<>();
        for (String line : lines.subList(1, lines.size())) { // 1行目は見出しなので飛ばす
            String[] cols = line.split(",");
            if (cols.length < 2) {
                continue;
            }
            holidays.put(LocalDate.parse(cols[0].trim(), fmt), cols[1].trim());
        }
        return holidays;
    }
}

syukujitsu.csvをCsvHolidayLoader.javaと同じフォルダに置いて実行した結果です。

読み込んだ件数: 1067
2026-09-21 敬老の日
2026-09-22 休日
2026-09-23 秋分の日

文字コードを指定しないと正しく読み込めません。このコードのFiles.readAllLines(path)は既定でUTF-8として読むため、Shift_JISのCSVではMalformedInputExceptionが発生します(FileReaderなど既定の文字コードで読む方法では文字化けになります)。Charset.forName("Shift_JIS")の指定を忘れないでください。

読み込んだMapは、前のサンプルのgetHolidays()の代わりにそのまま使えます。

よくある質問

Q1. CalendarとLocalDateどちらを使うべき?

A1. 新規コードではLocalDateがおすすめです。月が1始まりでバグを起こしにくく、イミュータブルでスレッドセーフという利点があります。Calendarはレガシーな既存コードとの互換性が必要な場合のみ使うのが現実的です。

Q2. 月初めの曜日はどうやって取得しますか?

A2. LocalDate.of(year, month, 1)で月初めの日付を作り、getDayOfWeek()を呼び出します。getValue()は月曜=1〜日曜=7を返すため、日曜始まりのカレンダーでは% 7で0〜6に変換します。

Q3. 祝日はJavaでどう管理すればよいですか?

A3. 学習用なら、固定祝日をMap<LocalDate, String>に登録し、ハッピーマンデーや春分・秋分の日を計算で求める方法で十分です。業務システムでは、内閣府が公開している祝日CSV(Shift_JIS)を毎年取り込む方式が確実です。

Q4. LocalDateはMapのキーに使えますか?

A4. はい、安全に使えます。LocalDateは値ベースでequals・hashCodeが実装されているため、同じ年月日を表すインスタンスはMapのキーとして正しく一致します。可変な古いDateクラスとは対照的です。

Q5. 振替休日はどうやって実装しますか?

A5. 祝日法のルールは「祝日が日曜日に当たるときは、その後で最も近い祝日でない日を休日とする」です。祝日Mapを走査し、日曜日の祝日があれば、祝日でない日まで1日ずつ後ろにずらして振替休日を登録します。

Q6. 月曜始まりのカレンダーにするには?

A6. 空白の数をgetDayOfWeek().getValue() - 1に変え、見出しを「月 火 水 木 金 土 日」に並べ替えます。改行の判定式(day + offset) % 7 == 0はそのままで、日曜日の後ろで改行されます。

Q7. Swingなど画面(GUI)にカレンダーを表示できますか?

A7. できます。1日の曜日と月の日数を求める部分はこの記事のコードをそのまま使い、System.outで出力している部分をJTableやGridLayoutに並べたJLabelへの表示に置き換えます。

まとめ:Javaでカレンダーを作る方法

Javaのカレンダー表示は、「1日の曜日」と「月の日数」を取得できれば、for文1つで作れます。

【要点まとめ】

  • 新規コードはLocalDate、課題で指定があればCalendarクラスを使う
  • 1日の曜日はgetDayOfWeek().getValue() % 7で日曜始まりの列番号にする
  • 月の日数はlengthOfMonth()で取得でき、うるう年も自動で判定される
  • (day + offset) % 7 == 0で土曜日の後ろに改行を入れる
  • Calendarクラスは月が0始まりなのでmonth - 1を忘れない
  • 祝日は固定祝日・ハッピーマンデー・春分/秋分・振替休日・国民の休日の5種類で判定する
  • 正確さが必要なら内閣府の祝日CSV(Shift_JIS)を読み込む

カレンダーが動いたら、次はテトリスや数当てゲームなど、ループと条件分岐をもっと使うプログラムに挑戦してみてください。

あわせて読む
あわせて読む
REVISIONS / 改訂履歴
REV.DATE内容
52026-10-15図解を描き直し(図面のデザインにそろえた)
42026-10-04記載内容の事実確認と修正
32026-09-022026年9月時点の情報で全体を見直し(古い記述を3件更新)
22026-04-302026年4月時点の情報で全体を見直し
12025-04-14初版
NEXT READ本棚から1本

AIで開発を組み直すなら、まずこの5冊から

入門・実践・設計まで、Claude Codeの本をレベル別に5冊選んで比べました。

→ おすすめ5冊を見る

  • この記事を書いた人
  • 最新記事

トム

SESで約8年、環境を変えられないもどかしさの中にいました。32歳で自社開発企業に転職し、今はClaude Codeと自動化で、仕事も時間も組み直している途中です。
・Javaバックエンドエンジニア(Java歴12年以上)
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎
詳細なプロフィール

𝕏

Java入門