使用C ++ 20 chrono,如何计算有关日期的各种事实 [英] Using C++20 chrono, how to compute various facts about a date

查看:139
本文介绍了使用C ++ 20 chrono,如何计算有关日期的各种事实的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

解决方案

使用<一个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 工作日(星期几)。以这种方式一劳永逸地计算它们是有效的。我们还将需要(多次)今年的第一天和最后一天。在这一点上很难说,但是将这些值存储为 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 wds 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 wds 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆