Creating daylight savings-aware DateTime when server set to UTC
我的应用程序托管在Windows Azure上,其中所有服务器都设置为UTC。
我需要知道任何给定的
我用来转换
1 2 3 4 5 6 7 8 9 10 | 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); } |
但是,以下测试在最后一行失败; 转换后的
1 2 3 4 5 6 7 8 9 | [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()); } |
请注意,仅当我的Windows时区设置为(UTC)协调世界时时,这才会失败。 当设定为(UTC)都柏林,爱丁堡,里斯本,伦敦(或任何其他观察夏令时的北半球时区)时,测试通过。 如果在Windows中更改此设置,则需要重新启动Visual Studio才能使更改完全生效。
我错过了什么?
您的最后一行指定该值位于其运行的系统的本地时区中 - 但实际上并非...它使用不同的时区进行转换。
在我看来,基本上
例如,来自
This method determines whether the current DateTime value falls within the daylight saving time range of the local time zone, which is returned by the TimeZoneInfo.Local property.
显然我有偏见,但我建议使用我的Noda Time项目 - 很可能使用
1 | bool daylight = zonedDateTime.GetZoneInterval().Savings != Offset.Zero; |
这有点啰嗦...我添加了一个功能请求,考虑将
-
你缺少的主要是"格林威治标准时间"不是伦敦的
TimeZoneInfo id。那个人实际上属于"(UTC)蒙罗维亚,雷克雅未克"。你想要"GMT标准时间",它映射到"(UTC)都柏林,爱丁堡,里斯本,伦敦"
是的,Windows时区很奇怪。 (至少你不住在法国,这被奇怪地标记为"浪漫标准时间"!)
-
另外,你不应该做这个部分:
1return DateTime.SpecifyKind(userDateTime, DateTimeKind.Local);这将使其他各种代码认为它来自本地机器的时区。保留"未指定"类型。 (或者甚至更好,使用
DateTimeOffset 而不是DateTime ) -
然后,您还需要在
TimeZoneInfo 对象上使用.IsDaylightSavingsTime 方法,而不是.DateTime 对象上的方法。 (对于不同的对象,有两种不同的方法,具有相同的名称,具有不同的行为。哎哟!)
但我完全同意这太复杂,容易出错。只需使用野田时间。你会很高兴的!