2016-02-24 14 views
12

Avendo un problema per cui la data che desidero salvare cambia dalla data selezionata sullo schermo se gli utenti selezionano un fuso orario che è avanti x numero di ore. E.g. scelgono UTC + 2 Atene e la data di 25/02/2016 dal pop-up del calendario, quindi la data registrata sarà 24/02/2016. Ho ristretto il ragionamento al fatto che il datetime selezionato è registrato come ad esempio 25/02/2016 00:00:00 e con l'offset di 2 ore, questo lo porta a 24/02/2016 22:00:00 Non avendo mai lavorato con fusi orari prima, o date/orari UTC, questo è altamente confusione.Problema intorno a data utc - TimeZoneInfo.ConvertTimeToUtc ha come risultato il cambio di data

Ecco il codice -

 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 sarebbe equivale a qualcosa come 25/02/2016 00:00:00 una volta tornato da ParseDateAndTimeNoUTCMap * (codice qui sotto) *

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; 
     } 

Una volta tornati da quanto sopra, i seguenti linee sono eseguite -

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

È all'interno di GetUTCUsingTimeZone che il problema sembra verificarsi.

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); 
    } 

Ho controllato TimezoneInfo per il valore di offset, e oResult equivale sempre alla oLocal param - l'offset. Quindi 25/02/2016 00:00:00 con uno scostamento di 3 ore equivale a 24/02/2016 21:00:00 Quando l'offset è -ora, va nell'altro diretto, quindi o Result = oLocal + the offset, se ciò ha senso. Quindi il problema principale della modifica della data non si verifica in questi casi.

Ovviamente questo non è quello che voglio. Voglio che la data sia ciò che l'utente ha selezionato, per il loro fuso orario. Qualcuno ha mai visto qualcosa di simile? Qualche possibile soluzione?

Non sono completamente sicuro di quello che ho fatto di sbagliato.

+0

Cosa la struttura/classe 'itTimeAndDate' assomiglia? –

+0

@Ian Kemp: è riuscito a risolvere questo problema eseguendo un'operazione ConvertTimeFromUtc sui dati immessi dall'utente (dopo che l'operazione ConvertTimeToUtc è stata eseguita e salvata nel db) quando un utente torna a questa pagina. Quindi la pagina mostra la data selezionata dall'utente, e cosa è registrato nel db è l'equivalente locale di ciò che hanno selezionato, se questo ha senso. Grazie per la risposta. –

+1

Poco chiaro. Una data in realtà non ha un fuso orario ... Un valore DateTime lo fa. Che tipo di componente UI usi, a cosa serve includere un TZ? –

risposta

0

La correzione è stato quello di eseguire la seguente dopo aver afferrato il valore dal db e prima si mostra di nuovo che -

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

}

Quindi, in sostanza solo facendo il rovescio della ConvertTimeToUtc eseguito in precedenza. Non so perché questo non è stato fatto in origine, ma ci vai.

Problemi correlati