我正在尝试将
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
您的代码中有两个错误。为了向他们展示我将通过
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
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
。