Vb.net .NET奇怪的行为与日期时间和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文件,

我正在修改旧的应用程序,发现了一个大错误。我在西班牙,这个应用程序正在读取一些文件,其中包含UTC字符串格式的日期,需要转换

由于格式:
“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

正如您在“检查”窗口中看到的,这就是行为。问题是,var
iHoraIn
的最终值是
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