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

求CArchive序列化MFC C++中CTime的格式说明及字节解析

解析CArchive序列化的CTime并转换为QDateTime

1. CTime的CArchive序列化格式拆解

MFC官方文档TN002并未明确说明CTime的具体序列化格式,但我们可以通过MFC源码推导得出。针对你提供的8字节数据:
0x0a 0x00 0x00 0x80 0x1b 0x0a 0x96 0x5d

逐段解析含义:

  • 第0-1字节(0x0a 0x00):小端存储的WORD类型版本号,CTime序列化的固定版本为10(0x0a)。
  • 第2-3字节(0x00 0x80):小端存储的WORD类型标记位,其中0x8000位表示当前CTime对象有效(非空/未初始化状态)。如果该位未置1,则代表这是一个无效的CTime。
  • 第4-7字节(0x1b 0x0a 0x96 0x5d):小端存储的__time32_t(32位整数)时间戳,代表从1970年1月1日UTC到目标时间的秒数。将字节逆序转换为十六进制值0x5d960a1b,对应十进制1569964571,即UTC时间2019-10-01 12:36:11。

注:较新的MFC版本中,针对2038年之后的时间,可能会使用64位的__time64_t进行序列化,对应总长度为12字节(2字节版本号+2字节标记位+8字节时间戳),你的样本数据属于32位时间戳的版本。

2. 使用QDataStream转换为QDateTime

以下是读取序列化字节并转换为QDateTime的具体步骤:

步骤1:读取原始字节

必须将QDataStream设置为小端字节序,以匹配MFC的存储方式:

QByteArray rawData = ...; // 你的8字节CArchive序列化数据
QDataStream in(&rawData, QIODevice::ReadOnly);
in.setByteOrder(QDataStream::LittleEndian);

WORD version;
WORD validityFlag;
quint32 epochSeconds;

in >> version >> validityFlag >> epochSeconds;

步骤2:校验与转换

  • 校验版本号:确保version == 10,确认是合法的CTime序列化数据。
  • 校验有效性:通过validityFlag & 0x8000判断CTime是否有效。
  • 转换为QDateTime:时间戳基于UTC,可根据需求转换为本地时区:
QDateTime result;
if (validityFlag & 0x8000) {
    result = QDateTime::fromSecsSinceEpoch(epochSeconds, Qt::UTC);
    // 如需转换为本地时区,取消下方注释:
    // result = result.toLocalTime();
} else {
    result = QDateTime(); // 代表无效/未初始化的CTime
}

3. 关键注意事项

  • CArchive始终使用小端字节序存储数据,因此必须设置QDataStream为LittleEndian,否则解析会出错。
  • 32位__time32_t时间戳的有效范围是1970-01-01至2038-01-19,若遇到12字节的序列化数据,则是使用64位__time64_t存储的跨2038年时间。
  • 由于官方文档未提及该细节,上述格式是通过分析MFC的CTime::Serialize()实现代码得出的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 17:00:02