如何使用c++日期库中的make_zoned?

问题描述 投票:0回答:1

我正在尝试使用日期(https://howardhinnant.github.io/date/date.html)库将数据/时间字符串转换为属于特定时区的日期/时间。

我正在用这个:

std::string t = "2024-01-02T14:42:27";
std::stringstream str(t);
std::chrono::time_point< std::chrono::system_clock, std::chrono::seconds > src_timestamp;
date::from_stream( str, "%Y-%m-%dT%H:%M:%S", result );
const auto src_tz = locate_zone(std::string("CET"));
auto zoned_src_timestamp = make_zoned(src_tz, src_timestamp);
std::cout << zoned_src_timestamp.get_local_time() << " TZ\n";

当我打印 zoned_src_timestamp.get_local_time() 时,我希望看到我的当地时间,但我得到的是“2024-01-02 15:42:27”。这不是我期待的当地时间。

我正在尝试将日期/时间字符串解析为 time_point 并将其与时区一起使用以获得可以转换为不同时区的本地时间。

c++ time c++-chrono
1个回答
0
投票

我正在尝试将日期/时间字符串解析为 time_point 并将其与时区一起使用以获得可以转换为不同时区的本地时间。

std::string t = "2024-01-02T14:42:27";
std::stringstream str(t);

到目前为止一切顺利。但我将“与时区一起使用”解释为“将时间解析为时区中的当地时间”,即“CET”。为此,

src_timestamp
的类型必须是
local_time
实例化,而不是
sys_time
实例化。

sys_time
是基于
time_point
system_clock
系列,始终表示 Unix Time
local_time
表示尚未与特定
time_zone
配对的当地时间。秒精度有一个特定的类型别名,称为
local_seconds
,可以方便使用:

date::local_seconds src_timestamp;

如果您更喜欢另一种精度,例如

milliseconds
,那么那就是:

date::local_time<std::chrono::millliseconds> src_timestamp;

然后用

local_time
:

进行解析
date::from_stream( str, "%Y-%m-%dT%H:%M:%S", src_timestamp );

如果您将其打印回来,您将得到完全相同的时间。现在用它来创建一个具有所需

zoned_time
time_zone
。您可以使用
time_zone const*
或字符串来指定
time_zone
:

auto zoned_src_timestamp = date::zoned_time("CET", src_timestamp);

这假设 C++17 或更高版本。

make_zoned
对于 C++11/14 来说很方便,因为它可以解决缺乏 CTAD 的问题。

zoned_src_timestamp
的构造创建了
{time_zone const*, sys_time}
的对数据结构。
sys_time
是在构造时使用
time_zone const*
local_time
转换为
sys_time
来计算的。如果您询问此对象的当地时间:
zoned_src_timestamp.get_local_time()
,那么它只会将
sys_time
转换回您用来构造它的
local_time

还可以用

zoned_time
构造
sys_time
,在这种情况下,在构造时可以避免转换为本地,并且只需存储
sys_time

一个人还可以用

另一个
zoned_time 构造一个
zoned_time
。我相信这就是您正在寻找的:

auto zoned_local_timestamp = date::zoned_time{date::current_zone(),
                                              zoned_src_timestamp};

这使用

current_zone()
作为
time_zone
,并使用
zoned_src_timestamp
作为“时间戳”。

  • current_zone()
    只是将
    time_zone const*
    返回到您的计算机当前设置的本地时区。

  • 使用

    zoned_src_timestamp
    进行构造,使用其
    sys_time
    来构造新的
    zoned_time
    ,以便两个
    zoned_time
    代表同一时刻,尽管位于(可能)不同的时区。 IE。它们具有相同的 UTC 时间,但当地时间不同。

然后就可以从

zoned_local_timestamp
中获取当地时间:

std::cout << zoned_local_timestamp.get_local_time() << " TZ\n";

zoned_time
只是一个方便的包装。您也可以直接使用
time_zone
来完成同样的事情:

std::string t = "2024-01-02T14:42:27";
std::stringstream str(t);
date::local_seconds src_timestamp;
date::from_stream( str, "%Y-%m-%dT%H:%M:%S", src_timestamp );
auto utc_timestamp = date::locate_zone("CET")->to_sys(src_timestamp);
auto local_timestamp = date::current_zone()->to_local(utc_timestamp);
std::cout << local_timestamp << " TZ\n";
当您想要使用 UTC 偏移量或时区缩写进行格式化时,

zoned_time
变得更加方便,因为
zoned_time
将有关
time_zone
/
local_time
组合的所有信息收集到单个对象中。

zoned_time
在通用代码中也会更方便,其中“时间戳”可以是
sys_time
local_time

© www.soinside.com 2019 - 2024. All rights reserved.