UTC的日期没有考虑夏令时

时间:2017-08-26 13:23:27

标签: .net datetime timezone dst nodatime

我正在使用日期(1/1/2018 11:30 AM)和时区(东部标准时间)并将其转换为UTC日期(2018-01-01T16:30:00Z)。原始日期实际上是Eastern Daylights Savings,因此当开发人员使用UTC进行转换时,他们会在12:30 PM而不是11:30 AM进行转换。如果我8/26/2018 11:30 AM,它工作正常。我的时区采用.NET Windows格式。

下面的方法是否有办法从NodaTime标准时区获得具有夏令时的正确UTC?

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

方式

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 个答案:

答案 0 :(得分:1)

如果您想继续使用TimeZoneInfo,请直接使用它。不需要你添加的所有额外逻辑。

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

尽管如此,一旦你使用NodaTime,就没有理由这样做。只需使用其内置功能:

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

一个重要的注意事项:你有一个回归TimeZoneInfo.Local.StandardName。这不安全 - 因为StandardName字段已本地化,并且即使在英语中也不总是匹配标识符的名称。如果您需要标识符,请使用Id代替StandardName。在NodaTime中,您可以使用DateTimeZoneProviders.Bcl.GetSystemDefault()