Issue around utc date - TimeZoneInfo.ConvertTimeToUtc results in date change
<p>Having an issue whereby the date I wish to save is changing from the onscreen selected date if the users selects a timezone that is ahead x number of hours.
E.g. they choose <em>UTC+2 Athens</em> and date of <code>25/02/2016</code> from the calendar pop-up, then date recorded will be <code>24/02/2016</code>.
I've narrowed the reasoning down to the fact that the selected datetime is recorded as for example <code>25/02/2016 00:00:00</code> and with the 2 hour offset, this takes it to <code>24/02/2016 22:00:00</code>
Having never worked with timezones before, or UTC dates/times, this is highly confusing.</p>

<p><strong>Here is the code -</strong></p>

<pre><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);  
        }
</code></pre>

<p><code>RefDate</code> would equate to something like <code>25/02/2016 00:00:00</code> once returned from <code>ParseDateAndTimeNoUTCMap</code> * (code below)*</p>

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

        /// &lt;summary&gt;
        /// Translate a string that has been entered by a user to a UTC date / time - mapping using the
        /// current time zone
        /// &lt;/summary&gt;
        /// &lt;param name="oTheRequest"&gt;Request context&lt;/param&gt;
        /// &lt;param name="sValue"&gt;Date / time string entered by a user&lt;/param&gt;
        /// &lt;returns&gt;UTC date / time object&lt;/returns&gt;
        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 &lt;= 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;
        }
</code></pre>

<p>Once returned from the above, the following lines are executed -</p>

<pre><code>TimeZoneInfo oTimeZone = TimeZoneInfo.FindSystemTimeZoneById(oObject.TimeZoneDetails);
        oObject.RefDate = itTimeAndDate.GetUTCUsingTimeZone(oTimeZone, oObject.RefDate);  
</code></pre>

<p>It is within <code>GetUTCUsingTimeZone</code> that the problem seems to occur to me.</p>

<pre><code>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);
    }
</code></pre>

<p>I have checked <code>TimezoneInfo</code> for the offset value, and <code>oResult</code> always equates to the <code>oLocal param</code> - the offset. So <code>25/02/2016 00:00:00</code> with a 3 hour offset would equate to <code>24/02/2016 21:00:00</code>
When the offset is -hours, it goes in the other direct, so o<code>Result = oLocal + the offset</code>, if that makes sense. So the main issue of the date changing is not occurring in those instances.</p>

<p>Obviously this is not what I want. I want the date to be what the user has selected, for their timezone.
Has anyone seen something like this before? Any possible solution?</p>

<p>I'm not entirely sure what I've done wrong.</p>