Search code examples
c#parsingdatetimelocaltime

c# making a short date ends up adding one day


I am trying to make a short date, but in the result I get one day more. With date like "2014-01-03 00:00:00" its okay, but it fails when time is "23:59:59".

EntryDate= "2014-01-03 23:59:59"

but getting result = "2014-01-04"

  try
        {
            DateTime exact = DateTime.ParseExact(EntryDate, "yyyyMMdd", (IFormatProvider)CultureInfo.InvariantCulture);
            mventryAttrib.Value = (exact.ToLocalTime().ToString("yyyy-MM-dd"));
        }
        catch (FormatException ex)
        {
            try
            {
                DateTime exact = DateTime.ParseExact(EntryDate, "yyyy-MM-dd HH:mm:ss", (IFormatProvider)CultureInfo.InvariantCulture);
                mventryAttrib.Value = (exact.ToLocalTime().ToString("yyyy-MM-dd"));
            }
            catch
            {
            }

Solution

  • This is due to ParseExact returns a DateTime with a Kind property value of DateTimeKind.Unspecified.

    This, when coupled with a call to .ToLocalTime() when you're in a timezone that has a positive offset from UTC, will bump the DateTime value forward by that many hours and return a DateTime value with a Kind property value of DateTimeKind.Local.

    Here is a short program that will demonstrate:

    var exact = DateTime.ParseExact("2014-01-03 23:59:59", "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
    Console.WriteLine($"{exact} - {exact.Kind}");
    
    var local = exact.ToLocalTime();
    Console.WriteLine($"{local} - {local.Kind}");
    
    Console.WriteLine(TimeZone.CurrentTimeZone.GetUtcOffset(exact));
    

    Output (on my machine):

    03.01.2014 23.59.59 - Unspecified
    04.01.2014 00.59.59 - Local
    01:00.00
    

    If you intended the parsed DateTime value to be local from the outset you should make a new value that is specifically local, with the same values:

    exact = new DateTime(exact.Ticks, DateTimeKind.Local);
    

    Be aware though that this may have unforseen consequences when dealing with timezone boundaries. I would urge you to find a better library than the built in DateTime types, such as Noda Time.