windows 上的 kestrel 和 macOs/linux 上的 kestrel 之间的日期反序列化差异

Date deserialization difference between kestrel on windows and kestrel on macOs/linux

我曾尝试搜索有关 net.core 文档(问题等)的信息,但没有结果。 代码更简单:

    [HttpGet()]
    [Route("dob")]
    public string dobTest()
    {
        var content = @"""1942-01-01T22:00:00.000Z""";
        var settings = new JsonSerializerSettings()
        {
            //DateFormatHandling = DateFormatHandling.IsoDateFormat,
            //DateParseHandling = DateParseHandling.DateTimeOffset,
            DateTimeZoneHandling = DateTimeZoneHandling.Local,
            //DateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind
        };
        var dob = JsonConvert.DeserializeObject<DateTime>(content, settings);

        return $"dob: {dob.ToString("yyyy-MM-dd HH:mm:ss.fff")} - {dob.Kind}";
    }

如果我 运行 此代码在 Mac 或 Linux 上,结果是:

dob: 1942-01-02 00:00:00.000 - Local

如果我 运行 这个代码在 windows 上,结果是:

dob: 1942-01-01 23:00:00.000 - Local

我的 MacOs 时区设置在罗马 (UTC +01:00) Windows 时区设置在罗马 (UTC +01:00)

Newtonsoft.Json的版本是12.0.3 net framework的版本是net core 3.1

Linux 和 OSX 都使用 IANA time zone database for its primary source of time zone information, which has correct historical data for time zones in 1942 in Rome, under the identifier Europe/Rome. You can see that UTC+2 is the correct offset for the date given here

另一方面,

Windows 没有该时区的历史记录。等效的 Windows 标识符是 W. Europe Standard Time,它的英文显示名称是 (UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna。您可以在注册表中的以下键下看到 Windows 的数据:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\W. Europe Standard Time

如果您使用 RegEdit 检查此键,您会注意到与其他几个时区不同,此时区没有 Dynamic DST 子键。这意味着 Windows 不知道 DST 规则中的任何历史差异,因此每年都在同一组规则下进行处理。

Windows 确实有 某些 区域的历史数据,但一般来说,Microsoft 仅根据其 DST/TZ support policy.[=18= 保证自 2010 年以来的历史准确性]

因此,如果您的应用程序需要历史时区准确性,那么您应该只使用 IANA 时区。在 .NET 中,您可以使用 Noda Time 库中的 TZDB 提供程序来执行此操作。