序列化日期时间

Serializing a datetime

本文关键字:时间 日期 序列化      更新时间:2023-10-16
执行

日期/时间对的二进制序列化的最佳方法是什么?

到目前为止,我最好的猜测是存储自 epoch 以来的秒数,由 POSIX time(( 和 mktime(( 函数返回,然后在检索时使用 localtime(( 将其转换回"人类可读"结构。

请注意,时间戳将由不同时区的计算机存储和检索。

这取决于您到底对哪些数据感兴趣:

  • 您需要亚秒级精度吗? 显然,POSIX time_t通常不提供这一点,除非您使用某种浮点类型(这可能会引入自己的问题(。 其他语言和库的时间格式(如JavaScript和Java(使用毫秒自固定日期而不是自固定纪元以来的秒来解决这个问题。
  • 如果时间戳将跨时区存储和检索,那么使用定义为相对于纪元的格式(如 POSIX time_t 或 JavaScript 数据(可能比存储本地时间 + 时区更好。
  • 如果您需要知道原始时区,那么您也需要存储它。
  • 由于 2038 年的问题,如果您使用 POSIX time_t 之类的东西,您需要将其存储为 64 位数字,而不是 32 位数字。 (即使将其存储为 64 位数字,请记住,C 运行时的mktimelocaltime实现可能不支持 64 位time_t值。

特别是关于 2038 年的问题:我不知道有任何 POSIX API 可以保证处理它。 如果你想要一个保证处理它的库,你最好使用类似的东西 boost::date_time . Project 2038 常见问题解答包含有关测试 C 运行时以获取 2038 支持的信息。 根据该页面,现代64位Linux系统不应受到影响。 Visual C++的最新版本也不受影响。 (看这里。 即使您的库当前不支持 64 位 time_t 值,您也可以序列化 64 位 int 并将其转换为 32 位来处理它;这样,您的磁盘数据结构至少是合规的,并且您的库有望在 2038 年成为问题之前更新。

请注意,时间戳将由不同时区的计算机存储和检索。

您是否也需要存储该时区?您是否对存储它的本地日期和时间感兴趣,或者只是对即时时间感兴趣?

基本上,找出哪些信息对你很重要,并确保你存储这些信息。

你已经回答了自己。 根据当地人的情况(即夏令时间、时区、24 小时等(按需转换为人类可读格式的计算机可理解的时间值是最好的。它的存储也很小。

这取决于您希望如何与二进制类型交互。如果始终使用 POSIX 函数,那么可以肯定的是,time_t值就可以了。在Windows上,您需要将其转换为其格式才能获得日期。始终将二进制值保存为 UTC,当然,不要对此原始值应用任何偏移量。

另一种方法(不是最快的(是存储字符串,而不是绑定到任何一个函数库。当然,如果您确定使用 POSIX 调用创建了二进制值 1345739726,那么如果您将该值移动到 Windows 系统,则可以进行转换。字符串格式只是消除了有关表示什么时间点的任何问题。字符串 sTime = "年:月:月日:工作日:小时:分钟:秒:日光:GMTOffset">