Gobble up pudding

プログラミングの記事がメインのブログです。

MENU

C++でカレンダー

スポンサードリンク

f:id:fa11enprince:20200628230502j:plain
カレンダーなんてJavaScriptを使ったらすでにたくさん便利なのがありますが、 自分でカレンダーを書いたらどうなるか…とおもい書いてみました。C++で。 そういえばツェラーの公式というのがあり、使ってみました。 C++はここ数か月書いてませんでしたが以外に覚えているものですね。 std::unordered_mapをconstにしたらmap[i]みたいのができないんだメンドクセ…っていうのがありました(findで代用しました)

ソース

#include <cstdio>
#include <unordered_map>

namespace Pudding {
    using namespace std;
    static const unordered_map<int, int> DaysOfMonth = {
        {1,31}, {2,28}, {3,31}, {4,30}, {5,31}, {6,30},
        {7,31}, {8,31}, {9,30}, {10,31}, {11,30}, {12,31}
    };

    class Calendar {
    public:
        static void print(int year, int month) {
            printf("\n%4d%2d月", year, month);
            printf("\n 日 月 火 水 木 金 土\n");
            int index = get_day_of_week_by_zeller(year, month, 0);
            int position = index % 7;
            fill_with_blank_to(position);
            for (int i = 0; i < get_days_of_month(year, month); i++) {
                line_break_if_sunday(position);
                printf("%3d", i + 1);
                position++;
            }
            printf("\n");
        }

    private:
        // 指定位置まで空白を埋める
        static void fill_with_blank_to(int position) {
            for (int i = 0; i < position; i++) {
                printf("   ");
            }
        }
        // 位置により必要なら改行をする 7の倍数(この場合日曜)なら改行
        static void line_break_if_sunday(int position) {
            if ((position % 7) == 0) {
                printf("\n");
            }
        }

        // うるう年判定
        static bool is_leap_year(int year) {
            return (year % 400 == 0) ? true
                : (year % 100 == 0) ? false
                : (year % 4 == 0) ? true
                : false;
        }

        // 月の日数
        static int get_days_of_month(int year, int month) {
            int days = DaysOfMonth.find(month)->second;
            if (is_leap_year(year) && month == 2) {
                days = 29;
            }
            return days;
        }

        // ツェラーの公式 曜日のインデックスを求める (1:月~7:日)
        static int get_day_of_week_by_zeller(int year, int month, int day) {
            if (month < 3) {
                year--;
                month += 12;
            }
            return (year + year / 4 - year / 100 + year / 400 + (13 * month + 8 ) / 5 + day) % 7 + 1;
        }
    };

}

auto main() -> int {
    for (int i = 1; i <= 12; i++) {
        Pudding::Calendar::print(2016, i);
    }
}

実行結果

2016年 1月
 日 月 火 水 木 金 土
                 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
 31

2016年 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

2016年 3月
 日 月 火 水 木 金 土
        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 31

...省略