https://www.timeanddate.com/date/weekday.htmlは、その年の1日に関するさまざまな事実を計算します。次に例を示します。
任意の日付が与えられた場合、これらの数値はC ++ 20クロノ仕様でどのように計算できますか?
https://www.timeanddate.com/date/weekday.htmlは、その年の1日に関するさまざまな事実を計算します。次に例を示します。
任意の日付が与えられた場合、これらの数値はC ++ 20クロノ仕様でどのように計算できますか?
回答:
これは、C ++ 20クロノ仕様で非常に簡単です。以下に、任意の日付を入力し、この情報をに出力する関数を示しcout
ます。この記事の執筆時点では、C ++ 20クロノ仕様はまだ出荷されていませんが、無料のオープンソースライブラリによって概算されています。したがって、C ++ 11以降を採用している限り、今日それを試し、出荷アプリケーションに含めることもできます。
この答えは関数の形をとります:
void info(std::chrono::sys_days sd);
sys_days
当日精度でtime_point
でsystem_clock
家族。つまり、1970-01-01 00:00:00 UTCからの日数です。型エイリアスsys_days
はC ++ 20で新しく追加されましたが、基礎となる型はC ++ 11(time_point<system_clock, duration<int, ratio<86400>>>
)以降で使用できます。あなたが使用している場合は、オープンソースのC ++ 20のプレビューライブラリを、sys_days
ですnamespace date
。
以下のコードは関数ローカルを想定しています:
using namespace std;
using namespace std::chrono;
冗長性を減らすため。オープンソースのC ++ 20プレビューライブラリを試す場合は、次のことも想定してください。
using namespace date;
見出し
最初の2行を出力するのは簡単です:
cout << format("{:%d %B %Y is a %A}\n", sd)
<< "\nAdditional facts\n";
日付sd
を取得format
し、使い慣れたstrftime
/ put_time
フラグを使用して日付とテキストを出力します。オープンソースのC ++ 20プレビューライブラリはまだ統合されていないFMTライブラリを、そして多少変更された書式文字列を使用します"%d %B %Y is a %A\n"
。
これは(例えば)出力します:
26 December 2019 is a Thursday
Additional facts
一度計算された一般的な中間結果
関数のこのセクションは最後に書かれています。何回計算が必要になるかはまだわからないからです。しかし、あなたが知ったら、それらを計算する方法は次のとおりです:
year_month_day ymd = sd;
auto y = ymd.year();
auto m = ymd.month();
weekday wd{sd};
sys_days NewYears = y/1/1;
sys_days LastDayOfYear = y/12/31;
年と月のフィールドsd
、およびweekday
(曜日)が必要です。この方法で一度にすべてを計算するのが効率的です。今年の最初と最後の日も(複数回)必要です。この時点で伝えるのは難しいですが、タイプとして、これらの値を格納するのに効率的であるsys_days
彼らのその後の使用が唯一の日指向算術であるようsys_days
である非常に(サブナノ秒の速度)で効率的。
ファクト1:年の日数、および年の残り日数
auto dn = sd - NewYears + days{1};
auto dl = LastDayOfYear - sd;
cout << "* It is day number " << dn/days{1} << " of the year, "
<< dl/days{1} << " days left.\n";
これは、1月1日を1日として、その年の日数を出力し、次に、を含まない、その年の残りの日数も出力しsd
ます。これを行うための計算は簡単です。各結果を分割するdays{1}
の日数を抽出する方法であるdn
とdl
目的をフォーマットするための一体型に。
ファクト2:この平日の数と年間の平日の総数
sys_days first_wd = y/1/wd[1];
sys_days last_wd = y/12/wd[last];
auto total_wd = (last_wd - first_wd)/weeks{1} + 1;
auto n_wd = (sd - first_wd)/weeks{1} + 1;
cout << format("* It is {:%A} number ", wd) << n_wd << " out of "
<< total_wd << format(" in {:%Y}.\n}", y);
wd
この記事の上部で計算された曜日(月曜日から日曜日)です。この計算を実行するには、最初wd
に年の最初と最後の日付が必要y
です。 1月y/1/wd[1]
の最初wd
で、12月y/12/wd[last]
の最後wd
です。
その年のの合計数はwd
、これら2つの日付の間の週数(プラス1)です。部分式last_wd - first_wd
は、2つの日付の間の日数です。この結果を1週間で割ると、2つの日付の間の週数を保持する整数型になります。
週番号は、週の総数と同じ方法で行われます。ただしwd
、年の最後ではなく現在の日から始まる場合を除きますsd - first_wd
。
事実3:この平日の数と月の平日の総数
first_wd = y/m/wd[1];
last_wd = y/m/wd[last];
total_wd = (last_wd - first_wd)/weeks{1} + 1;
n_wd = (sd - first_wd)/weeks{1} + 1;
cout << format("* It is {:%A} number }", wd) << n_wd << " out of "
<< total_wd << format(" in {:%B %Y}.\n", y/m);
これはファクト2と同じように機能しますwd
が、年y/m
全体ではなく、年と月のペアの最初と最後のs から始めます。
事実4:1年の日数
auto total_days = LastDayOfYear - NewYears + days{1};
cout << format("* Year {:%Y} has ", y) << total_days/days{1} << " days.\n";
このコードは、それ自体が意味をなしています。
ファクト5月の日数
total_days = sys_days{y/m/last} - sys_days{y/m/1} + days{1};
cout << format("* {:%B %Y} has ", y/m) << total_days/days{1} << " days.\n";
式y/m/last
は、年と月のペアの最後の日でy/m
あり、もちろんy/m/1
月の最初の日です。両方がに変換されsys_days
て、それらの間の日数を取得するために減算できます。1ベースのカウントに1を追加します。
使用する
info
このように使用できます:
info(December/26/2019);
またはこのように:
info(floor<days>(system_clock::now()));
次に出力例を示します。
26 December 2019 is a Thursday
Additional facts
* It is day number 360 of the year, 5 days left.
* It is Thursday number 52 out of 52 in 2019.
* It is Thursday number 4 out of 4 in December 2019.
* Year 2019 has 365 days.
* December 2019 has 31 days.
編集する
「従来の構文」が苦手な方のために、代わりに使用できる完全な「コンストラクター構文」があります。
例えば:
sys_days NewYears = y/1/1;
sys_days first_wd = y/1/wd[1];
sys_days last_wd = y/12/wd[last];
で置き換えることができます:
sys_days NewYears = year_month_day{y, month{1}, day{1}};
sys_days first_wd = year_month_weekday{y, month{1}, weekday_indexed{wd, 1}};
sys_days last_wd = year_month_weekday_last{y, month{12}, weekday_last{wd}};
std::cout << "a*b = " << a*b << "; a^b = " << a^b << '\n';
(幸いなことに、ほとんどの場合、コンパイル時に捕捉されますが、それでも厄介です)の動作に注意してください。したがって、この新しい除算演算子の乱用を使用するときは注意が必要です。