当我们有毫秒级别的日期时间字符串时,对于 strptime
来说下一个最好的选择是什么?
已知:
"30/03/09 16:31:32.121"
我们不能使用常规的strptime,因为struct tm
不存储毫秒。是否有新的类可以实现这一点?
我会手动解析这些字段(将秒读入int和double),然后使用days_from_civil将年/月/日转换为chrono::system_clock::time_point
:
std::chrono::system_clock::time_point t(days(days_from_civil(y, m, d)));
其中 days
表示:
using days = std::chrono::duration<int, std::ratio<86400>>;
然后你可以加上小时、分钟和秒。为了处理小数秒,你需要进行一些微调:
double s;
your_stream >> s; // 32.121
using namespace std::chrono;
duration<double> dsecs(s);
seconds sec = duration_cast<seconds>(dsecs);
milliseconds ms = duration_cast<milliseconds>(dsecs - sec);
t += sec + ms;
round
进行毫秒转换:milliseconds ms = round<milliseconds>(dsecs - sec);
duration_cast
是向零舍入的。还有其他的舍入模式:floor,round,ceil,在此链接上可以查看。
将其封装在一个整洁的函数中以便于重复使用。:-)
上述代码都假定为UTC时间。如果您正在解析的日期/时间已知与UTC相差多少,您可以添加/减去该偏移量。所有已知的system_clock
实现都跟踪Unix时间,即从1970-01-01起在UTC时区的秒数。
更新
自撰写本答案以来,我开发了一个更通用的库,似乎当时OP正在寻找。它可以直接将各种亚秒精度解析为std::chrono::system_clock::time_point
,如下所示:
#include "date/date.h"
#include <iostream>
#include <sstream>
int
main()
{
std::istringstream in{"30/03/09 16:31:32.121\n"
"30/03/09 16:31:32.1214"};
std::chrono::system_clock::time_point tp;
in >> date::parse("%d/%m/%y %T", tp);
using namespace date;
std::cout << tp << '\n';
in >> date::parse(" %d/%m/%y %T", tp);
std::cout << tp << '\n';
}
2009-03-30 16:31:32.121000
2009-03-30 16:31:32.121400
这个库使用了我最初描述的相同技术和工具,但是已经打包成一个单一头文件库,可以直接使用。
string
)解析自己的整数值并不难:https://github.com/HowardHinnant/date/blob/master/include/date/ptz.h#L828-L838。然后将这些整数值转换为基于`system_clock`的`time_point`就很容易了:`auto tp = sys_days{day{d}/m/y} + hours{h} + minutes{M} + seconds{s} + milliseconds{ms};`。 - Howard Hinnant
std::get_time
是 C++11 的函数,但它与strptime
的规范相似。您需要存储毫秒吗?还是只需要显示它? - user3920237