我们遇到一个问题,一个开发人员创建以下代码,并且该代码可以在他的DEV环境中工作。但是,当将其检入质量检查时,代码会中断并显示以下错误消息:

myRecord.UTCStartTime = TimeZoneInfo.ConvertTimeToUtc(myRecord.StartTime, myTimeZone);



在我的DEV环境中,以上代码生成的错误与质量检查服务器相同。我应用了以下更改来解决此问题:
DateTime utcStart = DateTime.SpecifyKind(myRecord.StartTime, DateTimeKind.Unspecified);
myRecord.UTCStartTime = TimeZoneInfo.ConvertTimeToUtc(utcStart, myTimeZone);

为什么第一个代码示例可在DEV1的环境上工作,但在DEV环境和QA服务器上却无法正常工作?

最佳答案

这取决于myRecord.StartTime的来源。

  • 如果您是从DateTime.Now获得的,则它将具有Local类型。
  • 如果您是从DateTime.UtcNow获得的,则它将具有Utc类型。
  • 如果您是从new DateTime(2013,5,1)获得的,则它将具有Unspecified类型。

  • 这也取决于您从哪里获得myTimeZone。例如:
  • TimeZoneInfo.Local
  • TimeZoneInfo.Utc
  • TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")

  • 如果TimeZoneInfo.ConvertTimeToUtc函数可以将区域与您指定的区域匹配,则该函数才起作用。如果两者都是本地的,或者两者都是UTC,那么它将起作用。如果要为其指定特定区域,则类型应为未指定。此行为是documented on MSDN

    您可以轻松一致地重现异常:
    var tz = TimeZoneInfo.FindSystemTimeZoneById("Fiji Standard Time");
    var utc = TimeZoneInfo.ConvertTimeToUtc(DateTime.Now, tz);
    

    假设您不住在斐济,这每次都会出错。您基本上说过:“将我在其他区域的本地时间转换为utc”-这没有任何意义。

    它可能在您的开发环境中有效,因为您正在测试myTimeZone的值恰好是开发人员的本地区域。

    关于您的更改-确保您可以强制指定未指定的种类,并且这样可以改变您所做工作的含义,以使其有意义。但是您确定这就是您想要的吗?提前日期的.Kind是什么?如果还不是Unspecified,那么它带有某种意图。您可能应该回到这些数据的来源,并确保它是您所期望的。

    如果所有这些听起来都疯狂,疯狂,令人沮丧和奇怪,那是因为DateTime对象发臭了。这里是一些其他阅读:
  • What's wrong with DateTime anyway?
  • The case against DateTime.Now

  • 您可以考虑改为使用NodaTime。其API可以防止您犯此类常见错误。

    关于c# - TimeZoneInfo.ConvertTimeToUtc问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/16322896/

    10-11 06:43