旧问题的新答案。新答案的理由:该问题是从其原始形式编辑的,因为当时的工具无法准确处理所询问的内容。最终接受的答案给出的行为与原始问题所要求的行为略有不同。
我并不是要放弃已接受的答案。这是一个很好的答案。只是 C API 如此令人困惑,这样的错误不可避免地会发生。
最初的问题是解析"Thu, 9 Jan 2014 12:35:34 +0000"。很明显,目的是解析代表 UTC 时间的时间戳。但是strptime(它不是标准的 C 或 C++,而是 POSIX)不会解析表明这是一个 UTC 时间戳的尾随 UTC 偏移量(它将使用%z 对其进行格式化,但不会对其进行解析)。
该问题随后被编辑为询问"Thu Jan 9 12:35:34 2014"。但是没有编辑了这个问题,以澄清这是 UTC 时间戳,还是计算机当前 本地 时区中的时间戳。由于使用了std::mktime,因此接受的答案隐式假定时间戳代表计算机的当前本地时区。
std::mktime 不仅将字段类型tm 转换为串行类型time_t,还执行从计算机本地时区到UTC 的偏移调整。
但是,如果我们想将 UTC 时间戳解析为原始(未经编辑的)问题,该怎么办?
今天可以使用更新的 free open-source library 来完成。
#include "date/date.h"
#include <iostream>
#include <sstream>
int
main()
{
using namespace std;
using namespace date;
istringstream in{"Thu, 9 Jan 2014 12:35:34 +0000"};
sys_seconds tp;
in >> parse("%a, %d %b %Y %T %z", tp);
}
这个库可以解析%z。而date::sys_seconds 只是一个类型定义:
std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>
问题还问:
从生成的持续时间中,我需要访问秒数、分钟数、小时数和天数。
那部分仍未得到答复。以下是使用 this library 的方法。
#include "date/date.h"
#include <chrono>
#include <iostream>
#include <sstream>
int
main()
{
using namespace std;
using namespace date;
istringstream in{"Thu, 9 Jan 2014 12:35:34 +0000"};
sys_seconds tp;
in >> parse("%a, %d %b %Y %T %z", tp);
auto tp_days = floor<days>(tp);
auto hms = hh_mm_ss<seconds>{tp - tp_days};
std::cout << "Number of days = " << tp_days.time_since_epoch() << '\n';
std::cout << "Number of hours = " << hms.hours() << '\n';
std::cout << "Number of minutes = " << hms.minutes() << '\n';
std::cout << "Number of seconds = " << hms.seconds() << '\n';
}
floor<days> 将秒精度 time_point 截断为 天精度 time_point。如果从 tp 中减去天数精度 time_point,则剩下的 duration 表示自午夜 (UTC) 以来的时间。
hh_mm_ss<seconds> 类型采用任何可转换为 seconds 的 duration(在本例中为从午夜开始的时间),并为每个字段创建一个带有 getter 的 {hours, minutes, seconds} 字段类型。如果持续时间的精度小于秒,则此字段类型还将具有亚秒的吸气剂。在 C++17 之前,必须将更精细的持续时间指定为模板参数。在 C++17 及以后的版本中可以推导出来:
auto hms = hh_mm_ss{tp - tp_days};
最后,可以打印出所有这些持续时间。此示例输出:
Number of days = 16079d
Number of hours = 12h
Number of minutes = 35min
Number of seconds = 34s
所以 2014-01-09 是 1970-01-01 之后的 16079 天。
这是完整的示例,但在 milliseconds 精度:
#include "date/date.h"
#include <chrono>
#include <iostream>
#include <sstream>
int
main()
{
using namespace std;
using namespace std::chrono;
using namespace date;
istringstream in{"Thu, 9 Jan 2014 12:35:34.123 +0000"};
sys_time<milliseconds> tp;
in >> parse("%a, %d %b %Y %T %z", tp);
auto tp_days = floor<days>(tp);
hh_mm_ss hms{tp - tp_days};
std::cout << tp << '\n';
std::cout << "Number of days = " << tp_days.time_since_epoch() << '\n';
std::cout << "Number of hours = " << hms.hours() << '\n';
std::cout << "Number of minutes = " << hms.minutes() << '\n';
std::cout << "Number of seconds = " << hms.seconds() << '\n';
std::cout << "Number of milliseconds = " << hms.subseconds() << '\n';
}
输出:
2014-01-09 12:35:34.123
Number of days = 16079d
Number of hours = 12h
Number of minutes = 35min
Number of seconds = 34s
Number of milliseconds = 123ms
这个库现在是 C++20 的一部分,但在 namespace std::chrono 中,可以在标题 <chrono> 中找到。