2

我正在修改旧应用程序,但发现了一个大错误。我在西班牙,这个应用程序正在这里读取一些文件,其中包含 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

编辑2:

由于看起来我的帖子很难理解,如评论中所见,我将尝试澄清一些事情。

我正在使用带有 .NET Framework 2.0 的 Visual Studio 2005。

中的值dtUTC被转换为本地时间,正如您在屏幕截图中看到的那样,它的值是,21:33它应该返回22AddHour(1).Hour

使用dtUTC.ToLocalTime()时应将其小时转换为值,23:33该值应返回0.AddHour(1).Hour

正如您在“检查”窗口中看到的那样,这就是行为。问题是, var 的最终值为iHoraIn22这是正确的,但代码不是。

实际上,将代码更改为仅删除ToLocalTime()部分会使最终值相同。

有人可以解释为什么以及如何发生这种情况吗?这是一个错误吗?

4

2 回答 2

1

日期时间类型

在 .Net 框架的 2.0 版中,Microsoft 引入了DateTime.Kind 属性。不同的种类如下:

Local
Unspecified
Utc

每个Date(底层 CLR 类型是DateTime)对象都具有Kind属性,该属性指定该对象的日期类型。也就是说,它指定日期值是本地、UTC 还是未知的。

如果Date对象具有,则在调用该函数Kind = Local时不执行任何转换。ToLocalTimeDateTime.ToLocalTime 方法,重点是我的:

种类结果(ToLocalTime)
------------ --------------------------------------- --
Utc 此 DateTime 实例被转换为本地时间。
本地 不执行转换。
未指定 DateTime 的此实例假定为 UTC 时间,
            并且转换的执行就像 Kind 是 UTC 一样。

这如何适用于您的情况?

当你使用CDate时,结果KindLocal。这意味着当您调用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 日期并将其转换为本地时间。

于 2013-11-22T04:00:58.440 回答
-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:33Z2013-10-26 15:33我的时区,dtUTC这次显示

我要增加 1 小时,所以iHoraIn现在是 16


在您的屏幕截图中,手表显示dtUTC为小时9:33 PM21

你加 1 小时,现在是22小时

这是你所期望的吗?

于 2013-11-14T12:02:24.513 回答