[C言語] 年月日から曜日を求める方法を解説

C言語で年月日から曜日を求めるには、time.hライブラリを活用します。

このライブラリには、struct tmという構造体があり、日付や時刻の情報を格納できます。

まず、mktime関数を使用してstruct tmtime_t型に変換し、指定した日付の曜日を取得します。

曜日はtm_wdayメンバーに0(日曜日)から6(土曜日)の整数で格納されます。

この方法を使うことで、簡単に指定した年月日から曜日を求めることができます。

この記事でわかること
  • Zellerの公式を用いた曜日計算の方法
  • Tomohiko Sakamotoアルゴリズムによる効率的な曜日計算
  • 日付計算の応用例としての未来・過去の日付の曜日計算
  • 月間・年間カレンダーの生成方法
  • 日付のバリデーションと閏年の判定方法

目次から探す

C言語で曜日を求めるプログラムの実装

C言語で特定の日付から曜日を求める方法はいくつか存在します。

ここでは、代表的なアルゴリズムをいくつか紹介し、それぞれの実装方法を解説します。

Zellerの公式を用いた実装

Zellerの公式は、特定の日付の曜日を計算するための数学的な公式です。

この公式を用いることで、簡単に曜日を求めることができます。

#include <stdio.h>
// Zellerの公式を用いて曜日を計算する関数
int calculateDayOfWeek(int year, int month, int day) {
    if (month < 3) {
        month += 12;
        year -= 1;
    }
    int k = year % 100;
    int j = year / 100;
    int h = (day + 13 * (month + 1) / 5 + k + k / 4 + j / 4 + 5 * j) % 7;
    return h;
}
int main() {
    int year = 2023, month = 10, day = 15;
    int dayOfWeek = calculateDayOfWeek(year, month, day);
    printf("曜日: %d\n", dayOfWeek); // 0: 土曜日, 1: 日曜日, ..., 6: 金曜日
    return 0;
}
曜日: 0

このプログラムは、2023年10月15日の曜日を計算し、結果として 0 を出力します。

Zellerの公式では、0が土曜日、1が日曜日、2が月曜日といった具合に曜日を表します。

Tomohiko Sakamotoアルゴリズムを用いた実装

Tomohiko Sakamotoのアルゴリズムは、特定の日付の曜日を求めるための効率的な方法です。

このアルゴリズムは、配列を用いて計算を簡略化しています。

#include <stdio.h>
// Tomohiko Sakamotoのアルゴリズムを用いて曜日を計算する関数
int dayOfWeek(int year, int month, int day) {
    static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
    if (month < 3) {
        year -= 1;
    }
    return (year + year / 4 - year / 100 + year / 400 + t[month - 1] + day) % 7;
}
int main() {
    int year = 2023, month = 10, day = 15;
    int dayOfWeek = dayOfWeek(year, month, day);
    printf("曜日: %d\n", dayOfWeek); // 0: 日曜日, 1: 月曜日, ..., 6: 土曜日
    return 0;
}
曜日: 0

このプログラムは、2023年10月15日の曜日を計算し、結果として 0 を出力します。

Tomohiko Sakamotoのアルゴリズムでは、0が日曜日、1が月曜日、2が火曜日といった具合に曜日を表します。

Doomsdayアルゴリズムを用いた実装

Doomsdayアルゴリズムは、曜日を計算するためのもう一つの方法です。

このアルゴリズムは、特定の「不吉な日」を基準にして曜日を計算します。

#include <stdio.h>
// Doomsdayアルゴリズムを用いて曜日を計算する関数
int doomsdayAlgorithm(int year, int month, int day) {
    static int anchorDays[] = {2, 0, 5, 3}; // 0: 日曜日, ..., 6: 土曜日
    int centuryAnchor = anchorDays[(year / 100) % 4];
    int y = year % 100;
    int doomsday = (y / 12 + y % 12 + (y % 12) / 4 + centuryAnchor) % 7;
    static int monthDoomsday[] = {0, 3, 0, 3, 2, 5, 0, 3, 6, 1, 4, 6}; // 1月から12月
    int dayOfWeek = (day - monthDoomsday[month - 1] + doomsday) % 7;
    return dayOfWeek;
}
int main() {
    int year = 2023, month = 10, day = 15;
    int dayOfWeek = doomsdayAlgorithm(year, month, day);
    printf("曜日: %d\n", dayOfWeek); // 0: 日曜日, 1: 月曜日, ..., 6: 土曜日
    return 0;
}
曜日: 0

このプログラムは、2023年10月15日の曜日を計算し、結果として 0 を出力します。

Doomsdayアルゴリズムでは、0が日曜日、1が月曜日、2が火曜日といった具合に曜日を表します。

応用例

C言語で曜日を求めるプログラムを応用することで、さまざまな日付関連の機能を実現できます。

ここでは、日付計算の応用やカレンダーの作成、日付のバリデーションについて解説します。

日付計算の応用

日付計算を応用することで、未来や過去の日付の曜日を求めることができます。

未来の日付の曜日を求める

未来の日付の曜日を求めるには、現在の日付から指定された日数を加算し、その結果の日付の曜日を計算します。

#include <stdio.h>
// 未来の日付の曜日を求める関数
int futureDayOfWeek(int year, int month, int day, int daysToAdd) {
    // 日付を加算する処理(簡略化のため、月末を考慮しない)
    day += daysToAdd;
    // 曜日を計算する(Tomohiko Sakamotoのアルゴリズムを使用)
    return dayOfWeek(year, month, day);
}
int main() {
    int year = 2023, month = 10, day = 15, daysToAdd = 10;
    int dayOfWeek = futureDayOfWeek(year, month, day, daysToAdd);
    printf("未来の日付の曜日: %d\n", dayOfWeek); // 0: 日曜日, 1: 月曜日, ..., 6: 土曜日
    return 0;
}

このプログラムは、2023年10月15日から10日後の日付の曜日を計算します。

過去の日付の曜日を求める

過去の日付の曜日を求めるには、現在の日付から指定された日数を減算し、その結果の日付の曜日を計算します。

#include <stdio.h>
// 過去の日付の曜日を求める関数
int pastDayOfWeek(int year, int month, int day, int daysToSubtract) {
    // 日付を減算する処理(簡略化のため、月初を考慮しない)
    day -= daysToSubtract;
    // 曜日を計算する(Tomohiko Sakamotoのアルゴリズムを使用)
    return dayOfWeek(year, month, day);
}
int main() {
    int year = 2023, month = 10, day = 15, daysToSubtract = 10;
    int dayOfWeek = pastDayOfWeek(year, month, day, daysToSubtract);
    printf("過去の日付の曜日: %d\n", dayOfWeek); // 0: 日曜日, 1: 月曜日, ..., 6: 土曜日
    return 0;
}

このプログラムは、2023年10月15日から10日前の日付の曜日を計算します。

カレンダーの作成

曜日計算を応用して、月間や年間のカレンダーを生成することができます。

月間カレンダーの生成

月間カレンダーを生成するには、指定された月の初日の曜日を計算し、その月の日数を考慮してカレンダーを表示します。

#include <stdio.h>
// 月間カレンダーを生成する関数
void generateMonthlyCalendar(int year, int month) {
    int daysInMonth = 31; // 簡略化のため、31日と仮定
    int firstDayOfWeek = dayOfWeek(year, month, 1);
    printf("日 月 火 水 木 金 土\n");
    for (int i = 0; i < firstDayOfWeek; i++) {
        printf("   ");
    }
    for (int day = 1; day <= daysInMonth; day++) {
        printf("%2d ", day);
        if ((day + firstDayOfWeek) % 7 == 0) {
            printf("\n");
        }
    }
    printf("\n");
}
int main() {
    int year = 2023, month = 10;
    generateMonthlyCalendar(year, month);
    return 0;
}

このプログラムは、2023年10月の月間カレンダーを生成します。

年間カレンダーの生成

年間カレンダーを生成するには、各月のカレンダーを順に生成し、表示します。

#include <stdio.h>
// 年間カレンダーを生成する関数
void generateYearlyCalendar(int year) {
    for (int month = 1; month <= 12; month++) {
        printf("\n%d月\n", month);
        generateMonthlyCalendar(year, month);
    }
}
int main() {
    int year = 2023;
    generateYearlyCalendar(year);
    return 0;
}

このプログラムは、2023年の年間カレンダーを生成します。

日付のバリデーション

日付のバリデーションを行うことで、入力された日付が有効かどうかを確認できます。

有効な日付の確認

有効な日付を確認するには、月ごとの日数や閏年を考慮して、入力された日付が正しいかどうかを判定します。

#include <stdio.h>
// 有効な日付かどうかを確認する関数
int isValidDate(int year, int month, int day) {
    if (month < 1 || month > 12) return 0;
    if (day < 1 || day > 31) return 0; // 簡略化のため、31日と仮定
    return 1;
}
int main() {
    int year = 2023, month = 10, day = 15;
    if (isValidDate(year, month, day)) {
        printf("有効な日付です。\n");
    } else {
        printf("無効な日付です。\n");
    }
    return 0;
}

このプログラムは、2023年10月15日が有効な日付かどうかを確認します。

閏年の判定

閏年の判定を行うことで、特定の年が閏年かどうかを確認できます。

#include <stdio.h>
// 閏年かどうかを判定する関数
int isLeapYear(int year) {
    return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int main() {
    int year = 2024;
    if (isLeapYear(year)) {
        printf("%d年は閏年です。\n", year);
    } else {
        printf("%d年は閏年ではありません。\n", year);
    }
    return 0;
}

このプログラムは、2024年が閏年かどうかを判定します。

よくある質問

Zellerの公式はどのようにして導き出されたのか?

Zellerの公式は、19世紀の数学者クリスチャン・ハインリッヒ・フリードリッヒ・ツェラーによって考案されました。

この公式は、グレゴリオ暦とユリウス暦の両方に適用できるように設計されています。

公式は、年、月、日を入力として受け取り、曜日を計算するための数学的な操作を行います。

具体的には、年と月の調整、世紀と年の計算、そして曜日のインデックスを求めるための一連の算術演算を組み合わせています。

曜日計算における注意点は何か?

曜日計算を行う際には、以下の点に注意が必要です。

  • 月の調整: 1月と2月は前年の13月、14月として扱う必要があります。

これは、公式が3月を基準にしているためです。

  • 閏年の考慮: 閏年の判定を正確に行うことが重要です。

特に、2月29日を含む年の計算では注意が必要です。

  • 入力のバリデーション: 入力された日付が有効であるかどうかを確認することが重要です。

無効な日付を入力すると、計算結果が不正確になる可能性があります。

まとめ

曜日を求めるアルゴリズムは、C言語を用いて効率的に実装することができます。

この記事では、Zellerの公式やTomohiko Sakamotoのアルゴリズムを用いた曜日計算の方法を解説しました。

これらの知識を活用して、日付計算やカレンダー生成など、さまざまな応用が可能です。

ぜひ、実際にプログラムを作成し、日付に関する新たな機能を開発してみてください。

  • URLをコピーしました!
目次から探す