Mus*_*ful 4 c++ c++-chrono c++14
此答案显示了如何将字符串解析为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));
Run Code Online (Sandbox Code Playgroud)
如果我想std::chrono::time_point从一个(Gregorian)日历日期创建一个在编译时就知道其年,月和日的日历日期,是否有比上述字符串解析更简单的方法呢?
如果您使用的是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));
Run Code Online (Sandbox Code Playgroud)
指定的初始值设定项已被注释掉,因为它们仅在C ++ 20中可用(尽管gcc在一段时间内一直支持普通的指定的初始值设定项作为扩展,并且可以在这种情况下使用)。如果一个字段具有完整的C ++ 20指定的初始化程序,并且希望在目标日期的午夜,则可以忽略初始化为零的字段。
重要的是要注意,mktime它将解释tm为本地时间,而不是GMT或UTC。如果tm_isdst未设置为-1,则它将是本地标准时间,即使在本地时区中使用指定时间的夏令时(夏令时)也是如此。
从a产生一个UTC时间点std::tm,这个问题与您的示例共同存在,在其他问题中得到解决,例如将struct tm(以UTC表示)转换为time_t类型的简单方法
是的,您可以在编译时进行整个计算,并constexpr system_clock::time_point使用Howard Hinnant的日期/时间库创建一个。
#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}, "");
}
Run Code Online (Sandbox Code Playgroud)
这是假定日期/时间为UTC。如果不是,则必须手动添加/减去UTC偏移量。由于时区规则总是在政客心血来潮中改变,因此制定这些规则几乎没有希望constexpr。当误解暴露时,甚至历史时区规则也会更新。
此外,该程序还将通过删除#include "date/date.h"和移植到C ++ 20 using namespace date;。另外,使用霍华德·辛南特(Howard Hinnant)的日期/时间库需要C ++ 14 constexpr肌肉。C ++ 11 constexpr是不够的(但是您可以在运行时删除constexprand 来做到static_assert)。