it-swarm.com.de

Problem mit TimeZoneInfo.ConvertTimeToUtc

Wir hatten ein Problem, bei dem ein Entwickler den folgenden Code erstellt und dieser in seiner DEV-Umgebung funktioniert. Aber wenn es in QA eingecheckt wird, bricht der Code mit der folgenden Fehlermeldung:

myRecord.UTCStartTime = TimeZoneInfo.ConvertTimeToUtc(myRecord.StartTime, myTimeZone);

Die Konvertierung konnte nicht abgeschlossen werden, da für die angegebene DateTime-Eigenschaft die Kind-Eigenschaft nicht richtig festgelegt wurde. Wenn die Kind-Eigenschaft beispielsweise DateTimeKind.Local ist, muss die Quellzeitzone TimeZoneInfo.Local sein.

In meiner DEV-Umgebung generiert der obige Code den gleichen Fehler wie der QS-Server. Ich habe die folgende Änderung angewendet, um das Problem zu beheben:

DateTime utcStart = DateTime.SpecifyKind(myRecord.StartTime, DateTimeKind.Unspecified);
myRecord.UTCStartTime = TimeZoneInfo.ConvertTimeToUtc(utcStart, myTimeZone);

Warum funktioniert das erste Codebeispiel in der Umgebung von DEV1, funktioniert aber nicht in meiner DEV-Umgebung und auf unserem QA-Server?

17
Jerry

Es hängt davon ab, wie der myRecord.StartTime entstanden ist.

  • Wenn Sie es von DateTime.Now erhalten haben, wird es eine Local-Art haben.
  • Wenn Sie es von DateTime.UtcNow erhalten haben, wird es eine Utc-Art haben.
  • Wenn Sie es von new DateTime(2013,5,1) erhalten haben, hat es eine Unspecified-Art.

Es hängt auch davon ab, woher Sie myTimeZone haben. Zum Beispiel:

  • TimeZoneInfo.Local
  • TimeZoneInfo.Utc
  • TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")

Die Funktion TimeZoneInfo.ConvertTimeToUtc funktioniert nur, wenn die Zone mit der Art übereinstimmt, die Sie ihr geben. Wenn beide lokal sind oder beide UTC sind, funktioniert es. Wenn Sie ihm eine bestimmte Zone zuweisen, sollte die Art nicht angegeben sein. Dieses Verhalten ist auf MSDN dokumentiert .

Sie können die Ausnahme problemlos konsistent reproduzieren:

var tz = TimeZoneInfo.FindSystemTimeZoneById("Fiji Standard Time");
var utc = TimeZoneInfo.ConvertTimeToUtc(DateTime.Now, tz);

Vorausgesetzt, Sie leben nicht in Fidschi, wird dies jedes Mal ein Fehler sein. Sie sagten im Grunde: "Konvertieren Sie meine Ortszeit in einer anderen Zone in UTC" - was keinen Sinn ergibt.

Es funktioniert wahrscheinlich in Ihrer Entwicklungsumgebung, da der Wert, den Sie für myTimeZone testen, zufällig die lokale Zone für den Entwickler ist.

In Bezug auf Ihre Änderung - stellen Sie sicher, dass Sie erzwingen können, dass die Art nicht angegeben wird, und dass sich die Bedeutung Ihrer Handlungen so ändert, dass sie sinnvoll sind. Aber bist du sicher, dass du das willst? Was ist der .Kind des Datums vor der Hand? Wenn es nicht schon Unspecified ist, dann hat es eine Absicht. Sie sollten wahrscheinlich zur Quelle dieser Daten zurückkehren und sicherstellen, dass sie Ihren Erwartungen entsprechen.

Wenn das alles verrückt, verrückt, frustrierend und bizarr klingt, dann weil das Objekt DateTime stinkt. Hier ist eine zusätzliche Lektüre:

Sie könnten erwägen, stattdessen NodaTime zu verwenden. Die API verhindert, dass Sie diese Art von häufigen Fehlern machen.

41
Matt Johnson

in diesem Beispiel habe ich die lokale Zeitzone in einen nicht angegebenen Typ konvertiert, sodass sie mit der Methode "DateTime.SpecifyKind ()" für mich einwandfrei funktioniert

DateTime.SpecifyKind (utc, DateTimeKind.Unspecified);

diese Methode erstellt ein neues DateTime-Objekt mit der gleichen Anzahl von Häkchen wie das angegebene DateTime-Objekt, das jedoch als nicht angegebener DateTimeKind-Typ festgelegt ist.

public static DateTime ConvertLocalDate (DateTime utc) {

        string id = ConfigurationManager.AppSettings["Timezone"].ToString();
        TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById(id);
        utc = DateTime.SpecifyKind(utc,DateTimeKind.Unspecified);
        DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(utc, cstZone);
        return cstTime;
    }
1

Ich habe hier eine wirklich einfache Lösung gefunden https://kiranpatils.wordpress.com/2011/01/09/die-Umwandlung- konnte-nicht-abgeschlossen werden, da-die-gelieferte-Datumszeit-nicht-ist -die-Art-Eigenschaft-richtig-setzen-zum-Beispiel-wenn-die-Art-Eigenschaft-datetimekind-lokal-die-Quelle-Zeitzone-muss/

Was anscheinend nur passiert, wenn Sie DateTime.Now verwenden. Ich aktualisiere meinen Code wie folgt und es funktioniert wieder :)

DateTime currentTime = new DateTime (DateTime.Now.Ticks, DateTimeKind.Unspecified);

1
Atta H.