C++ C++;从日期字符串解析时区

C++ C++;从日期字符串解析时区,c++,C++,你好,我有以下日期,我是从api消费 string sToParse = "2020-04-17T09:30:00-04:00"; 应该是人形的“2020年4月17日星期五08:30:00”中央时间 或1587130200年的时代 然而,这个代码 cout << "raw: " << sToParse << endl; static const std::string dateTimeFormat { "%Y-%m-%dT%H:%M:%S%Z" }; ist

你好,我有以下日期,我是从api消费

string sToParse = "2020-04-17T09:30:00-04:00";
应该是人形的“2020年4月17日星期五08:30:00”中央时间 或1587130200年的时代

然而,这个代码

cout << "raw: " << sToParse << endl;
static const std::string dateTimeFormat { "%Y-%m-%dT%H:%M:%S%Z" };
istringstream ss{ sToParse };
tm dt;
ss >> get_time(&dt, dateTimeFormat.c_str());
cout << mktime(&dt) << endl;
coutC++20将执行以下操作:

#include <chrono>
#include <iostream>
#include <sstream>
#include <string>

int
main()
{
    using namespace std;
    using namespace std::chrono;

    string sToParse = "2020-04-17T09:30:00-04:00";
    cout << "raw: " << sToParse << endl;
    static const std::string dateTimeFormat { "%Y-%m-%dT%H:%M:%S%z" };
    istringstream ss{ sToParse };
    sys_seconds dt;
    ss >> parse(dateTimeFormat, dt);
    cout << dt << '\n';
    cout << dt.time_since_epoch() << '\n';
}
这就是你要找的“大纪元时间”。最大的区别在于使用了
%z
而不是
%z
%z
是用于分析偏移量的命令<代码>%Z
解析时区缩写

这没有得到你期望的“人类时间”。上面打印的时间是UTC。检查时,这显然是正确的:13:30:00是09:30:00后4小时

如果你想要当地时间,它将是2020-04-17 09:30:00,与输入相同。提出08:30:00需要的信息比您上面提供的更多(例如,某些时区的输出,而不是在本地时间UTC偏移量为-4h的时区)

此外,通常不可能从UTC偏移量转换为时区名称或缩写,因为在任何时间点,多个时区通常具有相同的UTC偏移量

如果C++20
标题不适用于您(据我所知,它在任何地方都不可用),您可以使用。对于这个问题,我们只需要这个函数的标题“date.h”。所有内容都在
名称空间日期中,而不是
名称空间std::chrono
。它看起来是这样的:

#include "date/date.h"
#include <chrono>
#include <iostream>
#include <sstream>
#include <string>

int
main()
{
    using namespace date;
    using namespace std;
    using namespace std::chrono;

    string sToParse = "2020-04-17T09:30:00-04:00";
    cout << "raw: " << sToParse << endl;
    static const std::string dateTimeFormat { "%Y-%m-%dT%H:%M:%S%z" };
    istringstream ss{ sToParse };
    sys_seconds dt;
    ss >> parse(dateTimeFormat, dt);
    cout << dt << '\n';
    cout << dt.time_since_epoch() << '\n';
}
如果计算机的当前时区设置恰好是US Central,则构成
分区秒数的行也可以如下所示:

    zoned_seconds cst{current_zone(), utc};
或者相反,您可以使用此行在计算机设置为的任何时区中查找utc的本地时间

请注意,无论是使用名称(如
“America/Chicago”
)指定时区,还是使用
current_zone()
)指定时区,都将正确考虑指定时区内UTC偏移量的任何变化(如夏令时)


对于,标头
“tz.h”
的使用不仅仅是标头。它需要一个源文件,
tz.cpp
。但是,如果您使用的是完全一致的C++20
,那么上述操作只需删除
#包括“date/tz.h”
使用名称空间日期即可,并按照上面第5个项目符号中的说明调整格式字符串。

注意:
get_time
不起作用
%z
%z
,因此
tm_isdst
未写入,需要明确设置,以便与
mktime
等函数一起使用。您好,谢谢您的回复。为了适应时区,我还应该使用其他功能吗?您好,谢谢您的评论。给我的时间是EST,api返回2020-04-17T09:30:00-04:00,即我的时间(CST)上午8:30。当我将1587130200转换为“人类”时,我得到了预期的上午8:30。非常感谢你帮助我!!!
#include "date/tz.h"
#include <chrono>
#include <iostream>
#include <sstream>
#include <string>

int
main()
{
    using namespace date;
    using namespace std;
    using namespace std::chrono;

    string sToParse = "2020-04-17T09:30:00-04:00";
    cout << "raw: " << sToParse << endl;
    static const std::string dateTimeFormat { "%FT%T%z" };
    istringstream ss{ sToParse };

    sys_seconds utc;
    ss >> parse(dateTimeFormat, utc);
    zoned_seconds cst{"America/Chicago", utc};

    cout << utc.time_since_epoch() << '\n';
    cout << format("%F %T %Z\n", utc);
    cout << format("%F %T %Z\n", cst);
}
raw: 2020-04-17T09:30:00-04:00
1587130200s
2020-04-17 13:30:00 UTC
2020-04-17 08:30:00 CDT
    zoned_seconds cst{current_zone(), utc};