使用 Howard Hinnant 的库解析带有时区名称的日期/时间时出现问题
我正在编写一种方法来解析各种格式的日期/时间字符串。
std::chrono::system_clock::time_point toTimePoint(const std::string str) {
... a bunch of code that determines the format of the input string
std::string formatStr = string{"%Y-%m-%d"}
+ " " // Delimeter between date and time.
+ "%H:%M:%S"
+ "%t%Z"
;
// The %t should be 0 or 1 whitespace
// The %Z should be a timezone name
std::chrono::system_clock::time_point retVal;
std::istringstream in{str};
in >> date::parse(formatStr, retVal);
return retVal;
}
然后我用各种输入对其进行测试。其他格式都有效。我可以这样做:
2022-04-01 12:17:00.1234
2022-04-01 12:17:00.1234-0600
2022-04-01 12:17:00.1234-06:00
后两个适用于美国山区夏令时间。它做所有正确的事情。第一个显示为 12:17:00 UST。另外两个时间为 18:17:00 UST。工作得很好。为了简洁起见,我省略了所有代码。不起作用的是:
2022-04-01 12:17:00.1234 US/Central
在编写不同的程序来转储霍华德库已知的时区名称后,我尝试了各种时区名称。它们都不重要。我得到一个没有时区偏移的 UST 时间值。
幸运的是,我现在需要的是 -06:00 格式,这样我就可以继续前进。但我想修复代码,因为我们还有其他地方使用时区名称,并且我想让它正常工作。
我不确定我做错了什么。
I'm writing a method to parse date/time strings in a variety of formats.
std::chrono::system_clock::time_point toTimePoint(const std::string str) {
... a bunch of code that determines the format of the input string
std::string formatStr = string{"%Y-%m-%d"}
+ " " // Delimeter between date and time.
+ "%H:%M:%S"
+ "%t%Z"
;
// The %t should be 0 or 1 whitespace
// The %Z should be a timezone name
std::chrono::system_clock::time_point retVal;
std::istringstream in{str};
in >> date::parse(formatStr, retVal);
return retVal;
}
I then test it with a variety of inputs. The other formats work. I can do these:
2022-04-01 12:17:00.1234
2022-04-01 12:17:00.1234-0600
2022-04-01 12:17:00.1234-06:00
The latter two are for US Mountain Daylight Time. It does all the right things. The first one shows as 12:17:00 UST. The other two are 18:17:00 UST. Working great. I've omitted all that code for brevity. What does not work is this:
2022-04-01 12:17:00.1234 US/Central
I've tried a variety of timezone names after writing a different program to dump the ones known by Howard's library. None of them matter. I get a UST-time value with no time zone offset.
Luckily, what I need right now is the -06:00 format, so I can move forward. But I'd like to fix the code, as we have other places that use timezone names, and I'd like to get this working properly.
I'm not sure what I'm doing wrong.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
当使用
%z
(例如-0600
)读取偏移量时,结合sys_time
类型(例如system_clock::time_point
) code>,解析时间点被解释为本地时间,并且应用偏移量来获取sys_time
,如前两个示例中所期望的那样。然而,当使用
%Z
读取时区名称或缩写时,情况并非如此(请注意从小写 z 到大写 Z 的变化)。%Z
解析时区缩写或名称,它只是一个字符串。常见情况是仅解析缩写,例如 CST。一般来说,从缩写到偏移量不存在唯一的映射。因此偏移量不能在内部应用。因此,解析的值应始终被解释为本地时间。然而一切并没有失去。您可以将带有
%Z
的时区名称解析为字符串,然后查找具有该名称的time_zone
并使用它来转换解析的local_time 转换为
sys_time
。这可能看起来像:只需在
parse
调用中添加一个string
作为第三个参数,并确保第一个参数是local_time
而不是一个sys_time
。然后使用locate_zone
获取time_zone const*
并用它调用to_sys
,传入解析后的local_time
。上述程序输出:
这是与 -6 小时偏移量相比的一个小时,因为美国/中部地区于 2022 年 3 月 13 日(-5 小时偏移量)进入夏令时。
When reading an offset with
%z
(e.g.-0600
), combined with asys_time
type such assystem_clock::time_point
, the parse time point is interpreted as a local time, and the offset is applied to get thesys_time
, as desired in your first two examples.However this is not the case when reading a time zone name or abbreviation with
%Z
(note the change from lower case z to upper case Z).%Z
parses a time zone abbreviation or name, which is just a string. The common case is for this to just parse an abbreviation, e.g. CST. And in general, there is no unique mapping from an abbreviation to an offset. And so the offset can not be internally applied. Thus the parsed value should always be interpreted as a local time.However all is not lost. You can parse the time zone name with
%Z
into a string, and then look up thetime_zone
with that name and use it to convert the parselocal_time
into asys_time
. This could look like:Just add a
string
as the third argument in yourparse
call, and make sure the first argument is alocal_time
instead of asys_time
. Then uselocate_zone
to get atime_zone const*
and callto_sys
with that, passing in the parsedlocal_time
.The above program outputs:
This is an hour off from the -6h offset because US/Central goes to daylight saving on 2022-03-13 (-5h offset).