2016-02-24 5 views
12

Ich habe ein Problem, bei dem das Datum, das ich speichern möchte, sich vom ausgewählten Bildschirmdatum ändert, wenn der Benutzer eine Zeitzone vor mir x Stundenanzahl auswählt. Zum Beispiel Sie wählen UTC + 2 Athen und das Datum 25/02/2016 aus dem Kalender-Pop-up, dann wird das aufgezeichnete Datum 24/02/2016 sein. Ich habe die Argumentation darauf beschränkt, dass das ausgewählte Datum wie zum Beispiel 25/02/2016 00:00:00 und mit dem 2-Stunden-Offset aufgezeichnet wird, dies dauert Da nie mit Zeitzonen vor oder UTC Daten/Zeiten gearbeitet wurde, ist dies sehr hoch verwirrend.Ausgabe um Datum - TimeZoneInfo.ConvertTimeToUtc führt zu Datumsänderung

Hier ist der Code -

 oObject.RefDate = itTimeAndDate.ParseDateAndTimeNoUTCMap(Request, TextBox_RefDate.Text); 
     if (!string.IsNullOrEmpty(oObject.TimeZoneDetails)) 
     { 
TimeZoneInfo oTimeZone = TimeZoneInfo.FindSystemTimeZoneById(oObject.TimeZoneDetails); 
      oObject.RefDate = itTimeAndDate.GetUTCUsingTimeZone(oTimeZone, oObject.RefDate); 
     } 

RefDate zu so etwas wie 25/02/2016 00:00:00 einmal zurück von ParseDateAndTimeNoUTCMap * (Code unten) *

static public itDateTime ParseDateAndTimeNoUTCMap(HttpRequest oTheRequest, string sValue) 
     { 
      DateTime? oResult = ParseDateAndTimeNoUTCMapNull(oTheRequest, sValue); 
      if (oResult != null) 
       return new itDateTime(oResult.Value); 
      return null; 
     } 

     /// <summary> 
     /// Translate a string that has been entered by a user to a UTC date/time - mapping using the 
     /// current time zone 
     /// </summary> 
     /// <param name="oTheRequest">Request context</param> 
     /// <param name="sValue">Date/time string entered by a user</param> 
     /// <returns>UTC date/time object</returns> 
     static public DateTime? ParseDateAndTimeNoUTCMapNull(HttpRequest oTheRequest, string sValue) 
     { 
      try 
      { 
       if (string.IsNullOrEmpty(sValue)) 
        return null; 
       sValue = sValue.Trim(); 
       if (string.IsNullOrEmpty(sValue)) 
        return null; 

       if (oTheRequest != null) 
       { 
        const DateTimeStyles iStyles = DateTimeStyles.AllowInnerWhite | DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite; 
        // Create array of CultureInfo objects 
        CultureInfo[] aCultures = new CultureInfo[oTheRequest.UserLanguages.Length + 1]; 
        for (int iCount = oTheRequest.UserLanguages.GetLowerBound(0); iCount <= oTheRequest.UserLanguages.GetUpperBound(0); 
         iCount++) 
        { 
         string sLocale = oTheRequest.UserLanguages[iCount]; 
         if (!string.IsNullOrEmpty(sLocale)) 
         { 

          // Remove quality specifier, if present. 
          if (sLocale.Contains(";")) 
           sLocale = sLocale.Substring(0, sLocale.IndexOf(';')); 
          try 
          { 
           aCultures[iCount] = new CultureInfo(sLocale, false); 
          } 
          catch (Exception) { } 
         } 
         else 
         { 
          aCultures[iCount] = CultureInfo.CurrentCulture; 
         } 
        } 
        aCultures[oTheRequest.UserLanguages.Length] = CultureInfo.InvariantCulture; 
        // Parse input using each culture. 
        foreach (CultureInfo culture in aCultures) 
        { 
         DateTime oInputDate; 
         if (DateTime.TryParse(sValue, culture.DateTimeFormat, iStyles, out oInputDate)) 
          return oInputDate; 
        } 
       } 
       return DateTime.Parse(sValue); 
      } 
      catch (Exception) 
      { 
      } 
      return null; 
     } 

Einmal aus dem oben zurück entsprechen würde, wird die folgende Linien werden ausgeführt -

TimeZoneInfo oTimeZone = TimeZoneInfo.FindSystemTimeZoneById(oObject.TimeZoneDetails); 
     oObject.RefDate = itTimeAndDate.GetUTCUsingTimeZone(oTimeZone, oObject.RefDate); 

Es ist innerhalb GetUTCUsingTimeZone, dass das Problem scheint mir auffallen.

static public itDateTime GetUTCUsingTimeZone(TimeZoneInfo oTimeZone, itDateTime oDateTime) 
    { 
     if (oDateTime == null || oTimeZone == null) 
     return oDateTime; 
     DateTime oLocal = DateTime.SpecifyKind(oDateTime.Value, DateTimeKind.Unspecified); 
     DateTime oResult = TimeZoneInfo.ConvertTimeToUtc(oLocal, oTimeZone); 

     return new itDateTime(oResult); 
    } 

I TimezoneInfo für den Offset-Wert überprüft haben, und oResult entspricht immer dem oLocal param - der Offset. Also 25/02/2016 00:00:00 mit einem 3-Stunden-Offset würde 24/02/2016 21:00:00 entsprechen Wenn der Offset-Stunden ist, geht es in den anderen direkt, so o Result = oLocal + the offset, wenn das Sinn macht. Daher tritt das Hauptproblem der Datumsänderung in diesen Fällen nicht auf.

Offensichtlich ist das nicht was ich will. Ich möchte, dass das Datum dem entspricht, was der Benutzer für seine Zeitzone ausgewählt hat. Hat jemand so etwas schon mal gesehen? Irgendeine mögliche Lösung?

Ich bin mir nicht ganz sicher, was ich falsch gemacht habe.

+0

Was sieht die 'itTimeAndDate' struct/Klasse aus? –

+0

@Ian Kemp - Dieses Problem wurde gelöst, indem eine ConvertTimeFromUtc-Operation für die Daten ausgeführt wurde, die der Benutzer eingegeben hat (nachdem die Operation ConvertTimeToUtc ausgeführt und in der Datenbank gespeichert wurde), wenn ein Benutzer auf diese Seite zurückkehrt. So zeigt die Seite das Datum an, das der Benutzer ausgewählt hat, und was in der db aufgezeichnet wird, ist das lokale Äquivalent dessen, was sie ausgewählt haben, wenn dies sinnvoll ist. Danke für die Antwort. –

+1

Unklar. Ein Date hat nicht wirklich eine TimeZone ... Ein DateTime-Wert. Welche Art von Benutzeroberflächenkomponente (n) verwenden Sie? Was ist der beabsichtigte Einsatz von TZ? –

Antwort

0

Das Update war die folgende nach sich ziehen den Wert aus der db und vor erneutes Anzeigen, um sie auszuführen -

static public itDateTime FixUTCUsingTimeZone(TimeZoneInfo oTimeZone, itDateTime oDateTime) 
{ 
    if (oDateTime == null || oTimeZone == null) 
     return oDateTime; 

    DateTime oTime = DateTime.SpecifyKind(oDateTime.Value, DateTimeKind.Unspecified); 
    DateTime oResult = TimeZoneInfo.ConvertTimeFromUtc(oTime, oTimeZone); 

    return new itDateTime(oResult); 

}

So im Wesentlichen nur die Rückseite des ConvertTimeToUtc tun früher durchgeführt. Nicht sicher, warum das ursprünglich nicht gemacht wurde, aber da gehst du.