4

With the code below, I'm trying to convert this datetime string to a Local DateTime

private DateTime ConvertToLocalTime(string datetimestring)
{
    DateTime timeUtc = DateTime.Parse(datetimestring);
    TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
    DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, cstZone);
    return cstTime;
}

This is the Exception I'm getting:

at System.TimeZoneInfo.ConvertTime(DateTime dateTime, TimeZoneInfo sourceTimeZone, TimeZoneInfo destinationTimeZone, TimeZoneInfoOptions flags, CachedData cachedData) at System.TimeZoneInfo.ConvertTimeFromUtc(DateTime dateTime, TimeZoneInfo destinationTimeZone)

The conversion could not be completed because the supplied DateTime did not have the Kind property set correctly. For example, when the Kind property is DateTimeKind.Local, the source time zone must be TimeZoneInfo.Local.

The example for ConvertTimeFromUtc looks exactly like my code except I'm parsing this string into the timeUtc: 2017-01-23T05:00:00+00:00

If I call the Parse like this:

DateTime.Parse(datetimestring, null, System.Globalization.DateTimeStyles.RoundtripKind);

timeUtc.Kind.ToString() returns "Local"

So, how do I remedy this? The times are going to be sent to me UTC.

Meer
  • 2,765
  • 2
  • 19
  • 28
MB34
  • 4,210
  • 12
  • 59
  • 110
  • Will this can help? http://stackoverflow.com/questions/6239976/how-to-set-a-time-zone-or-a-kind-of-a-datetime-value – Prisoner Jan 24 '17 at 04:29

3 Answers3

3

DateTime.Parse converts the result into local time regardless of the zone specified in the input string. You have to explicitly specify that you want a UTC result, as TimeZoneInfo.ConvertTimeFromUtc requires the DateTime value to be of kind UTC.

private DateTime ConvertToLocalTime(string datetimestring)
{
    DateTime timeUtc = DateTime.Parse(datetimestring, null, System.Globalization.DateTimeStyles.AdjustToUniversal);
    TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
    DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, cstZone);
    return cstTime;
}
Ghasan غسان
  • 5,577
  • 4
  • 33
  • 44
3

You have to add DateTime.SpecifyKind

private static DateTime ConvertToLocalTime(string datetimestring)
{
    DateTime timeUtc = DateTime.Parse(datetimestring);
    var dt = DateTime.SpecifyKind(timeUtc, DateTimeKind.Utc);
    TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
    DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(dt, cstZone);
    return cstTime;
}

.net Fiddle

Max
  • 1,070
  • 3
  • 13
  • 19
  • Will test this out tomorrow. Didn't see the SpecifyKind method. – MB34 Jan 24 '17 at 04:46
  • No, it works. You could check in fiddler. @MB34 error is that when he converts timeUtc.Kind is Local but timeUtc variable has UTC time. DateTime.SpecifyKind function sets timeUtc.Kind to UTC without changing time. – Max Jan 24 '17 at 14:54
0

If you just want to convert to local datetime and you do not need the offset, since your string has offset info, DateTime.Parse will use the offset info and convert to local datetime. Then all you need to do is:

private static DateTime ConvertToLocalTime(string datetimestring)
{
    // Parses to local datetime
    // check the Kind property and you will see it has Local
    return DateTime.Parse(datetimestring);
}

If you need the local datetime with the offset info, then have a look at DateTimeOffset because it is for this very purpose:

private static DateTimeOffset ConvertToLocalTime(string datetimestring)
{
    DateTime timeUtc = DateTime.Parse(datetimestring, null, DateTimeStyles.AdjustToUniversal);
    DateTimeOffset dateCst = new DateTimeOffset(timeUtc, TimeZoneInfo.Local.BaseUtcOffset);

    return dateCst;
}

If you need the utc datetime converted to some other timezone, not local, then specify it like below:

private static DateTimeOffset ConvertToLocalTime(string datetimestring)
{
    DateTime timeUtc = DateTime.Parse(datetimestring, null, DateTimeStyles.AdjustToUniversal);
    TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
    DateTimeOffset dateCst = new DateTimeOffset(timeUtc, cstZone.GetUtcOffset(timeUtc));

    return dateCst;
}

This is the documentation:

//
// Summary:
//     Initializes a new instance of the System.DateTimeOffset structure using the specified
//     System.DateTime value and offset.
//
// Parameters:
//   dateTime:
//     A date and time.
//
//   offset:
//     The time's offset from Coordinated Universal Time (UTC).
//
// Exceptions:
//   T:System.ArgumentException:
//     dateTime.Kind equals System.DateTimeKind.Utc and offset does not equal zero.-or-dateTime.Kind
//     equals System.DateTimeKind.Local and offset does not equal the offset of the
//     system's local time zone.-or-offset is not specified in whole minutes.
//
//   T:System.ArgumentOutOfRangeException:
//     offset is less than -14 hours or greater than 14 hours.-or-System.DateTimeOffset.UtcDateTime
//     is less than System.DateTimeOffset.MinValue or greater than System.DateTimeOffset.MaxValue.
CodingYoshi
  • 25,467
  • 4
  • 62
  • 64