Vb.net .NET奇怪的行为与日期时间和UTC到本地时间的转换
我正在修改旧的应用程序,发现了一个大错误。我在西班牙,这个应用程序正在读取一些文件,其中包含UTC字符串格式的日期,需要转换 由于格式:Vb.net .NET奇怪的行为与日期时间和UTC到本地时间的转换,vb.net,datetime,visual-studio-2005,.net-2.0,Vb.net,Datetime,Visual Studio 2005,.net 2.0,我正在修改旧的应用程序,发现了一个大错误。我在西班牙,这个应用程序正在读取一些文件,其中包含UTC字符串格式的日期,需要转换 由于格式: “yyyy-MM-yyTHH:mmZ” 但是这里的代码使用.ToLocalTime,再次将日期转换为本地值,可能使时间再次更改为不正确的值 现在出现了一个奇怪的事实,var采用了正确的值,但代码没有返回该值。在VisualStudio的“检查”部分,您可以看到结果应该是0,而不是22(第二天的0小时) 这里发生了什么 编辑: 应用程序正在读取一个XML文件,
“yyyy-MM-yyTHH:mmZ”
但是这里的代码使用.ToLocalTime
,再次将日期转换为本地值,可能使时间再次更改为不正确的值
现在出现了一个奇怪的事实,var采用了正确的值,但代码没有返回该值。在VisualStudio的“检查”部分,您可以看到结果应该是0,而不是22(第二天的0小时)
这里发生了什么
编辑:
应用程序正在读取一个XML文件,此时正在读取以下内容:
<IntervaloTiempo v="2013-10-26T19:33Z/2013-10-26T22:00Z"/>
我用这个更正了代码,应用程序也以同样的方式工作:
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
正如您在“检查”窗口中看到的,这就是行为。问题是,variHoraIn
的最终值是22
,这是正确的,但代码不是
实际上,将代码更改为仅删除ToLocalTime()
部分会使最终值相同
有人能解释为什么会发生这种情况,以及是如何发生的吗?这是一个bug吗?这里发生的是
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
小时
这就是你所期望的吗?DateTime.Kind 在.Net framework的2.0版中,Microsoft引入了。不同的种类如下:
Local
Unspecified
Utc
每个Date
(基础CLR类型为DateTime
)对象都具有Kind
属性,该属性指定该对象的日期类型。也就是说,它指定日期值是本地、UTC还是未知
如果Date
对象具有Kind=Local
,则调用ToLocalTime
函数时不执行转换。从这个角度来看,我的重点是:
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
时发生的情况,以及显式设置种类时发生的情况。前两个代码块是等效的-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
因此,您看到的不是bug,而是预期的行为。您试图转换您认为的UTC日期;然而,实际上这是一个当地的约会
我相信您希望看到的是上面第三个代码块中发生的事情。它创建一个UTC日期并将其转换为本地时间。最好也添加代码,让我们来计算它。顺便说一句,截图很好。这是一个@jon skeet问题,因为他是约会时间专家!从你的结果(如答案中所解释的)中可以清楚地看出22的原因:9:33(21:33)+1=22。在任何情况下,您都不应该依赖CDate,而应该依赖其他方法(最好是较新的.NET方法)来解释确切的日期格式(通过CultureInfo,或者在本例中,通过目标字符串格式)。执行/编译器的差异是什么意思?我正在执行您的代码(我在西班牙),我在任何地方都会得到预期的结果,即22小时。@SysDragon,您能以答案形式向您提供解决方案并接受您自己的答案吗?正确的结果是22
,但代码在执行过程中和compiler@SysDragon,在您看到0的手表中,在0的最右侧是否有一个小图标“刷新”?点击它这正是我想知道的。我知道有一个解释。回答得很好,谢谢。
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