2016-04-03 15 views
0

Es ist ein Fehler Umwandlung in Datetime UTC Datetime wenn die Art Utc ist. Die origDateTime kommt vom Webservice, also habe ich keine Kontrolle über den Inhalt oder das Format. In den meisten Fällen ist es mit Art kommt = (hart auch die Zeit, in Utc ist) unspezifisch und dann die Konvertit zu Datetime warf Ausnahme, dass es funktioniert, aber in seltenen Fällen die Art = Utc und dann: „Die UTC-Offset für Utc Datetime-Instanzen 0. \ r \ nParameter Name sein muss: Offset“ Wie soll ich es lösen?Fehler von Datetime UTC Umwandlung in Datetime wenn Art Utc ist

 try { 

      //cause error !!!! 
      DateTime databaseUtcTime = DateTime.Parse("4/2/2016 6:25:20 PM"); 
      var localTimeTemp = databaseUtcTime.ToLocalTime(); 
      DateTime origDateTime = localTimeTemp.ToUniversalTime(); 

      //this is working 
      //DateTime origDateTime = DateTime.Parse("4/2/2016 6:25:20 PM"); 

      string timeZoneName = "Pacific Standard Time"; 
      TimeZoneInfo localTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneName); 
      DateTimeOffset localTime = new DateTimeOffset(origDateTime, localTimeZone.GetUtcOffset(origDateTime)); 
      return localTime; 
     } 
     catch (Exception ex) { 
      string msg = ex.Message; 
      return null; 
     } 
+0

Datatime Parse konvertiert automatisch zu UTC Zeitzoneneinstellungen, so gibt es keine Notwendigkeit zu konvertieren ist. Die Verbindung zu einer Datenbank verwendet auch automatisch die UTC-Zeit, daher ist Ihr Code nicht sehr sinnvoll. Verwenden Sie Zeitzonen-Offsets nur, wenn Sie Daten eingeben, die in einer anderen Zeitzone gesammelt wurden, oder wenn Sie Zeit in einer anderen Zeitzone anzeigen möchten. Die Funktionen der Net-Bibliothek speichern die Zeit auf dem Computer als eine Zahl in UTC und konvertieren die UTC automatisch bei der Eingabe oder Ausgabe. – jdweng

+0

Ich muss jedes Datetime zu einem Datetimeoffset mit verschiedenen Zeitzonen (entsprechend einem anderen Feld) konvertieren, um in verschiedenen Zeitzonen zu zeigen. Xavier Antwort löste das Problem. Danke. – user2455595

Antwort

2

Ein paar Dinge:

  • Wenn Sie wirklich die Kind eines DateTime müssen wechseln, ohne Anpassung sein Wert, verwenden Sie DateTime.SpecifyKind. Es ist sauberer als der Umgang mit Zecken. Aber ich glaube nicht, dass du das wirklich tun musst.

  • Verwenden Sie nicht ToLocalTime oder ToUniversalTime. Beide werden die Zeitzoneneinstellung des Server im Konvertierungsprozess verwenden.

  • Ich bin mir nicht sicher, ob Ihr echte Code tatsächlich eine Zeichenfolge analysiert, weil Sie angegeben haben, dass es aus der Datenbank stammt. Wenn es von der Datenbank kommt, sollte kein String-Parsing beteiligt sein. Genau wie folgt vor:

    DateTime databaseUtcTime = (DateTime) yourDataReader["YourDataField"]; 
    
  • Sobald Sie den Eingang haben, können Sie dann wandeln die TimeZoneInfo.ConvertTime Funktionen. Ihr vorhandener Code konvertiert die Zeit nicht korrekt, sondern weist nur einen Offset zu, ohne den Zeitwert korrekt einzustellen.

    Da Sie Ihre Ausgabe sein ein datetimeoffset wollten, dann ist der einfachste Weg, um zunächst Ihre Eingabe datetime zu einem datetimeoffset mit Null für den Offset zu konvertieren (da es von UTC kommt).

    DateTimeOffset dtoUtc = new DateTimeOffset(databaseUtcTime, TimeSpan.Zero); 
    

    Dann ist es ziemlich einfach zu konvertieren:

    string timeZoneName = "Pacific Standard Time"; 
    TimeZoneInfo localTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneName); 
    DateTimeOffset dtoLocal = TimeZoneInfo.ConvertTime(dtoUtc, localTimeZone); 
    
+0

Die Verwendung von String dient nur zu Testzwecken, gleiches gilt für ToUniversalTime. Es ist nur um die Daten vom Server zu simulieren. Kannst du bitte erklären, was ist der Unterschied zwischen dem, was ich tat, Offset im Konstruktor DateTimeOffset hinzufügen localTime = new DateTimeOffset (origDateTime, localTimeZone.GetUtcOffset (origDateTime)); und Ihr Code, der ConvertTime verwendet? – user2455595

+0

Ich sah den Unterschied, Ihr Code wirklich das Datum und ändern Sie es auf {4/2/2016 11:25:20 AM -07: 00} per Definition Ich brauche nur den Offset zu tun, sonst würde ich Ihren Code verwenden . danke. – user2455595

+0

Das Datum und die Uhrzeit in einem 'DateTimeOffset' sind die * lokale * Zeit, die bereits für diesen Offset eingestellt wurde. Dies ist nicht nur eine .NET Sache - es ist nach ISO8601 Konvention. Der Zeitstempel "2016-04-02T18: 25: 20 + 00: 00" entspricht "2016-04-02T11: 25: 20-07: 00". Wenn Sie nur einen Versatz anwenden, ohne den Zeitwert anzupassen, beziehen Sie sich auf einen völlig anderen Zeitpunkt. –

1

So wird Ihr Problem, wenn Sie konsequent Ihre gesetzt DateTimeKind zu Unspecified gelöst werden, ist es nicht?

Versuchen Sie folgendes:

DateTime origDateTime = new DateTime(origDateTimeUnspecifiedKind.Ticks, DateTimeKind.Unspecified); 

Integriert mit Ihrem Beispiel:

 try 
     { 

      //cause error !!!! 
      DateTime databaseUtcTime = DateTime.Parse("4/2/2016 6:25:20 PM"); 
      var localTimeTemp = databaseUtcTime.ToLocalTime(); 
      DateTime origDateTimeUnspecifiedKind = localTimeTemp.ToUniversalTime(); 

      // FIX: specify the kind 
      DateTime origDateTime = new DateTime(origDateTimeUnspecifiedKind.Ticks, DateTimeKind.Unspecified); 

      //this is working 
      //DateTime origDateTime = DateTime.Parse("4/2/2016 6:25:20 PM"); 

      string timeZoneName = "Pacific Standard Time"; 
      TimeZoneInfo localTimeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneName); 
      DateTimeOffset localTime = new DateTimeOffset(origDateTime, localTimeZone.GetUtcOffset(origDateTime)); 
      return localTime; 
     } 
     catch (Exception ex) 
     { 
      string msg = ex.Message; 
      return null; 
     } 
+1

Dies löste das Problem. Danke. – user2455595