使用 Howard Hinnant 的库使用时区名称解析 date/time 时出现问题
Problem parsing date/time with timezone name using Howard Hinnant's library
我正在编写一种方法来解析 date/time 多种格式的字符串。
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
在编写了一个不同的程序来转储霍华德图书馆已知的时区名称后,我尝试了各种时区名称。 None 其中很重要。我得到一个没有时区偏移的 UST 时间值。
幸运的是,我现在需要的是 -06:00 格式,所以我可以继续前进。但我想修复代码,因为我们还有其他地方使用时区名称,我想让它正常工作。
我不确定我做错了什么。
当读取带有%z
(例如-0600
)的偏移量时,结合sys_time
类型(例如system_clock::time_point
),解析时间点被解释为本地时间,并根据前两个示例中的需要应用偏移量来获得 sys_time
。
然而,当使用 %Z
读取时区名称或缩写时,情况并非如此(请注意从小写 z 变为大写 Z)。
%Z
解析时区缩写或名称,它只是一个字符串。常见的情况是只解析一个缩写,例如科技委。通常,从缩写到偏移量没有唯一映射。因此不能在内部应用偏移量。因此,解析后的值应始终解释为本地时间。
然而一切并没有丢失。您可以将带有 %Z
的时区名称解析为字符串,然后查找带有该名称的 time_zone
并使用它将解析 local_time
转换为 sys_time
。这可能看起来像:
#include "date/tz.h"
#include <chrono>
#include <iostream>
#include <sstream>
int
main()
{
using namespace date;
using namespace std;
using namespace std::chrono;
istringstream in{"2022-04-01 12:17:00.1234 US/Central"};
string tz_name;
local_time<microseconds> local_tp;
in >> parse("%F %T%t%Z", local_tp, tz_name);
system_clock::time_point tp = locate_zone(tz_name)->to_sys(local_tp);
cout << tp << '\n';
}
只需在 parse
调用中添加 string
作为第三个参数,并确保第一个参数是 local_time
而不是 sys_time
。然后使用 locate_zone
得到一个 time_zone const*
并用它调用 to_sys
,传入解析后的 local_time
.
以上程序输出:
2022-04-01 17:17:00.123400
这与 -6h 偏移相差一个小时,因为 US/Central 在 2022-03-13(-5h 偏移)进入夏令时。
我正在编写一种方法来解析 date/time 多种格式的字符串。
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
在编写了一个不同的程序来转储霍华德图书馆已知的时区名称后,我尝试了各种时区名称。 None 其中很重要。我得到一个没有时区偏移的 UST 时间值。
幸运的是,我现在需要的是 -06:00 格式,所以我可以继续前进。但我想修复代码,因为我们还有其他地方使用时区名称,我想让它正常工作。
我不确定我做错了什么。
当读取带有%z
(例如-0600
)的偏移量时,结合sys_time
类型(例如system_clock::time_point
),解析时间点被解释为本地时间,并根据前两个示例中的需要应用偏移量来获得 sys_time
。
然而,当使用 %Z
读取时区名称或缩写时,情况并非如此(请注意从小写 z 变为大写 Z)。
%Z
解析时区缩写或名称,它只是一个字符串。常见的情况是只解析一个缩写,例如科技委。通常,从缩写到偏移量没有唯一映射。因此不能在内部应用偏移量。因此,解析后的值应始终解释为本地时间。
然而一切并没有丢失。您可以将带有 %Z
的时区名称解析为字符串,然后查找带有该名称的 time_zone
并使用它将解析 local_time
转换为 sys_time
。这可能看起来像:
#include "date/tz.h"
#include <chrono>
#include <iostream>
#include <sstream>
int
main()
{
using namespace date;
using namespace std;
using namespace std::chrono;
istringstream in{"2022-04-01 12:17:00.1234 US/Central"};
string tz_name;
local_time<microseconds> local_tp;
in >> parse("%F %T%t%Z", local_tp, tz_name);
system_clock::time_point tp = locate_zone(tz_name)->to_sys(local_tp);
cout << tp << '\n';
}
只需在 parse
调用中添加 string
作为第三个参数,并确保第一个参数是 local_time
而不是 sys_time
。然后使用 locate_zone
得到一个 time_zone const*
并用它调用 to_sys
,传入解析后的 local_time
.
以上程序输出:
2022-04-01 17:17:00.123400
这与 -6h 偏移相差一个小时,因为 US/Central 在 2022-03-13(-5h 偏移)进入夏令时。