【发布时间】:2021-06-22 18:27:42
【问题描述】:
我正在尝试在 C# 中实现 MsgPack TimeStamp 64 type。规范是这样说的:
timestamp 64 存储自 1970-01-01 00:00:00 UTC 以来经过的秒数和纳秒数 在 32 位无符号整数中: +--------+--------+--------+--------+--------+---- --|-+--------+--------+--------+--------+ | 0xd7 | -1 |纳秒。 30 位无符号整数 | 34 位无符号整数秒数 | +--------+--------+--------+--------+--------+---- --^-+--------+--------+--------+--------+ * Timestamp 64 格式可以表示 [1970-01-01 00:00:00.000000000 UTC, 2514-05-30 01:53:04.000000000 UTC) 范围内的时间戳。 * 在时间戳 64 和时间戳 96 格式中,纳秒不得大于 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")));
输出是:
时间戳 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,但是我盯着它看太久了……
附:请注意,这还不是 MsgPack 实现,我首先需要得到这个,然后才能开始使用单元测试验证我的真实代码。如果基础已经被破坏,那么带有这些移位位的小端和大端之间的转换只会增加更多的混乱......
【问题讨论】:
-
仅供参考,1970 年 1 月 1 日 00:00:00 UTC 可以写为
DateTime.UnixEpoch(在 .NET Core,.NET 5.0+ 中)
标签: c# datetime timestamp msgpack