如何在C ++中将iso 8601日期(带有可选的毫秒)解析为struct tm? [英] how do I parse an iso 8601 date (with optional milliseconds) to a struct tm in C++?

查看:263
本文介绍了如何在C ++中将iso 8601日期(带有可选的毫秒)解析为struct tm?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个字符串,应该以 ISO 8601 格式指定日期和时间,或可能没有毫秒,并且我想从中获取struct tm以及可能已指定的任何毫秒值(如果字符串中不存在,则可以假定为零).

I have a string which should specify a date and time in ISO 8601 format, which may or may not have milliseconds in it, and I am wanting to get a struct tm from it as well as any millisecond value that may have been specified (which can be assumed to be zero if not present in the string).

检测字符串是否格式正确以及将用户指定的字符串转换为struct tm和毫秒值将涉及什么?

What would be involved in detecting whether the string is in the correct format, as well as converting a user-specified string into the struct tm and millisecond values?

如果不是针对Millisconds的问题,我可能只使用C函数strptime(),但是我不知道当秒数包含小数点时该函数的定义行为是什么.

If it weren't for the millisconds issue, I could probably just use the C function strptime(), but I do not know what the defined behavior of that function is supposed to be when the seconds contain a decimal point.

作为最后的告诫,如果可能的话,我非常希望这样一种解决方案,该解决方案不依赖于仅在Boost中找到的函数(但是我很乐意接受C ++ 11作为前提条件) ).

As one final caveat, if it is at all possible, I would greatly prefer a solution that does not have any dependency on functions that are only found in Boost (but I'm happy to accept C++11 as a prerequisite).

输入将类似于:

2014-11-12T19:12:14.505Z

2014-11-12T12:12:14.505-5:00

在这种情况下,

Z表示UTC,但是可以使用任何时区,并且将表示为相对于GMT的+或-小时/分钟.秒字段的小数部分是可选的,但事实上它可能在那里,这就是为什么我不能简单地使用strptime()std::get_time()的原因,如果在字符中找到了这样的字符,它们就不会描述任何特定的已定义行为.字符串的秒部分.

Z, in this case, indicates UTC, but any time zone might be used, and will be expressed as a + or - hours/minutes offset from GMT. The decimal portion of the seconds field is optional, but the fact that it may be there at all is why I cannot simply use strptime() or std::get_time(), which do not describe any particular defined behavior if such a character is found in the seconds portion of the string.

推荐答案

您可以使用Csscanf( http://www.cplusplus.com/reference/cstdio/sscanf/)进行解析:

You can use C's sscanf (http://www.cplusplus.com/reference/cstdio/sscanf/) to parse it:

const char *dateStr = "2014-11-12T19:12:14.505Z";
int y,M,d,h,m;
float s;
sscanf(dateStr, "%d-%d-%dT%d:%d:%fZ", &y, &M, &d, &h, &m, &s);

如果您有std::string,则可以这样调用它( http://www.cplusplus.com/reference/string/string/c_str/):

If you have std::string it can be called like this (http://www.cplusplus.com/reference/string/string/c_str/):

std::string dateStr = "2014-11-12T19:12:14.505Z";
sscanf(dateStr.c_str(), "%d-%d-%dT%d:%d:%fZ", &y, &M, &d, &h, &m, &s);

如果它应该处理不同的时区,则需要使用sscanf返回值-解析参数的数量:

If it should handle different timezones you need to use sscanf return value - number of parsed arguments:

int tzh = 0, tzm = 0;
if (6 < sscanf(dateStr.c_str(), "%d-%d-%dT%d:%d:%f%d:%dZ", &y, &M, &d, &h, &m, &s, &tzh, &tzm)) {
    if (tzh < 0) {
       tzm = -tzm;    // Fix the sign on minutes.
    }
}

然后您可以填写tm( http://www.cplusplus.com/reference/ctime/tm/)结构:

And then you can fill tm (http://www.cplusplus.com/reference/ctime/tm/) struct:

tm time;
time.tm_year = y - 1900; // Year since 1900
time.tm_mon = M - 1;     // 0-11
time.tm_mday = d;        // 1-31
time.tm_hour = h;        // 0-23
time.tm_min = m;         // 0-59
time.tm_sec = (int)s;    // 0-61 (0-60 in C++11)

也可以通过std::get_time( http://en. cppreference.com/w/cpp/io/manip/get_time ),因为C++11如@Barry在评论

It also can be done with std::get_time (http://en.cppreference.com/w/cpp/io/manip/get_time) since C++11 as @Barry mentioned in comment how do I parse an iso 8601 date (with optional milliseconds) to a struct tm in C++?

这篇关于如何在C ++中将iso 8601日期(带有可选的毫秒)解析为struct tm?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆