如何使用 chrono::parse 在流中写入/读取 std::chrono::zoned_seconds?

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

我正在尝试将

chrono::zoned_seconds
对象作为文本写入文件,然后检索它并稍后构造另一个
chrono::zoned_seconds
对象。如何以相当有效的方式完成此操作?

我认为下面的代码片段没有显示正确的结果:

#include <fstream>
#include <print>
#include <chrono>
#include <format>
#include <string>
#include <sstream>


int main()
{
    {
        std::ofstream file("data.txt");
        if (!file) {
            std::println( "Unable to open file.\n" );
            return 1;
        }

        auto now = std::chrono::system_clock::now();
        const std::chrono::zoned_seconds zs { "America/New_York", std::chrono::time_point_cast<std::chrono::seconds>( now ) };

        std::format_to(std::ostreambuf_iterator<char>(file), "{:%F %T %Z}", zs);
        std::println( "{:%F %T %Z}", zs ); // correct time
    }

    {
        std::ifstream file("data.txt");
        if (!file) {
            std::println( "Unable to open file.\n" );
            return 1;
        }

        std::string str;
        std::getline(file, str);
        std::istringstream iss { str };

        std::chrono::sys_seconds tp;
        std::string zone_name;
        iss >> std::chrono::parse("%F %T %Z", tp, zone_name);
        std::chrono::zoned_seconds zs { zone_name, tp };
        std::println( "{:%F %T %Z}", zs );  // incorrect time!!
    }
}

可以看出,我使用了

std::chrono::parse
但输出不匹配:

2024-03-01 13:35:20 EST
2024-03-01 08:35:20 EST
c++ datetime-format fstream c++-chrono c++23
2个回答
1
投票

您的代码中有两个错误。为了向他们展示我将通过

stringstream
进行读写来简化事情。

这是您的代码,除了使用

stringstream
之外,没有更改:

#include <sstream>
#include <print>
#include <chrono>
#include <format>
#include <string>
#include <sstream>


int main()
{
    std::stringstream file;
    auto now = std::chrono::floor<std::chrono::seconds>(std::chrono::system_clock::now());
    const std::chrono::zoned_seconds zs { "America/New_York", now };

    file << std::format( "{:%F %T %Z}", zs);
    std::println( "{:%F %T %Z}", zs ); // correct time

    std::chrono::sys_seconds tp;
    std::string zone_name;
    file >> std::chrono::parse("%F %T %Z", tp, zone_name);
    std::chrono::zoned_seconds zs2 { zone_name, tp };
    std::println( "{:%F %T %Z}", zs2 );
}

当前的输出看起来像

2024-03-01 14:04:28 EST 2024-03-01 09:04:28 EST
时间差异较大的原因是,当您格式化

zoned_time

时,它显示的是
本地时间,而不是UTC。但是,当您在上面阅读时,您正在解析,就好像解析的时间是 UTC,而不是本地时间:

std::chrono::sys_seconds tp;
将上面的行更改为:

std::chrono::local_seconds tp;
您将 

2024-03-01 14:04:28

 的语义从 UTC 更改为 
local 时间。

输出:

2024-03-01 14:08:06 EST 2024-03-01 14:08:06 EST
虽然这看起来是对的,但它仍然是微妙的错误。

EST

 是 IANA 时区,没有 DST 规则。它的固定 UTC 偏移量为 -5 小时。一年中的几个月,
America/New_York
EST
 相同,然后在一年中的其余时间实行夏令时。所以上面的程序只有在夏令时不生效的情况下才是正确的 
America/New_York

要纠正此错误,“America/New_York”必须存储在

file

 而不是 
EST
 中。这可以通过更改一行来解决:

file << std::format( "{:%F %T %Z}", zs);
至:

file << std::format( "{:%F %T }", zs) << zs.get_time_zone()->name();
即这会输出实际时区

名称,而不是时区缩写

输出:

2024-03-01 14:13:30 EST 2024-03-01 14:13:30 EST
    

0
投票
std::chrono::sys_seconds tp; std::string zone_name; iss >> std::chrono::parse("%F %T %Z", tp, zone_name);
这是不正确的。您正在将分区时间 H:M:S 解析为 sys_seconds 时间点。

由此产生的时间点是一个谎言。它位于错误的时区 - 系统时区。

当您将错误的时区时间点转换为 NY 时,它会正确更改小时值。

A

std::local_time

 是没有时区的时间。您想使用它而不是那里的 
sys_time

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