Joh*_*vat 2 c++ epoch c++11 c++-chrono
是否可以手动将纪元日期/时间设置为0000年1月1日,因此我可以使用std :: chrono :: time_point :: time_since_epoch来计算给定日期与1月1日0000之间的差异?
我尝试了以下方法:
#include <iostream>
#include <chrono>
#include <ctime>
int main(int argc, char*argv[])
{
std::tm epochStart = {};
epochStart.tm_sec = 0;
epochStart.tm_min = 0;
epochStart.tm_hour = 0;
epochStart.tm_mday = 0;
epochStart.tm_mon = 0;
epochStart.tm_year = -1900;
epochStart.tm_wday = 0;
epochStart.tm_yday = 0;
epochStart.tm_isdst = -1;
std::time_t base = std::mktime(&epochStart);
std::chrono::system_clock::time_point baseTp=
std::chrono::system_clock::from_time_t(base);
std::time_t btp = std::chrono::system_clock::to_time_t(baseTp);
std::cout << "time: " << std::ctime(&btp);
}
Run Code Online (Sandbox Code Playgroud)
但这给了我
time: Thu Jan 1 00:59:59 1970
Run Code Online (Sandbox Code Playgroud)
我会std::time_t完全避免.使用days_from_civil时间兼容的低级别日期算法,您可以立即计算出公历日历1中的任何差异std::chrono::system_clock::time_point和任何日期.
除了days_from_civil需要一年/每月/每天三倍并将其转换为1970-01-01之前/之后的天数(时间兼容的纪元),创建chrono::duration24小时的自定义也很方便:
typedef std::chrono::duration
<
int,
std::ratio_multiply<std::ratio<24>, std::chrono::hours::period>
> days;
Run Code Online (Sandbox Code Playgroud)
现在,您只需创建所需的任何纪元:
constexpr days epoch = days(days_from_civil(0, 1, 1)); // 0000-01-01
Run Code Online (Sandbox Code Playgroud)
在C++ 1y中,这甚至是编译时计算!
你可以std::chrono::duration从任何其他减去这个std::chrono::duration:
auto delta = std::chrono::system_clock::now().time_since_epoch() - epoch;
Run Code Online (Sandbox Code Playgroud)
delta现在std::chrono::duration表示从现在到0000-01-01之间的时间量.然后,您可以根据需要打印出来,或以其他方式操纵它.例如,这是一个完整的工作演示:
#include "../date_performance/date_algorithms"
#include <iostream>
#include <chrono>
typedef std::chrono::duration
<
int,
std::ratio_multiply<std::ratio<24>, std::chrono::hours::period>
> days;
int
main()
{
constexpr days epoch = days(days_from_civil(0, 1, 1));
auto delta = std::chrono::system_clock::now().time_since_epoch() - epoch;
days d = std::chrono::duration_cast<days>(delta);
std::cout << "It has been " << d.count() << " days, ";
delta -= d;
auto h = std::chrono::duration_cast<std::chrono::hours>(delta);
std::cout << h.count() << " hours, ";
delta -= h;
auto m = std::chrono::duration_cast<std::chrono::minutes>(delta);
std::cout << m.count() << " minutes, ";
delta -= m;
auto s = std::chrono::duration_cast<std::chrono::seconds>(delta);
std::cout << s.count() << " seconds ";
std::cout << " since 0000-01-01\n";
}
Run Code Online (Sandbox Code Playgroud)
哪个对我输出:
It has been 735602 days, 19 hours, 14 minutes, 32 seconds since 0000-01-01
Run Code Online (Sandbox Code Playgroud)
关于溢出的警告:
在std::chrono::system_clock::time_point::duration不能保证有足够的范围大到做到这一点.事实证明,在我的系统上它确实如此.签名长的长度为微秒,将超过+/- 292,000年.如果您需要避免溢出问题,可以截断您std::chrono::system_clock::time_point::duration的courser单位(例如秒或天)以在减去0000-01-01之前扩展范围.
我开始思考
这通常会导致灾难.但是在这种情况下,无论如何我决定加入这篇文章.这个:
constexpr days epoch = days(days_from_civil(0, 1, 1));
Run Code Online (Sandbox Code Playgroud)
有类型days,这是一个duration.但它确实不是一个duration.这是一个时间点.这是约会.它time_point具有粗糙的精度.通过引入一个新的typedef,这篇文章中的代码可以稍微清理一下:
typedef std::chrono::time_point<std::chrono::system_clock, days> date_point;
Run Code Online (Sandbox Code Playgroud)
现在而不是写:
constexpr days epoch = days(days_from_civil(0, 1, 1));
Run Code Online (Sandbox Code Playgroud)
人们可以写:
constexpr date_point epoch{days(days_from_civil(0, 1, 1))};
Run Code Online (Sandbox Code Playgroud)
但更重要的是,而不是:
auto delta = std::chrono::system_clock::now().time_since_epoch() - epoch;
Run Code Online (Sandbox Code Playgroud)
我们现在可以写:
auto delta = std::chrono::system_clock::now() - epoch;
Run Code Online (Sandbox Code Playgroud)
这delta仍然具有与之前完全相同的类型和值,并且演示中的其他所有内容仍然与之前完全一样.
这既是一个小变化,也是一个很大的变化.通过将's和's 的代数epoch视为time_point代替a duration,它们为我们工作,简化和类型检查我们的表达式,以帮助我们编写更清晰的代码,减少错误.time_pointduration
例如,可以将两个duration一起添加.但它完全没有任何意义:
epoch + epoch
Run Code Online (Sandbox Code Playgroud)
通过使用time_point而不是duration类型epoch,编译器在编译时捕获这样的非敏感表达式.
1的proleptic公历有一个0年在这一年0是儒略历后面2天.使用0年也符合ISO 8601.只要所有相关方知道您使用的是哪个日历,那么一切都很好.如果需要,非正年和"BC年"之间的转换是微不足道的.
| 归档时间: |
|
| 查看次数: |
2187 次 |
| 最近记录: |