使用date.h和std::chrono处理日历持续时间算法,但得到意外结果。
示例代码为:
#include "date.h"
#include <string>
#include <chrono>
#include <iostream>
int main() {
date::sys_seconds calendarDate = {};
calendarDate = std::chrono::years(30) + date::sys_seconds(std::chrono::days(10));
std::string stringDate = date::format("%Y-%m-%d %H:%M:%S", calendarDate);
std::cout << "{} + 30 years + 10 days = " << stringDate << "\n";
return 0;
}
实际产量:{} +30年+10天= 2000年1月11日06时36分
预期输出:{} +30年+10天= 2000年1月11日00:00:00
使用Ubuntu 22.04;g++ 11.3.0
编制单位:gcc -g -标准品=c++20主要成分cpp-最低标准品dc ++
从此处使用date. h:https://raw.githubusercontent.com/HowardHinnant/date/master/include/date/date.h
你对额外的6小时36分钟增加了什么有什么见解吗?
3条答案
按热度按时间v9tzhpje1#
这是因为闰年的缘故。
在定义
std::chrono::years
时考虑了这一点,将其定义为duration type with Periodstd::ratio<31556952>
(60 * 60 * 24 * 365.2425 = 31556952)。但是,如果将此值与一年的非闰年持续时间(60 * 60 * 24 * 365 = 31536000)进行比较,则会得到20952秒或5小时49分12秒的差值。如果将该差值乘以30,则会得到:
7天6小时36分零秒--而且至少后面的部分你应该看起来很熟悉。
但是那7天呢?事实证明在1970年到2000年之间:1972年、1976年、1980年、1984年、1988年、1992年和1996年是闰年--如果你算上闰年,那就是7年,这就是日子的流逝。
您可以通过更改代码并查看输出来检查这一点:
calendarDate += std::chrono::seconds(60 * 60 * 24 * 365 * 30);
-“1999年12月25日00:00:00”calendarDate += std::chrono::seconds(60 * 60 * 24 * 365 * 30) + day(7);
-“2000年1月1日00:00:00”顺便说一下,问题是
std::chrono::years
提供的是一个 * 平均 * 年的长度,而date.h
库知道(并关心)具体的年份:它知道1970年不是闰年(60 * 60 * 24 * 365 = 31536000秒),但1972年是闰年(60 * 60 * 24 * 366 = 31622400秒)。如果你增加了31年,那么你会从平均年增加5:49:12的偏差,但然后删除1天,因为2000年也是闰年-所以它将打印的时间仍然是2000年,但大约12小时前的新年2001年。
0aydgbwb2#
除了Frodyne's good answer(我投了赞成票),我想补充的是,您可以使用date.h执行 chronological 算术或 calendrical 算术。
您已经完成了 chronological 运算,其中
years
被认为是一个统一的单位,等于平均民用年。日历算术遵循日历的不规则性,这也是你所期望的。下面是你将如何实现这一点:
首先将时间转换为日历日期,并将
years
添加到日历日期中,然后再将其转换回时间。下面是另一个SO答案,它遵循了同样的原则,只是使用了月份:https://stackoverflow.com/a/43018120/576911
vmdwslir3#
Linux将日期存储为UTC。我猜您的机器位于中央时区(CT),距离UTC +6小时。