TimeZoneInfo.ConvertTime在DateTime.MinValue上非常慢



我刚刚注意到我们的一个单元测试占用了十秒钟。在尝试了它之后,我创建了一个最小的 linqpad 示例来重现它:

void Main()
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    var timeZone = TimeZoneInfo.Local;
    for(int i=0; i<10000; i++)
    {
      //var dateTime = TimeZoneInfo.ConvertTime(DateTime.UtcNow, timeZone);   
      var dateTime = TimeZoneInfo.ConvertTime(DateTime.MinValue, timeZone);   
    }
    sw.Stop();
    (sw.ElapsedMilliseconds + " ms").Dump();
}

在我的电脑或我们的内部电脑上,这需要 40 秒。如果我使用DateTime.UtcNow,则需要15毫秒。

有什么原因或解决方法吗?


编辑:正如评论中所建议的,我反编译了TimeZoneInfo,并且在DateTime.MinValue上有一个特殊情况:

static public DateTime ConvertTime(DateTime dateTime, TimeZoneInfo destinationTimeZone) {
    // Special case to give a way clearing the cache without exposing ClearCachedData()
    if (dateTime.Ticks == 0) {
        ClearCachedData();
    }

看起来像(测试?(代码,每次使用 DateTime.MinValue 调用缓存时都会清除缓存。

留下了为什么会发生这种情况的问题。

没有必要反编译。 您可以在 .NET Framework 参考源代码或 GitHub 上的 CoreCLR 源代码中找到此信息。

此特殊情况是在 .NET 4.6 中添加的,作为清除当时未公开 ClearCachedData 方法的环境(如 WinRT(中的时区缓存的非官方解决方法。 我在这里进一步描述这一点。

偶尔清除时区缓存通常不会产生明显效果。 你看到它是因为紧密的循环。 如果这是您的用例的问题,那么我建议使用 ConvertTimeFromUtc 方法或与 DateTimeOffset 一起使用的ConvertTime版本。 这些代码路径不会遇到特殊情况。

是的,我同意这应该更好地记录下来。 我看看我能不能把它弄进去。

请注意,从逻辑上讲,将时区转换为DateTime.MinValue没有多大意义,因为我们今天所知道的时区在第 1 年不存在。

相关内容

  • 没有找到相关文章