我们遇到了一个问题,一个开发人员创建了以下代码,并且它可以在他的DEV环境中运行。但是当它被检入QA时,代码会出现以下错误消息:
myRecord.UTCStartTime = TimeZoneInfo.ConvertTimeToUtc(myRecord.StartTime, myTimeZone);
由于提供的DateTime无法完成转换 没有正确设置Kind属性。例如,当 Kind属性是DateTimeKind.Local,源时区必须是 TimeZoneInfo.Local。
在我的DEV环境中,上面的代码生成与QA服务器相同的错误。我应用以下更改来解决问题:
DateTime utcStart = DateTime.SpecifyKind(myRecord.StartTime, DateTimeKind.Unspecified);
myRecord.UTCStartTime = TimeZoneInfo.ConvertTimeToUtc(utcStart, myTimeZone);
为什么第一个代码示例适用于DEV1的环境但在我的DEV环境和QA服务器上中断?
答案 0 :(得分:46)
这取决于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
对象很臭。这是一些额外的阅读:
您可以考虑使用NodaTime代替。它的API将阻止您犯这些类型的常见错误。
答案 1 :(得分:1)
只有在使用DateTime.Now时才会出现这种情况。我更新了我的代码,如下所示,它再次运行:)
DateTime currentTime = new DateTime(DateTime.Now.Ticks,DateTimeKind.Unspecified);
答案 2 :(得分:0)
基本上是以前的答案中所说的,但要精简:
DateTime.Now
或 DateTime.Today
将 Kind 设置为 Local
,因此将其更改为 Unspecified
在处理日期的方法中:
// Incoming date has DateTimeKind.Local
var localDateTime = DateTime.Now;
// Set to unspecified
var unspecifiedDateTime = DateTime.SpecifyKind(localDateTime, DateTimeKind.Unspecified);
我只是在部署时收到这个,然后意识到一个库正在将 DateTime.Now
而不是 new DateTime(...)
传递给一个方法。
答案 3 :(得分:-2)
在C#中
public static DateTime IndianDateTime(DateTime currentTime)
{
DateTime cstTime = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(currentTime, TimeZoneInfo.Local.Id, "India Standard Time");
return cstTime;
}
在VB中
Public Shared Function IndianDateTime(ByVal currentTime As DateTime) As DateTime
Dim cstTime As DateTime = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(currentTime, TimeZoneInfo.Local.Id, "India Standard Time")
Return cstTime
End Function