TimeZoneInfo.ConvertTime在DateTime.MinValue上非常慢

时间:2018-01-04 15:14:54

标签: c# .net timezone

我刚注意到我们的一个单元测试花了十秒钟。在玩完它之后,我创建了一个最小的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();
    }

看起来(test?)代码在每次使用DateTime.MinValue调用时清除缓存。

提出为什么会发生这种情况的问题。

1 个答案:

答案 0 :(得分:3)

没有必要反编译。您可以在the .NET Framework Reference Sourcethe CoreCLR source code on GitHub中找到此内容。

.NET 4.6中添加了一个特殊情况作为非官方的解决方法,用于清除当时没有公开ClearCachedData方法的WinRT等环境中的时区缓存。 I describe this further here

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

是的,我同意这应该记录得更好。我会看看能不能搞定。

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