Date to UTC not taking into account daylight savings

439 views Asked by At

I am using a date (1/1/2018 11:30 AM) with timezone (Eastern Standard Time) and converting it to a UTC date (2018-01-01T16:30:00Z). The original date is really Eastern Daylights Savings, so when developers do a conversion with the UTC, they get 12:30 PM instead of 11:30 AM. If I do 8/26/2018 11:30 AM, it works fine. My time zones are in the .NET Windows formats.

Is there a way with my method below to get the correct UTC that has the daylight savings from the timezone that is Standard with NodaTime?

2018-01-01T16:30:00Z = Helper.GetUtcTimeZone("1/1/2018 11:30 AM", "Eastern Standard Time").ToString();

Method

public static Instant GetUtcTimeZone(DateTime dateTime, string timeZone)
{
    var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZone ?? TimeZoneInfo.Local.StandardName);

    if (timeZoneInfo != null)
    {
        if (dateTime.Kind == DateTimeKind.Unspecified)
        {
            dateTime = TimeZoneInfo.ConvertTimeToUtc(dateTime, timeZoneInfo);
        }
    }

    return Instant.FromDateTimeUtc(dateTime);
}
1

There are 1 answers

1
Matt Johnson-Pint On BEST ANSWER

If you want to keep using TimeZoneInfo, just use it directly. No need for all the extra logic you've added.

public static Instant GetUtcTimeZone(DateTime dateTime, string timeZone)
{
    TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZone);
    DateTime utcDateTime = TimeZoneInfo.ConvertTimeToUtc(dateTime, timeZoneInfo);
    return Instant.FromDateTimeUtc(utcDateTime);
}

Though really, once you are using NodaTime, there's no reason for that. Just use its built-in functionality:

public static Instant GetUtcTimeZone(DateTime dateTime, string timeZone)
{
    LocalDateTime ldt = LocalDateTime.FromDateTime(dateTime);
    DateTimeZone tz = DateTimeZoneProviders.Bcl[timeZone];
    return ldt.InZoneLeniently(tz).ToInstant();
}

One important note: You had a fall-back to TimeZoneInfo.Local.StandardName. That's not safe - as the StandardName fields are localized, and don't always match the names of the identifiers even in English. Use Id instead of StandardName if you are expecting an identifier. In NodaTime, you can use DateTimeZoneProviders.Bcl.GetSystemDefault().