Sam
Sam

Reputation: 948

UTC DateTime Conversion To US Eastern

I am getting confused about UTC and cannot find anything anywhere.

I have the GMT time of 00:00:00

I want to convert it to the UTC time for US Eastern Standard Time.

I get 04:00:00-04 as the UTC string.

This is my code.

string UTCDateTime;
TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById("US Eastern Standard Time")
DateTime dateTimeOld = new DateTime(2017,09,11,0,0,0);
DateTime dateTime = TimeZoneInfo.ConvertTimeToUtc(dateTimeOld, timeZone);

UTCDateTime = dateTime.ToUniversalTime().ToString("yyyy-MM-dd HH:mm:ss");

var offset = timeZone.GetUtcOffset(dateTime);

UTCDateTime += ((offset < TimeSpan.Zero) ? "-" : "+") + offset.ToString("hh");'

So my output will be a UTC string: "2017-09-11 04:00:00-04".

Is that correct? Shouldn't it be "2017-09-11 00:00:00-04"

Upvotes: 0

Views: 2294

Answers (2)

Matt Johnson-Pint
Matt Johnson-Pint

Reputation: 241420

This use case is much better handled with DateTimeOffset.

// The source time in UTC
DateTimeOffset utc = new DateTimeOffset(2017, 9, 11, 0, 0, 0, TimeSpan.Zero);

// The time zone for the Eastern US
TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");

// The converted time in the time zone
DateTimeOffset eastern = TimeZoneInfo.ConvertTime(utc, timeZone);

// output in a usable format
Console.WriteLine(eastern.ToString("yyyy-MM-dd HH:mm:ss zzz"));

//=>  2017-09-10 20:00:00 -04:00

A few notes:

  • GMT and UTC mean the same thing in this context. Saying you have GMT and you want UTC is nonsensical. If you meant a string in a particular format, then describe the format. UTC is not a string format.

  • The "US Eastern Standard Time" entry should only used in certain parts of Indiana. Most of the US Eastern time zone is represented by the "Eastern Standard Time" entry. If you are interested, see Time in Indiana for more details.

  • Don't assume all time zones will have only hours offset. Many are also offset by 30 or 45 minutes. Presenting only hours could lead to data errors if you ever use any of those time zones.

  • Avoid calling ToUniversalTime unless the source data is indeed in the computer's local time zone.

  • Note the output. Neither your code or your assumption were correct. Eastern US is four hours behind UTC. Therefore, when it is midnight UTC, it is 20:00 (or 8:00 PM) on the prior day in US Eastern time.

Upvotes: 2

Lars M&#248;llebjerg
Lars M&#248;llebjerg

Reputation: 255

Your dateTimeOld is midnight in EST.

You then convert this to UTC using your timezone and put in dateTime.

Since UTC is 4 hours ahead of EST, this means dateTime is now 04:00 with DateTimeKind.Utc.

You then convert it once more in the assignment to UTCDateTime. But as it already is UTC (from your previous conversion) this does nothing. So it will put 2017-09-11 04:00:00 into the string UTCDateTime.

You then add the timezone offset from your timezone info - which makes no sense. The timezone is associated with a local time - which is dateTimeOld. By converting to UTC you specifically get rid of the timezone offset.

So either initialize the string from dateTimeOld and add the timezone offset - this would give: 2017-09-11 00:00:00-04

or use the UTC time in dateTime directly with a 'Z' postfix to indicate UTC (Zulu time), so you get 2017-09-11 04:00:00Z

Both of these indicate the same time (unless I copy pasted something wrong) :)

In general when dealing with dates the common convention is to get the data converted to UTC as soon as possible and keep UTC throughout the program - and then convert to local time just as the data is displayed. But you can choose to use DateTimeOffset as well - it can, unlike DateTime, store local time across multiple timezones.

Upvotes: 1

Related Questions