This答案显示如何将字符串解析为std::chrono::time_point
,如下所示:
std::tm tm = {};
std::stringstream ss("Jan 9 2014 12:35:34");
ss >> std::get_time(&tm, "%b %d %Y %H:%M:%S");
auto tp = std::chrono::system_clock::from_time_t(std::mktime(&tm));
如果我想从(公历)日历日期创建一个std::chrono::time_point
,其日年,月份和日期在编译时是已知的,有没有比上面建议的字符串解析它更简单的方法?
是的,你可以在编译时完成整个计算,使用constexpr system_clock::time_point
创建一个Howard Hinnant's date/time library。
#include "date/date.h"
#include <chrono>
int
main()
{
using namespace date;
using namespace std::chrono;
constexpr system_clock::time_point tp = sys_days{January/9/2014} + 12h + 35min + 34s;
static_assert(tp == system_clock::time_point{1389270934s}, "");
}
这假设日期/时间是UTC。如果不是,则必须手动添加/减去UTC偏移量才能实现。随着时区规则随着政治家的一时兴起而改变,制作constexpr
的希望渺茫。当误解被揭露时,甚至历史时区规则也会更新。
此程序还将通过删除#include "date/date.h"
和using namespace date;
移植到C ++ 20。同样使用Howard Hinnant's date/time library需要C ++ 14 constexpr
肌肉。 C ++ 11 constexpr
还不够(但你可以在运行时完成它,放弃constexpr
和static_assert
)。
如果您有c ++ 20,或者将使用Howard Hinnant日期/时间库,那么Howard Hannant的答案会更好,因为它会为您提供constexpr time_point。
但是,如果还没有c ++ 20并且想要避免添加更多外部库,那么这个答案仍然有用。
您可以在初始化程序中单独设置std::tm
的成员,以避免解析字符串。
// 9th January, 2014
#define DAY 9
#define MONTH 1
#define YEAR 2014
std::tm tm = { .tm_sec = 0,
.tm_min = 0,
.tm_hour = 0,
.tm_mday = (DAY),
.tm_mon = (MONTH) - 1,
.tm_year = (YEAR) - 1900,
};
tm.tm_isdst = -1; // Use DST value from local time zone
auto tp = std::chrono::system_clock::from_time_t(std::mktime(&tm));
由于gcc对C ++代码中非平凡指定的初始值设定项的限制,因此只能在那里对零字段进行初始化,如果想要在编译日期的午夜,则可以省略。
值得注意的是,mktime
会将tm
解释为当地时间,而不是GMT或UTC。如果tm_isdst
未设置为-1,则它将是本地标准时间,即使夏令时(夏令时)将在指定时间内在本地时区使用。
从std::tm
生成UTC时间点,与您的示例共享的问题,在其他问题中得到解决,例如Easy way to convert a struct tm (expressed in UTC) to time_t type