从编译时已知的日历日期创建"std::chrono::time_point"



这个答案显示了如何将字符串解析为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,该日历日期的年、月和月几在编译时是已知的,有没有比从上面建议的字符串解析它更简单的方法?

如果你有 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));

指定的初始值设定项被注释掉,因为它们仅在 C++20 中可用(尽管 gcc 已经支持简单的指定初始值设定项作为扩展一段时间了,并且可以处理这种情况(。 如果指定了完整的 C++20 个初始值设定项并希望在目标日期的午夜,则可以省略初始化为零的字段。

请务必注意,mktime会将tm解释为当地时间,而不是格林威治标准时间或世界标准时间。 如果tm_isdst未设置为 -1,则它将是本地标准时间,即使本地时区将在指定时间内使用夏令时(夏令时(。

std::tm生成 UTC 时间点 ,与您的示例共享的问题,在其他问题中得到解决,例如 将结构 tm(以 UTC 表示(转换为time_t类型的简单方法

是的,您可以在编译时进行整个计算,使用 Howard Hinnant 的日期/时间库创建constexpr system_clock::time_point

#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的日期/时间库需要C++14constexpr肌肉。 C++11constexpr是不够的(但您可以在运行时执行此操作,删除constexprstatic_assert(。

这适用于 C++11 及更高版本:

#include <chrono>
std::chrono::system_clock::time_point
createDateTime(int year,
int month,
int day,
int hour,
int minute,
int second) // these are UTC values
{
tm timeinfo1 = tm();
timeinfo1.tm_year = year - 1900;
timeinfo1.tm_mon = month - 1;
timeinfo1.tm_mday = day;
timeinfo1.tm_hour = hour;
timeinfo1.tm_min = minute;
timeinfo1.tm_sec = second;
tm timeinfo = timeinfo1;
time_t tt = toUTC(timeinfo);
return std::chrono::system_clock::from_time_t(tt);
}
time_t toUTC(std::tm& timeinfo)
{
#ifdef _WIN32
std::time_t tt = _mkgmtime(&timeinfo);
#else
time_t tt = timegm(&timeinfo);
#endif
return tt;
}

取自 ApprovalTests/utilities/DateUtils.cpp

最新更新