当服务器设置为UTC时,创建夏令时感知的DateTime

Ric*_*ett 4 c# datetime utc azure dst

我的应用程序托管在Windows Azure上,其中所有服务器都设置为UTC.

我需要知道什么时候给予DateTime夏令时.为简单起见,我们可以假设我的用户都在英国(因此使用格林威治标准时间).

我用来转换DateTime对象的代码是

public static DateTime UtcToUserTimeZone(DateTime dateTime)
{
    dateTime = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc);

    var timeZone = TimeZoneInfo.FindSystemTimeZoneById("Greenwich Standard Time");

    var userDateTime = TimeZoneInfo.ConvertTime(dateTime, timeZone);

    return DateTime.SpecifyKind(userDateTime, DateTimeKind.Local);
}
Run Code Online (Sandbox Code Playgroud)

但是,以下测试在最后一行失败; 转换后DateTime不知道它应该在夏令时.

[Test]
public void UtcToUserTimeZoneShouldWork()
{
    var utcDateTime = new DateTime(2014, 6, 1, 12, 0, 0, DateTimeKind.Utc);
    Assert.IsFalse(utcDateTime.IsDaylightSavingTime());

    var dateTime = Utils.UtcToUserTimeZone(utcDateTime);
    Assert.IsTrue(dateTime.IsDaylightSavingTime());
}
Run Code Online (Sandbox Code Playgroud)

请注意,仅当我的Windows时区设置为(UTC)协调世界时时,这才会失败.当设定为(UTC)都柏林,爱丁堡,里斯本,伦敦(或任何其他观察夏令时的北半球时区)时,测试通过.如果在Windows中更改此设置,则需要重新启动Visual Studio才能使更改完全生效.

我错过了什么?

Jon*_*eet 5

您的最后一行指定该值位于其运行的系统的本地时区中 - 但实际上并非...它使用不同的时区进行转换.

基本上DateTime有点坏,在我看来-这使得它难以正确使用.没有办法说"此DateTime值在时区x" - 您可以执行转换以查找特定的本地时间,但不记得时区.

例如,从DateTime.IsDaylightSavingTime(强调我的)文档:

此方法确定当前DateTime值是否属于TimeZoneInfo.Local属性返回的本地时区的夏令时时间范围.

显然我有偏见,但我建议使用我的Noda Time项目 - 很可能使用a ZonedDateTime.您可以调用GetZoneInterval以获取ZoneIntervalfor ZonedDateTime,然后用于ZoneInterval.Savings检查当前偏移量是否包含夏令时组件:

bool daylight = zonedDateTime.GetZoneInterval().Savings != Offset.Zero;
Run Code Online (Sandbox Code Playgroud)

这有点啰嗦......我添加了一个功能请求,考虑添加一个IsDaylightSavingTime()方法ZonedDateTime......