我们遇到一个问题,一位开发人员创建了以下代码,并且该代码可以在他的 DEV 环境中运行。但是当它被签入 QA 时,代码会中断并显示以下错误消息:
myRecord.UTCStartTime = TimeZoneInfo.ConvertTimeToUtc(myRecord.StartTime, myTimeZone);
由于提供的 DateTime 无法完成转换
没有正确设置 Kind 属性。例如,当
Kind属性是DateTimeKind.Local,源时区必须是
时区信息.Local。
在我的 DEV 环境中,上述代码会生成与 QA 服务器相同的错误。我应用了以下更改来解决该问题:
DateTime utcStart = DateTime.SpecifyKind(myRecord.StartTime, DateTimeKind.Unspecified);
myRecord.UTCStartTime = TimeZoneInfo.ConvertTimeToUtc(utcStart, myTimeZone);
为什么第一个代码示例可以在 DEV1 环境中运行,但在我的 DEV 环境和 QA 服务器上却无法运行?
这取决于如何myRecord.StartTime
被起源。
- 如果你从
DateTime.Now
,那么它将有一个Local
kind.
- 如果你从
DateTime.UtcNow
那么它会有一个Utc
kind.
- 如果你从
new DateTime(2013,5,1)
那么它会有一个Unspecified
kind.
这也取决于你在哪里得到的myTimeZone
从。例如:
TimeZoneInfo.Local
TimeZoneInfo.Utc
TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")
The TimeZoneInfo.ConvertTimeToUtc
仅当该功能可以将区域与您指定的类型相匹配时,该功能才会运行。如果两者都是本地的,或者都是 UTC,那么它就可以工作。如果你给它一个特定的区域,那么类型应该是未指定的。这种行为是记录在 MSDN 上 http://msdn.microsoft.com/en-us/library/vstudio/bb495915.aspx.
您可以轻松一致地重现异常:
var tz = TimeZoneInfo.FindSystemTimeZoneById("Fiji Standard Time");
var utc = TimeZoneInfo.ConvertTimeToUtc(DateTime.Now, tz);
假设您不住在斐济,每次都会出错。你基本上是说,“将我在其他区域的本地时间转换为 utc” - 这是没有意义的。
它可能适用于您的开发环境,因为您正在测试的值myTimeZone
恰好是开发商的本地区域。
关于你的改变 - 当然你可以强制不指定类型,这会改变你正在做的事情的含义,使其有意义。但你确定这就是你想要的吗?是什么.Kind
手头的日期?如果还没有Unspecified
,那么它就带有某种意图。您可能应该返回到此数据的来源并确保它是您所期望的。
如果这一切听起来疯狂、疯狂、令人沮丧和怪异,那是因为DateTime
物体发臭。这里有一些补充阅读:
- DateTime 有什么问题吗? http://noda-time.blogspot.com/2011/08/what-wrong-with-datetime-anyway.html
- 针对 DateTime.Now 的案例 http://codeofmatt.com/2013/04/25/the-case-against-datetime-now/
您可能会考虑使用NodaTime http://nodatime.org反而。它的 API 将防止您犯这些类型的常见错误。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)