我有一个日期时间字符串:
20:48:01.469 UTC 2016年3月31日
我想使用struct tm
将此时间字符串表示转换为strptime
,但我的格式字符串不起作用。
是否有小数秒的格式说明符?可能是%S
,%s
或其他什么?
代码段如下:
tm tmbuf;
const char *str = "20:48:01.469 UTC MAR 31 2016"
const char *fmt = "%H:%M:%s %Z %b %d %Y";
strptime(str,fmt,&tmbuf);
答案 0 :(得分:3)
使用这个free, open source C++11/14 library,这是处理解析小数秒的另一种方法:
#include "tz.h"
#include <iostream>
#include <sstream>
int main()
{
using namespace date;
using namespace std::chrono;
std::istringstream str("20:48:01.469 UTC MAR 31 2016");
sys_time<milliseconds> tp;
parse(str, "%T %Z %b %d %Y", tp);
std::cout << tp << '\n';
}
输出:
2016-03-31 20:48:01.469
即,使用此工具%S
和%T
正常工作。不使用标志来控制精度,而是使用std::chrono::time_point
的精度。
如果你想找出你解析的时区缩写,那也是可能的:
std::istringstream str("20:48:01.469 UTC MAR 31 2016");
sys_time<milliseconds> tp;
std::string abbrev;
parse(str, "%T %Z %b %d %Y", tp, abbrev);
std::cout << tp << ' ' << abbrev << '\n';
输出:
2016-03-31 20:48:01.469 UTC
这就是说,这个库建立在std::get_time
之上,因此具有相同的可移植性问题,Jonathan的优秀(和赞成)答案暗示:只有libc ++目前以不区分大小写的方式解析月份名称。希望这将在不太遥远的未来发生变化。
VSO#232129错误报告。
如果你必须处理UTC以外的时区,一般来说,没有确定的方法可以做到这一点,因为在任何时候,不止一个时区可以使用相同的缩写。因此UTC偏移可能不明确。但是here is a short article关于如何使用这个库将缩写缩小到候选时区列表,你可能会从中选择一个独特的时区。
答案 1 :(得分:1)
请注意,表示最小时间增量的tm
成员为tm_sec
,这是int
,仅在以下范围内定义:
自C ++ 11以来[0,60]分钟后的秒数
因此,您无法在tm
中存储一小段时间,您只需要丢弃小数点后的数字。
As suggested by Karsten Koop你可以读两年,第二个%Y
会踩到第一个:
auto fmt = "%H:%M:%S.%Y %Z %b %d %Y";
那就是说,我建议使用strptime
使用get_time
它是一个POSIX函数,使用像Live Example这样的标准函数会更好。这有一个小缺点; get_time
没有时区知识,但tm
也没有,tm_isdst
除外:
夏令时标志。如果DST生效,则该值为正,否则为零;如果没有可用信息则为负
因此,如果你坚持这样的话,你可能需要独立分配tm_isdst
:
tm tmbuf;
stringstream str("20:48:01.469 UTC MAR 31 2016");
str >> get_time(&tmbuf, "%H:%M:%S.%Y UTC %b %d %Y");
我的get_time
回答有点虚伪,因为当我谈到标准化的重要性时,我只能让它在libc ++上运行。因此,我认为我发布了一个更通用的解决方案,它也会丢弃时区,所以您再次需要独立设置tm_isdst
:
tm tmbuf{};
stringstream str("20:48:01.469 UTC MAR 31 2016");
string tm_mon;
str >> get_time(&tmbuf, "%T");
str.ignore(std::numeric_limits<std::streamsize>::max(), 'C');
str >> tm_mon >> get_time(&tmbuf, "%d %Y");
for (const auto& i : { "JAN"s, "FEB"s, "MAR"s, "APR"s, "MAY"s, "JUN"s, "JUL"s, "AUG"s, "SEP"s, "OCT"s, "NOV"s, "DEC"s }) {
if (equal(cbegin(tm_mon), cend(tm_mon), cbegin(i), cend(i), [](const unsigned char a, const unsigned char b) { return toupper(a) == b; })) break;
++tmbuf.tm_mon;
}
这有两个关键依赖项:
'C'
结尾(必须为大写)initializer_list