You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现std::chrono::zoned_time的序列化与反序列化?

实现std::chrono::zoned_seconds的序列化与反序列化

问题背景

std::chrono::zoned_time 并非POD类型(因为它不属于trivial类型),无法直接以原始数据序列的形式读写到文件。它内部包含一个std::chrono::time_point成员,以及一个指向std::chrono::time_zone对象的指针成员。

问题核心在于指针成员无法直接序列化/反序列化,但我们需要同时保存并恢复zoned_time对象的时区信息(而非仅存储时间点)。可行思路是通过std::chrono::time_zone::name获取时区名称,将其字符串形式与时间点的秒数存储到文件,再反向重建对象。

完整代码实现

#include <chrono>
#include <fstream>
#include <string>
#include <stdexcept>

// 序列化zoned_seconds
std::ofstream& operator<<(std::ofstream& ofs, const std::chrono::zoned_seconds& time)
{
    // 1. 写入时区名称的长度,避免读取时字符串截断
    const auto& zone_name = time.get_time_zone()->name();
    const std::size_t name_len = zone_name.size();
    ofs.write(reinterpret_cast<const char*>(&name_len), sizeof(name_len));
    
    // 2. 写入时区名称的字符数据
    ofs.write(zone_name.data(), name_len);
    
    // 3. 写入时间点的秒数(转换为int64_t保证跨平台兼容性)
    const auto tp = time.get_sys_time();
    const std::int64_t seconds = std::chrono::duration_cast<std::chrono::seconds>(tp.time_since_epoch()).count();
    ofs.write(reinterpret_cast<const char*>(&seconds), sizeof(seconds));
    
    return ofs;
}

// 反序列化zoned_seconds
std::ifstream& operator>>(std::ifstream& ifs, std::chrono::zoned_seconds& time)
{
    // 1. 读取时区名称长度
    std::size_t name_len;
    ifs.read(reinterpret_cast<char*>(&name_len), sizeof(name_len));
    if (!ifs) throw std::runtime_error("Failed to read zone name length");
    
    // 2. 读取时区名称字符串
    std::string zone_name(name_len, '\0');
    ifs.read(zone_name.data(), name_len);
    if (!ifs) throw std::runtime_error("Failed to read zone name");
    
    // 3. 通过名称获取对应的time_zone对象
    auto* zone = std::chrono::locate_zone(zone_name);
    if (!zone) throw std::runtime_error("Invalid time zone name: " + zone_name);
    
    // 4. 读取秒数并重建time_point
    std::int64_t seconds;
    ifs.read(reinterpret_cast<char*>(&seconds), sizeof(seconds));
    if (!ifs) throw std::runtime_error("Failed to read seconds");
    
    std::chrono::sys_seconds tp{std::chrono::seconds{seconds}};
    
    // 5. 赋值给目标zoned_seconds对象
    time = std::chrono::zoned_seconds{zone, tp};
    
    return ifs;
}

关键细节说明

  • 时区名称处理:先写入字符串长度再写入内容,避免读取时因无结束符导致的字符串截断问题,兼容包含特殊字符的时区名称。
  • 时间点存储:将系统时间点转换为秒数用std::int64_t存储,能覆盖chrono库支持的时间范围,且跨平台兼容性更强。
  • 错误处理:加入基础异常抛出,方便调试时定位序列化/反序列化环节的问题。
  • 环境依赖:需确保程序运行环境的时区数据库可用(如Linux的/usr/share/zoneinfo、Windows系统时区数据),locate_zone才能正确找到对应时区。

内容的提问来源于stack exchange,提问作者digito_evo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 05:55:00