围绕utc日期的问题 - TimeZoneInfo.ConvertTimeToUtc导致日期更改

Ter*_*unt 12 c# timezone datetime utc

如果用户选择提前x个小时的时区,则存在我希望保存的日期从屏幕上选择的日期改变的问题.例如,他们选择UTC + 2雅典和25/02/2016日历弹出日期,然后记录日期24/02/2016.我已经将推理范围缩小到以下事实:所选日期时间被记录为例如25/02/2016 00:00:002小时偏移量,这使得它24/02/2016 22:00:00 从未使用过之前的时区或UTC日期/时间,这非常令人困惑.

这是代码 -

     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);  
        }
Run Code Online (Sandbox Code Playgroud)

RefDate等同于25/02/2016 00:00:00从ParseDateAndTimeNoUTCMap*返回的东西(下面的代码)*

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;
        }
Run Code Online (Sandbox Code Playgroud)

从上面返回后,执行以下行 -

TimeZoneInfo oTimeZone = TimeZoneInfo.FindSystemTimeZoneById(oObject.TimeZoneDetails);
        oObject.RefDate = itTimeAndDate.GetUTCUsingTimeZone(oTimeZone, oObject.RefDate);  
Run Code Online (Sandbox Code Playgroud)

正是在GetUTCUsingTimeZone这个范围内,问题似乎发生在我身上.

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);
    }
Run Code Online (Sandbox Code Playgroud)

我检查TimezoneInfo了偏移值,并oResult始终等于oLocal param- 偏移量.因此25/02/2016 00:00:00,3小时的偏移量等于24/02/2016 21:00:00 当偏移量是-hours时,它会直接进入另一个,所以o Result = oLocal + the offset,如果这是有意义的话.因此,在这些情况下不会发生日期变更的主要问题.

显然这不是我想要的.我希望日期是用户为他们的时区选择的.以前有人见过这样的东西吗?任何可能的解决方

我不完全确定我做错了什么.

Ter*_*unt 0

修复方法是在从数据库中获取值之后并在重新显示它之前运行以下命令 -

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);
Run Code Online (Sandbox Code Playgroud)

}

因此,本质上只是执行之前执行的 ConvertTimeToUtc 的相反操作。不知道为什么最初没有这样做,但就是这样。