关于.net:UTC的日期不考虑夏令时

Date to UTC not taking into account daylight savings

我正在使用日期(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?

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

方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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);
}

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

1
2
3
4
5
6
public static Instant GetUtcTimeZone(DateTime dateTime, string timeZone)
{
    TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZone);
    DateTime utcDateTime = TimeZoneInfo.ConvertTimeToUtc(dateTime, timeZoneInfo);
    return Instant.FromDateTimeUtc(utcDateTime);
}

虽然真的,一旦你使用NodaTime,就没有理由这样做。 只需使用其内置功能:

1
2
3
4
5
6
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()