C++20 のカレンダーとタイム ゾーン:カレンダーの日付の処理

前回の投稿「C++20 のカレンダーとタイム ゾーン:カレンダーの日付」で、新しいカレンダー関連のデータ型を紹介しました。今日、私はさらに一歩進んで彼らと交流しています。

year(2100)/2/29. のようなカレンダー日付があるとします。 あなたの最初の質問は次のようなものかもしれません:この日付は有効ですか?

日付が有効かどうかを確認する

C++20 のさまざまなカレンダー型には、関数 ok があります。 .この関数は true を返します 日付が有効な場合。

// leapYear.cpp

#include <iostream>
#include "date.h"
 
int main() {

 std::cout << std::boolalpha << std::endl;
 
 using namespace date; 

 std::cout << "Valid days" << std::endl; // (1) 
 day day31(31);
 day day32 = day31 + days(1);
 std::cout << " day31: " << day31 << "; ";
 std::cout << " day31.ok(): " << day31.ok() << std::endl;
 std::cout << " day32: " << day32 << "; ";
 std::cout << "day32.ok(): " << day32.ok() << std::endl;
 

 std::cout << std::endl;

 std::cout << "Valid months" << std::endl; // (2) 
 month month1(1);
 month month0(0);
 std::cout << " month1: " << month1 << "; ";
 std::cout << " month1.ok(): " << month1.ok() << std::endl;
 std::cout << " month0: " << month0 << "; ";
 std::cout << "month0.ok(): " << month0.ok() << std::endl;

 std::cout << std::endl;

 std::cout << "Valid years" << std::endl; // (3) 
 year year2020(2020);
 year year32768(-32768);
 std::cout << " year2020: " << year2020 << "; ";
 std::cout << " year2020.ok(): " << year2020.ok() << std::endl;
 std::cout << " year32768: " << year32768 << "; ";
 std::cout << "year32768.ok(): " << year32768.ok() << std::endl;

 std::cout << std::endl;

 std::cout << "Leap Years" << std::endl; // (4) 

 constexpr auto leapYear2016{year(2016)/2/29};
 constexpr auto leapYear2020{year(2020)/2/29};
 constexpr auto leapYear2024{year(2024)/2/29};

 std::cout << " leapYear2016.ok(): " << leapYear2016.ok() << std::endl;
 std::cout << " leapYear2020.ok(): " << leapYear2020.ok() << std::endl;
 std::cout << " leapYear2024.ok(): " << leapYear2024.ok() << std::endl;

 std::cout << std::endl;

 std::cout << "No Leap Years" << std::endl; // (5) 

 constexpr auto leapYear2100{year(2100)/2/29};
 constexpr auto leapYear2200{year(2200)/2/29};
 constexpr auto leapYear2300{year(2300)/2/29};

 std::cout << " leapYear2100.ok(): " << leapYear2100.ok() << std::endl;
 std::cout << " leapYear2200.ok(): " << leapYear2200.ok() << std::endl;
 std::cout << " leapYear2300.ok(): " << leapYear2300.ok() << std::endl;

 std::cout << std::endl;

 std::cout << "Leap Years" << std::endl; // (6) 

 constexpr auto leapYear2000{year(2000)/2/29};
 constexpr auto leapYear2400{year(2400)/2/29};
 constexpr auto leapYear2800{year(2800)/2/29};

 std::cout << " leapYear2000.ok(): " << leapYear2000.ok() << std::endl;
 std::cout << " leapYear2400.ok(): " << leapYear2400.ok() << std::endl;
 std::cout << " leapYear2800.ok(): " << leapYear2800.ok() << std::endl;

 std::cout << std::endl;

}

特定の日 (1 行目)、特定の月 (2 行目)、または特定の年 (3 行目) が有効かどうかをプログラムでチェックインしました。日の範囲は [1, 31]、月は [1, 12]、年は [ -32767, 32767] です。したがって、 ok 対応する値の -call は false を返します .さまざまな値を出力すると、興味深いことが 2 つあります。まず、値が有効でない場合、出力は次のように表示されます:"is not a valid day "; "is not a valid month "; "is not a valid year ". 次に、月の値が文字列表現で表示されます。

ok を適用できます -カレンダーの日付に電話してください。特定のカレンダーの日付がうるう日であるかどうか、つまり対応する年がうるう年であるかどうかを簡単に確認できるようになりました。世界中で使用されているグレゴリオ暦では、次の規則が適用されます:

4 でちょうど割り切れる年 うるう年です r.

  • 100 で割り切れる年を除く . 閏年ではない .
    • 400 で割り切れる年を除く . うるう年です .

複雑すぎる?プログラム jumpYears.cpp は、このルールの例です。

拡張された chrono ライブラリにより、カレンダーの日付間の期間を簡単に尋ねることができます。

カレンダーの日付のクエリ

難しい話は抜きにして。次のプログラムは、いくつかのカレンダーの日付を照会します。

// queryCalendarDates.cpp

#include "date.h"
#include <iostream>

int main() {

 using namespace date;

 std::cout << std::endl;

 auto now = std::chrono::system_clock::now(); // (1)
 std::cout << "The current time is: " << now << " UTC\n"; 
 std::cout << "The current date is: " << floor<days>(now) << std::endl;
 std::cout << "The current date is: " << year_month_day{floor<days>(now)} << std::endl;
 std::cout << "The current date is: " << year_month_weekday{floor<days>(now)} << std::endl;

 std::cout << std::endl;

 
 auto currentDate = year_month_day(floor<days>(now)); // (2)
 auto currentYear = currentDate.year();
 std::cout << "The current year is " << currentYear << '\n'; 
 auto currentMonth = currentDate.month();
 std::cout << "The current month is " << currentMonth << '\n'; 
 auto currentDay = currentDate.day();
 std::cout << "The current day is " << currentDay << '\n'; 

 std::cout << std::endl;
 // (3)
 auto hAfter = floor<std::chrono::hours>(now) - sys_days(January/1/currentYear); 
 std::cout << "It has been " << hAfter << " since New Year!\n"; 
 auto nextYear = currentDate.year() + years(1); // (4)
 auto nextNewYear = sys_days(January/1/nextYear);
 auto hBefore = sys_days(January/1/nextYear) - floor<std::chrono::hours>(now); 
 std::cout << "It is " << hBefore << " before New Year!\n";

 std::cout << std::endl;
 // (5)
 std::cout << "It has been " << floor<days>(hAfter) << " since New Year!\n"; 
 std::cout << "It is " << floor<days>(hBefore) << " before New Year!\n";
 
 std::cout << std::endl;
 
}

C++20 拡張機能を使用すると、現在 (1 行目) などの時点を直接表示できます。 std::chrono::floor 時点を 1 日 std::chrono::sys_days に変換できます .この値は、カレンダー タイプの初期化に使用できます std::chrono::year_month_day .最後に、値を std::chrono::year_month_weekday に入れると カレンダー型の場合、この特定の日は 10 月の第 3 火曜日であるという答えが得られました。

もちろん、現在の年、月、日 (2 行目) など、そのコンポーネントの暦日を尋ねることもできます。

行 (3) は最も興味深いものです。現在の日付から現在の年の最初の 1 月の時間単位の解像度を差し引くと、新年からの時間が得られます。逆に、翌年の最初の 1 月 (4 行目) から現在の日付を時間単位で減算すると、新年までの時間が得られます。時間の解像度が気に入らないかもしれません。行 5 は値を日単位で表示します。

誕生日の平日が知りたいです。

Query Weekdays

拡張された chrono ライブラリのおかげで、特定の暦日の曜日を簡単に取得できます。

// weekdaysOfBirthdays.cpp

#include <cstdlib>
#include <iostream>
#include "date.h"

int main() {

 std::cout << std::endl;

 using namespace date;

 int y;
 int m;
 int d;

 std::cout << "Year: "; // (1)
 std::cin >> y;
 std::cout << "Month: ";
 std::cin >> m;
 std::cout << "Day: ";
 std::cin >> d;

 std::cout << std::endl;

 auto birthday = year(y)/month(m)/day(d); // (2)

 if (not birthday.ok()) { // (3)
 std::cout << birthday << std::endl;
 std::exit(EXIT_FAILURE);
 }

 std::cout << "Birthday: " << birthday << std::endl;
 auto birthdayWeekday = year_month_weekday(birthday); // (4)
 std::cout << "Weekday of birthday: " << birthdayWeekday.weekday() << std::endl;

 auto currentDate = year_month_day(floor<days>(std::chrono::system_clock::now())); 
 auto currentYear = currentDate.year();
 
 auto age = (int)currentDate.year() - (int)birthday.year(); // (5)
 std::cout << "Your age: " << age << std::endl;

 std::cout << std::endl;

 std::cout << "Weekdays for your next 10 birthdays" << std::endl; // (6)

 for (int i = 1, newYear = (int)currentYear; i <= 10; ++i ) { 
 std::cout << " Age " << ++age << std::endl;
 auto newBirthday = year(++newYear)/month(m)/day(d);
 std::cout << " Birthday: " << newBirthday << std::endl;
 std::cout << " Weekday of birthday: " 
 << year_month_weekday(newBirthday).weekday() << std::endl;
 }

 std::cout << std::endl;

}

最初に、プログラムはあなたの誕生日の年、月、日を尋ねます (1 行目)。入力に基づいて、カレンダーの日付が作成され (2 行目)、有効かどうかがチェックされます (3 行目)。これで、あなたの誕生日の平日が表示されます。したがって、カレンダーの日付を使用して、カレンダー タイプ std::chrono::year_month_weekday を埋めます。 (4 行目)。 int を取得するには カレンダー型の年の表現、私はそれを int に変換する必要があります (5 行目)。年齢を表示できるようになりました。最後に、for ループは、次の 10 回の誕生日 (6 行目) ごとに、年齢、暦日、および曜日の情報を表示します。 age をインクリメントするだけです と newYear

これが私の誕生日のプログラムの一部です。

次は?

拡張された Chrono ライブラリへの投稿で重要なコンポーネントが 1 つまだありません:タイム ゾーンです。