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
{
}
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.