我正在修改和旧的应用程序,我发现了一个大错误。我在西班牙,这个应用程序正在读取一些包含UTC字符串格式的日期的文件,需要进行转换。
由于以下格式,字符串值已转换为CDate
的本地时间:
"yyyy-MM-yyTHH:mmZ"
但是这里的代码再次将日期转换为.ToLocalTime
的本地值,可能会使时间再次变为不正确的值。
现在出现了一个奇怪的事实,即var取正确的值,但代码没有返回。在Visual Studio的“检查”部分中,您可以看到结果应为0,而不是22(第二天的0小时)。
这里发生了什么?
修改
该应用正在读取XML文件,此时正在阅读:
<IntervaloTiempo v="2013-10-26T19:33Z/2013-10-26T22:00Z"/>
代码是屏幕截图中显示的代码:
Valor = Split(.Value, "/")
dtUTC = CDate(Valor(0))
iHoraIn = Hour(dtUTC.ToLocalTime().AddHours(1))
我用这个更正了代码,应用程序的工作方式相同:
iHoraIn = dtUTC.AddHours(1).Hour
EDIT2:
由于看起来我的帖子很难理解,如评论所示,我会尝试澄清一些事情。
我正在使用Visual Studio 2005和.NET Framework 2.0。
dtUTC
中的值会转换为本地时间,其值(如屏幕截图所示)为21:33
,应该22
返回AddHour(1).Hour
。
使用dtUTC.ToLocalTime()
时,其小时应转换为23:33
值,该值应0
返回AddHour(1).Hour
。
正如您在“检查”窗口中看到的那样,这就是行为。问题是,var iHoraIn
的最终值是22
,这是正确的,但代码不是。
实际上,将代码更改为仅删除ToLocalTime()
部分会使最终值相同。
有人可以解释为什么以及如何发生这种情况?这是一个错误吗?
答案 0 :(得分:1)
<强> DateTime.Kind 强>
在.Net框架的2.0版本中,Microsoft引入了DateTime.Kind property。不同种类如下:
Local
Unspecified
Utc
每个Date
(基础CLR类型为DateTime
)对象都具有Kind
属性,该属性指定该对象的日期类型。也就是说,它指定日期值是本地值,UTC还是未知。
如果Date
对象具有Kind = Local
,则在调用ToLocalTime
函数时不会执行转换。从DateTime.ToLocalTime method开始,重点是我的:
Kind Results (of ToLocalTime) ----------- ----------------------------------------- Utc This instance of DateTime is converted to local time. Local No conversion is performed. Unspecified This instance of DateTime is assumed to be a UTC time, and the conversion is performed as if Kind were UTC.
这对您的情况有何影响?
使用CDate
时,生成的Kind
为Local
。这意味着当您在其上调用ToLocal
时,不会进行转换:
Dim valor = "2013-10-26T19:33Z"
Dim dtUTC = CDate(valor)
' dtUTC.Kind is Local
' The following does not do any conversion
Dim dtLocal = dtUTC.ToLocal()
更完整的示例
此示例显示使用CDate
时会发生什么,以及明确设置Kind
时会发生什么。前两个代码块是等效的 - CDate
创建Local
日期。第三个块显示指定UTC日期时会发生什么。
Sub Main()
Dim valor = "2013-10-26T19:33Z"
Dim dtUTC = CDate(valor)
Dim dtLocal = dtUTC.ToLocalTime()
Dim iHoraIn = Hour(dtLocal.AddHours(1))
Dim kind = dtUTC.Kind
printDate(dtUTC, dtLocal, iHoraIn, kind)
Dim dtUTC2 = DateTime.SpecifyKind(dtUTC, DateTimeKind.Local)
Dim dtLocal2 = dtUTC2.ToLocalTime()
Dim iHoraIn2 = Hour(dtLocal2.AddHours(1))
Dim kind2 = dtUTC2.Kind
printDate(dtUTC2, dtLocal2, iHoraIn2, kind2)
Dim dtUTC3 = DateTime.SpecifyKind(dtUTC, DateTimeKind.Utc)
Dim dtLocal3 = dtUTC3.ToLocalTime()
Dim iHoraIn3 = Hour(dtLocal3.AddHours(1))
Dim kind3 = dtUTC3.Kind
printDate(dtUTC3, dtLocal3, iHoraIn3, kind3)
End Sub
Sub printDate(ByVal dtUtc, ByVal dtLocal, ByVal hora, ByVal utcKind)
System.Console.WriteLine("UTC: {0}, UTC KIND: {1}, LOCAL: {2}, HORA: {3}", dtUtc, utcKind, dtLocal, hora)
End Sub
以上产生了这个输出:
UTC: 2013-10-26 09:33:00 PM, UTC KIND: Local, LOCAL: 2013-10-26 09:33:00 PM, HORA: 22
UTC: 2013-10-26 09:33:00 PM, UTC KIND: Local, LOCAL: 2013-10-26 09:33:00 PM, HORA: 22
UTC: 2013-10-26 09:33:00 PM, UTC KIND: Utc, LOCAL: 2013-10-26 11:33:00 PM, HORA: 0
所以你所看到的不是一个错误 - 它是预期的行为。您正在尝试转换您认为的UTC日期;但实际上它实际上是一个当地的约会。
我相信你期望看到的是上面第三个代码块中发生的事情。它会创建一个UTC日期并将其转换为当地时间。
答案 1 :(得分:-1)
这里发生的是
Sub Main()
Dim valor = "2013-10-26T19:33Z"
'this convert to local time
Dim dtUTC = CDate(valor)
'this add one hour to local time in 24 hour format
'equal to dtUTC.AddHours(1).Hour
Dim iHoraIn = dtUTC.ToLocalTime.AddHours(1).Hour
End Sub
2013-10-26T19:33Z
在我的时区2013-10-26 15:33
,dtUTC
显示此时间
我要加1小时,所以iHoraIn
现在是16
dtUTC
显示为9:33 PM
21
小时
你加1小时,现在是22
小时
这是你期望的吗?