使用C ++ 20 chrono,如何计算有关日期的各种事实 [英] Using C++20 chrono, how to compute various facts about a date
问题描述
?
使用<一个href = http://eel.is/c++draft/#time rel = nofollow noreferrer> C ++ 20计时规范。下面,我显示一个函数,该函数输入一个任意日期,并将此信息打印到 cout
。尽管在撰写本文时, C ++ 20计时规范尚未发布尚未发布,可以通过免费的开放源代码库进行估算。因此,只要您采用C ++ 11或更高版本,就可以立即进行试验,甚至可以将其包含在运输应用程序中。
此答案将采用a的形式函数:
无效信息(std :: chrono :: sys_days sd);
sys_days
是日精度<$ system_clock
系列中的c $ c> time_point 。这意味着距UTC 1970-01-01 00:00:00只是几天的时间。类型别名 sys_days
在C ++ 20中是新的,但是底层类型自C ++ 11起就可用( time_point< system_clock,duration< int,比率86400
)。如果您使用开源C ++ 20预览库,则 sys_days
在命名空间日期
中。
下面的代码假定是本地函数:
使用命名空间std;
使用命名空间std :: chrono;
减少冗长。如果您正在尝试使用开源C ++ 20预览库,请假定:
使用名称空间日期;
标题
输出前两行很简单:
cout<< format( {:%d%B%Y是%A} \n,sd)
<< 其他事实;
只需将日期 sd
并使用 format
和熟悉的 strftime
/ put_time
标志以打印出日期和文字。 开源C ++ 20预览库尚未集成 fmt库,因此使用格式稍有变化的格式字符串%d%B%Y是%A \n
。
这将输出(例如):
2019年12月26日是星期四
其他事实
一次计算出的中间结果
函数的这一部分最后写完了,因为尚不知道会进行什么计算需要多次。但是一旦您知道了,这是如何计算它们:
year_month_day ymd = sd;
auto y = ymd.year();
auto m = ymd.month();
工作日wd {sd};
sys_days NewYears = y / 1/1;
sys_days LastDayOfYear = y / 12/31;
我们将需要 sd $ c $的年和月字段c>和
工作日
(星期几)。以这种方式一劳永逸地计算它们是有效的。我们还将需要(多次)今年的第一天和最后一天。在这一点上很难说,但是将这些值存储为 sys_days
类型是有效的,因为它们的后续用法仅用于 sys_days
在(亚纳秒级的速度)上非常有效。
事实1:天数年份以及一年中剩余的天数
auto dn = sd-新年+天{1};
auto dl = LastDayOfYear-sd;
cout<< *是天数<< dn / days {1}<< ,
<< dl / days {1}<< 还剩几天。n;
这将打印出一年中的天数,其中1月1日为第1天,然后还会打印减去一年中剩余的天数,不包括 sd
。执行此操作的计算量很小。将每个结果除以天{1}
是一种提取 dn
和<$ c $中天数的方法c> 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( *为{:%A}数字,wd)<< n_wd<< 中的
<< total_wd<< format( {:%Y} .\n},y);
wd
是星期几(周一至周日)在本文顶部进行了计算。要执行此计算,我们首先需要在 y
年中第一个和最后一个 wd
的日期。 y / 1 / wd [1]
是一月份的第一个 wd
,而 y / 12 / wd [last]
是12月的最后一个 wd
。
总计一年中 wd
的数量就是这两个日期之间的周数(加1)。子表达式 last_wd-first_wd
是两个日期之间的天数。将该结果除以1周将得到一个整数类型,该整数类型保存两个日期之间的周数。
周数的计算方法与周总数相同除了一个从当前日期开始,而不是一年中的最后一个 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)/周{1} + 1;
cout<< format( *为{:%A}数字},wd)<< n_wd<< 中的
<< total_wd<< format( {:%B%Y}中的字符。\n,y / m);
与事实2一样,除了我们从第一个和最后一个开始年/月对中的wd
y / m 而不是全年。
事实4:一年中的天数
auto total_days = LastDayOfYear-NewYears + days { 1};
cout<< format( *年{:%Y}具有,y)<< total_days / days {1}<< 天。n;
代码几乎可以说明一切。
事实5每月的天数
total_days = sys_days {y / m / last} -sys_days {y / m / 1} +天{1};
cout<< format( * {:%B%Y}具有,y / m)<< total_days / days {1}<< 天。n;
表达式 y / m / last
是年月对 y / m
的最后一天,当然 y / m / 1
是第一对一个月中的某天。两者都被转换为 sys_days
,因此可以将它们相减得到它们之间的天数。为基于1的计数加1。
使用
info
可以这样使用:
info(2019年12月26日);
或类似这样:
info(floor< days>(system_clock :: now()));
以下是示例输出:
2019年12月26日是星期四
其他事实
*这是一年中的第360天,还剩5天。
*它是2019年52个中的第52个星期四。
*它是2019年12月4个中的第4个星期四。
* 2019年有365天。
* 2019年12月为31天。
编辑
对于那些不喜欢常规语法的人,可以使用完整的构造函数语法代替。
例如:
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}};
https://www.timeanddate.com/date/weekday.html computes various facts about a day of the year, for example:
Given an arbitrary date, how can these numbers be computed with the C++20 chrono specification?
This is remarkably easy with the C++20 chrono specification. Below I show a function which inputs an arbitrary date, and prints this information to cout
. Though at the time of this writing, the C++20 chrono specification isn't yet shipping, it is approximated by a free, open-source library. So you can experiment with it today, and even include it in shipping applications as long as you adopt C++11 or later.
This answer will take the form of a function:
void info(std::chrono::sys_days sd);
sys_days
is a day-precision time_point
in the system_clock
family. That means it is simply a count of days since 1970-01-01 00:00:00 UTC. The type alias sys_days
is new with C++20, but the underlying type has been available since C++11 (time_point<system_clock, duration<int, ratio<86400>>>
). If you use the open-source C++20 preview library, sys_days
is in namespace date
.
The code below assumes function-local:
using namespace std;
using namespace std::chrono;
to reduce verbosity. If you are experimenting with the open-source C++20 preview library, also assume:
using namespace date;
Heading
To output the first two lines is simple:
cout << format("{:%d %B %Y is a %A}\n", sd)
<< "\nAdditional facts\n";
Just take the date sd
and use format
with the familiar strftime
/put_time
flags to print out the date and text. The open-source C++20 preview library hasn't yet integrated the fmt library, and so uses the slightly altered format string "%d %B %Y is a %A\n"
.
This will output (for example):
26 December 2019 is a Thursday
Additional facts
Common intermediate results computed once
This section of the function is written last, because one doesn't yet know what computations will be needed multiple times. But once you know, here is how to compute them:
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;
We will need the year and month fields of sd
, and the weekday
(day of the week). It is efficient to compute them once and for all in this manner. We will also need (multiple times) the first and last days of the current year. It is hard to tell at this point, but it is efficient to store these values as type sys_days
as their subsequent use is only with day-oriented arithmetic which sys_days
is very efficient at (sub-nanosecond speeds).
Fact 1: day number of year, and number of days left in year
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";
This prints out the day number of the year, with January 1 being day 1, and then also prints out the number of days remaining in the year, not including sd
. The computation to do this is trivial. Dividing each result by days{1}
is a way to extract the number of days in dn
and dl
into an integral type for formatting purposes.
Fact 2: Number of this weekday and total number of weekdays in year
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
is the day of the week (Monday thru Sunday) computed at the top of this article. To perform this computation we first need the dates of the first and last wd
's in the year y
. y/1/wd[1]
is the first wd
in January, and y/12/wd[last]
is the last wd
in December.
The total number of wd
s in the year is just the number of weeks between these two dates (plus 1). The sub-expression last_wd - first_wd
is the number of days between the two dates. Dividing this result by 1 week results in an integral type holding the number of weeks between the two dates.
The week number is done the same way as the total number of weeks except one starts with the current day instead of the last wd
of the year: sd - first_wd
.
Fact 3: Number of this weekday and total number of weekdays in month
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);
This works just like Fact 2, except we start with the first and last wd
s of the year-month pair y/m
instead of the entire year.
Fact 4: Number of days in year
auto total_days = LastDayOfYear - NewYears + days{1};
cout << format("* Year {:%Y} has ", y) << total_days/days{1} << " days.\n";
The code pretty much speaks for itself.
Fact 5 Number of days in month
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";
The expression y/m/last
is the last day of the year-month pair y/m
, and of course y/m/1
is the first day of the month. Both are converted to sys_days
so that they can be subtracted to get the number of days between them. Add 1 for the 1-based count.
Use
info
can be used like this:
info(December/26/2019);
or like this:
info(floor<days>(system_clock::now()));
Here is example output:
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.
Edit
For those who are not fond of the "conventional syntax", there is a complete "constructor syntax" that can be used instead.
For example:
sys_days NewYears = y/1/1;
sys_days first_wd = y/1/wd[1];
sys_days last_wd = y/12/wd[last];
can be replaced by:
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}};
这篇关于使用C ++ 20 chrono,如何计算有关日期的各种事实的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!