指定した日付が有効かどうかを判定する関数テンプレートです。元ネタとは異なり、std::tm構造体のtm_monに合わせて、月は0~11で指定するようにしています。また、閏年用のテーブルも持たせることで、コードを単純化しました。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
inline bool is_valid_day_helper(int year, int month, int day, bool leap) { static const char days_in_month[2][12] = { { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } }; return value_in_range_inclusive(0, month, 11) && (1 <= day && day <= days_in_month[leap][month]); } template <typename Calender> inline bool is_valid_day(int year, int month, int day, Calender calender) { return is_valid_day_helper(year, month, day, is_leapyear(year, calender)); } |
内部で以前に作った関数を呼び出していますので、リンクを貼っておきます。
また、引数のcalenderには前回のgregorianまたはjulianを指定します。
最初に書いたように、monthに指定する値は0~11でなければなりません。ですので、2021年2月29日が有効か否かを調べるのであれば、is_valid_day(2021, 1, 29, gregorian);のようにしますので注意してください。
ところで、旧サイトでは「メタ関数版も準備中です」と書いておきながらそのままになってしまっていました。あれから時間も経って今さらメタ関数版も必要ないと思いますので、constexpr版を作っておきます。
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
template <typename T> constexpr bool value_in_range_inclusive(const T& min, const T& value, const T& max) { return !(value < min) && !(max < value); } constexpr bool is_valid_day_helper(int year, int month, int day, bool leap) { constexpr const char days_in_month[2][12] = { { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } }; return value_in_range_inclusive(0, month, 11) && (1 <= day && day <= days_in_month[leap][month]); } template <typename Calender> constexpr bool is_valid_day(int year, int month, int day, Calender calender) { return is_valid_day_helper(year, month, day, is_leapyear(year, calender)); } |
ほとんど変わりませんが、is_valid_day_helper関数内のテーブルもconstexprになっています。また、value_in_range_inclusive関数もconstexprにする必要があったのでいっしょに掲載しておきました。残念ながらC++11ではコンパイルできませんので、C++14以降対応になります。