#include <stdio.h>
// 閏年判定関数
// 4で割り切れてかつ100で割り切れない、または400で割り切れる年は閏年
int isLeapYear(int year){
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
// 1年の日数を判定する関数
// 閏年の場合は366を返しそれ以外は365を返す
int findDaysOfYear(int year){
if(isLeapYear(year)){
return(366);
}else{
return(365);
}
}
// 月ごとの日数を返す関数
// 閏年ならば2月は29日にする
int findDaysInMonth(int month, int year){
// 各月の日数(平年), 月と要素番号を合わせるために0番目に0を格納する
int daysInMonth[] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
// 閏年の場合は2月を29日とする
if(isLeapYear(year)){
if(month == 2){
daysInMonth[month] = 29;
}
}
return(daysInMonth[month]);
}
// 引数の日付の曜日を計算する
// 戻り値は曜日番号 0:Sunday, 1:Monday, 2:Tuesday, 3:Wednesday, 4:Thursday, 5:Friday, 6:Saturday
// -> 2000/1/1からの日数を計算することにより曜日番号を求める
// (c.f. 2000/1/1 Saturday)
int calcDayOfWeek(int year, int month, int day){
int y, m;
// 基準とする2000/1/1からの日数
int totalDays = 0;
// 曜日番号 0:Sunday, 1:Monday, 2:Tuesday, 3:Wednesday, 4:Thursday, 5:Friday, 6:Saturday
int dayOfWeekNum;
if(year < 2000){
// 1999年以前のカレンダーを計算する場合
// この場合は1999/12/31から求める日付まで遡るように計算する
// 例として1990/5/5の曜日を求める場合を考える
// 1999~1991までの日数を足す
for(y = 1999; y > year; y--){
// 閏年ならば1年366日, それ以外は365日を足す
totalDays += findDaysOfYear(y);
}
// 1990年の12月から6月までの日数の合計を求める
for(m = 12; m > month; m--){
totalDays += findDaysInMonth(m, year);
}
// 5月末から5/5までの日数を加える
totalDays += findDaysInMonth(m, year) - day + 1;
dayOfWeekNum = 6 - totalDays%7;
}else{
// 2000年以降のカレンダーを計算する場合
for(y = 2000; y < year; y++){
// 閏年ならば1年366日, それ以外は365日を足す
totalDays += findDaysOfYear(y);
}
// yearにおいてが求める日付の前の月までの日数を求める
for(m = 1; m < month; m++){
totalDays += findDaysInMonth(m, year);
}
totalDays += day - 1;
// 基準日である2000/1/1の曜日番号も足す
totalDays += 6;
dayOfWeekNum = totalDays%7;
}
return (dayOfWeekNum);
}
// 指定年月のカレンダーを表示
void dispCalendar(int year, int month, int firstDay){
int daysOfCertainMonth = findDaysInMonth(month, year);
// カレンダーの見出し
printf("\n< %d-%02d calendar >\n", year, month);
printf("Sun Mon Tur Wed Thu Fri Sat\n");
// カレンダー最初の行に半角スペース4文字の空白を出力
for (int i = 0; i < firstDay; i++) {
printf(" ");
}
// 各日の出力
for (int day = 1; day <= daysOfCertainMonth; day++) {
printf(" %2d ", day);
// 土曜ごとに改行
if ((firstDay + day) % 7 == 0) printf("\n");
}
printf("\n"); // 最後に改行
}
int main(void){
int year, month;
// 年の入力
printf("Input the year: ");
scanf("%d", &year);
// 月の入力
printf("Input the month: ");
scanf("%d", &month);
if(year < 1873){
printf("Only compatible from 1873.\n");
return(0);
}
if(month < 1 || 12 < month){
printf("input the month in 1-12.\n");
return(0);
}
// 指定月の1日が何曜日かを計算する
int firstDay = calcDayOfWeek(year, month, 1);
// 指定年月のカレンダーを表示
dispCalendar(year, month, firstDay);
return(0);
}