2

古いアプリを修正していて、大きなバグを発見しました。私はスペインにいて、このアプリは UTC 文字列形式の日付を含むいくつかのファイルを読み込んでおり、変換する必要があります。

文字列値はCDate、次の形式により、すでに現地時間に変換されています。
"yyyy-MM-yyTHH:mmZ"

しかし、ここのコードは を使用して日付をローカル値に再度変換し.ToLocalTime、おそらく時刻を誤った値に再度変更します。

var が正しい値を取得しているのに、コードがそれを返していないという奇妙な事実が発生します。Visual Studio の「Inspection」セクションで、結果が 22 (翌日の 0 時) ではなく 0 であることを確認できます。

Visual Studio エラー

ここで何が起きてるの?

編集:

アプリは 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、 で返さ22AddHour(1).Hourます。

時間を使用する場合は、値にdtUTC.ToLocalTime()変換する必要があります。23:33値は で返さ0AddHour(1).Hourます。

「検査」ウィンドウでわかるように、それが動作です。iHoraIn問題は、var の最終値22が正しいことですが、コードが正しくないことです。

実際には、コードを変更してその部分を削除するだけでToLocalTime()、最終的な値は同じになります。

誰かがなぜ、どのようにこれが起こっているのか説明できますか? これはバグですか?

4

2 に答える 2

1

DateTime.Kind

In Version 2.0 of the .Net framework, Microsoft introduced the DateTime.Kind property. The different kinds are as follows:

Local
Unspecified
Utc

Every Date (the underlying CLR type is DateTime) object has the Kind property, which specifies what kind of date that object is. That is, it specifies whether the date value is local, UTC, or unknown.

If a Date object has Kind = Local, then no conversion is performed when the ToLocalTime function is called. From the DateTime.ToLocalTime method, emphasis is mine:

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.

How does this apply to your situation?

When you use CDate, the resulting Kind is Local. This means that when you call ToLocal on it, no conversion takes place:

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()

A more complete example

This example shows what happens when you use CDate, and what happens when the Kind is explicitly set. The first two code blocks are equivalent - CDate creates a Local date. The third block shows what happens when you specify a UTC date.

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

The above produces this output:

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

So what you are seeing is not a bug - it is expected behavior. You are trying to convert what you think is a UTC Date; however in reality it is really a local date.

I believe what you are expecting to see is what happens in the third code block above. It creates a UTC date and converts it to local time.

于 2013-11-22T04:00:58.440 に答える