将 MsgPack 时间戳 64 字段转换为 DateTime 的错误结果

Wrong result converting MsgPack timestamp 64 fields to DateTime

我正在尝试在 C# 中实现 MsgPack TimeStamp 64 type。规范是这样说的:

timestamp 64 stores the number of seconds and nanoseconds that have elapsed since 1970-01-01 00:00:00 UTC
in 32-bit unsigned integers:
+--------+--------+--------+--------+--------+------|-+--------+--------+--------+--------+
|  0xd7  |   -1   | nanosec. in 30-bit unsigned int |   seconds in 34-bit unsigned int    |
+--------+--------+--------+--------+--------+------^-+--------+--------+--------+--------+

* Timestamp 64 format can represent a timestamp in [1970-01-01 00:00:00.000000000 UTC, 2514-05-30 01:53:04.000000000 UTC) range.
* In timestamp 64 and timestamp 96 formats, nanoseconds must not be larger than 999999999.

请注意,秒字段是三十 位,而不是三十二位。因此,可以通过将 32 位最大值 unsigned int 左移两位并设置现在已清除的两个最低有效位来计算最大值。

我尝试使用以下 C# 代码验证这一点,但得到了不同的结果:

DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); // the zero starting point
long maxSecs = ((long)uint.MaxValue << 2) | 3; // 17179869183
long maxNanoSec = 999999999; // not uint.MaxValue
TimeSpan maxNanoSecSpan = new TimeSpan(maxNanoSec * 100); // 1 tick = 100 nanosec.
DateTime MaxFExt8 = epoch.AddSeconds(maxSecs).Add(maxNanoSecSpan); 
Console.WriteLine(string.Concat("Timestamp 64 : ", epoch.ToString("yyyy-MM-dd HH:mm:ss.fffffff"), " - ", MaxFExt8.ToString("yyyy-MM-dd HH:mm:ss.fffffff")));

输出为:

Timestamp 64 : 1970-01-01 00:00:00.0000000 - 2514-05-30 04:39:42.9999900

2 小时 46 分 39 秒太多了...

opening an issue关于差异之后,其他人检查并发现他们得到了与规格相同的结果。一个使用 MacOS 内置的 NSDate 类型,另一个使用 ruby.

我想我的6行代码肯定有bug,但我盯着它看太久了...

P.S。请注意,这还不是 MsgPack 实现,在我开始使用单元测试验证我的真实代码之前,我首先需要正确设置它。如果基础已经被破坏,那么使用这些移位位在小端和大端之间的转换只会增加更多的混乱....

当您应该除以纳秒时,您乘以纳秒:TimeSpan maxNanoSecSpan = new TimeSpan(maxNanoSec * 100);