2016-02-24 23 views
12

Có vấn đề trong đó ngày tôi muốn lưu đang thay đổi từ ngày được chọn trên màn hình nếu người dùng chọn múi giờ trước x số giờ. Ví dụ: họ chọn UTC + 2 Athens và ngày 25/02/2016 từ cửa sổ bật lên lịch, sau đó ghi ngày sẽ là 24/02/2016. Tôi đã thu hẹp lý do xuống đến thực tế rằng ngày giờ đã chọn được ghi lại như ví dụ 25/02/2016 00:00:00 và với bù 2 giờ, điều này sẽ mất đến 24/02/2016 22:00:00 Chưa bao giờ làm việc với múi giờ trước đây, hoặc ngày/giờ UTC, điều này rất cao gây nhầm lẫn.Vấn đề xung quanh ngày utc - TimeZoneInfo.ConvertTimeToUtc dẫn đến thay đổi ngày

Đây là mã -

 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 sẽ tương đương với một cái gì đó giống như 25/02/2016 00:00:00 một lần trở về từ ParseDateAndTimeNoUTCMap * (mã bên dưới) *

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

Khi trở về từ bên trên, sau đây các dòng được thực thi -

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

Đó là trong phạm vi GetUTCUsingTimeZone rằng vấn đề dường như xảy ra với tôi.

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

Tôi đã kiểm tra TimezoneInfo cho giá trị bù đắp, và oResult luôn tương đương với các oLocal param - bù đắp. Vì vậy, 25/02/2016 00:00:00 với chênh lệch 3 giờ sẽ tương đương với 24/02/2016 21:00:00 Khi bù đắp-giờ, nó đi theo hướng khác, vì vậy o Result = oLocal + the offset, nếu điều đó có ý nghĩa. Vì vậy, vấn đề chính của ngày thay đổi không xảy ra trong những trường hợp đó.

Rõ ràng đây không phải là điều tôi muốn. Tôi muốn ngày là những gì người dùng đã chọn, cho múi giờ của họ. Có ai nhìn thấy một cái gì đó như thế này trước đây không? Bất kỳ giải pháp có thể?

Tôi không hoàn toàn chắc chắn những gì tôi đã làm sai.

+0

gì hiện struct/class 'itTimeAndDate' trông như thế nào? –

+0

@Ian Kemp - được quản lý để giải quyết vấn đề này bằng cách thực hiện thao tác ConvertTimeFromUtc trên dữ liệu người dùng nhập (sau khi đã thực hiện thao tác ConvertTimeToUtc và lưu vào db) khi người dùng quay lại trang này. Vì vậy, trang hiển thị ngày người dùng đã chọn và những gì được ghi lại trong db là tương đương cục bộ của những gì họ đã chọn, nếu điều đó có ý nghĩa. Cảm ơn bạn đã trả lời. –

+1

Không rõ ràng. Một ngày không thực sự có một TimeZone ... Một giá trị DateTime nào. Bạn sử dụng (các) thành phần giao diện người dùng nào, mục đích sử dụng bao gồm TZ là gì? –

Trả lời

0

Việc sửa chữa là để chạy sau khi lấy các giá trị từ db và trước redisplaying nó -

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

}

Vì vậy, về cơ bản chỉ là làm ngược lại của ConvertTimeToUtc thực hiện trước đó. Không chắc chắn tại sao điều này đã không được thực hiện ban đầu, nhưng có bạn đi.

0

Nếu bạn cần duy trì múi giờ chính xác, bạn nên sử dụng loại DateTimeOffset thay vì loại DateTime.

DateTimeOffset duy trì bù đắp từ UTC, do đó bạn không bao giờ mất thông tin múi giờ của bạn và có rất nhiều phương pháp hữu ích như UtcDateTime

Từ ngựa miệng:

https://msdn.microsoft.com/en-us/library/system.datetimeoffset(v=vs.110).aspx

https://docs.microsoft.com/en-us/dotnet/standard/datetime/choosing-between-datetime

Các vấn đề liên quan