C#使用NodaTime时IANA时区偏移计算结果不匹配问题
偏移不匹配原因
America/New_York(美国东部时区)实行夏令时规则,全年偏移值不固定:- 夏令时时段(每年3月第二个周日至11月第一个周日):偏移为
UTC-4(EDT) - 冬令时(标准时间)时段(每年其余时间):偏移为
UTC-5(EST)
- 夏令时时段(每年3月第二个周日至11月第一个周日):偏移为
- 你传入的待转换日期为2016年12月10日,该时间点在2016年11月6日夏令时结束之后,属于冬令时时段,代码返回的
-05偏移结果是准确的。 - 谷歌查询返回的
-04是你查询时刻纽约的生效偏移(查询时纽约正处于夏令时时段),由于你没有指定查询2016年12月的历史偏移,该结果和目标日期的偏移没有参考性。
代码潜在问题与修正
你当前的代码在本次场景下返回结果正确,但存在隐性缺陷:LocalDateTime.FromDateTime(dt)会直接读取dt的时间刻度,完全忽略dt的Kind属性,若传入的dt是UTC时间或其他时区的本地时间,会出现时间映射错误。根据业务需求选择对应修正方案:
- 需求为「传入的dt本身就是纽约时区的本地时间,需要返回带正确偏移的时间」
增加Kind校验避免隐式错误,代码如下:if (dt.Kind != DateTimeKind.Unspecified) { throw new ArgumentException("传入日期需为无时区标记的时间值", nameof(dt)); } LocalDateTime fromLocal = LocalDateTime.FromDateTime(dt); DateTimeZone fromZone = DateTimeZoneProviders.Tzdb[timeZone]; // InZoneLeniently会自动处理夏令时切换的歧义/无效时间,适配多数业务场景 ZonedDateTime fromZoned = fromLocal.InZoneLeniently(fromZone); return fromZoned.ToDateTimeOffset(); - 需求为「传入UTC时间/其他时区时间,转换为纽约时区对应时间」
不要直接转LocalDateTime,先通过Instant做跨时区转换,以传入UTC时间为例:if (dt.Kind != DateTimeKind.Utc) { throw new ArgumentException("传入日期需为UTC时间", nameof(dt)); } Instant dtInstant = Instant.FromDateTimeUtc(dt); DateTimeZone targetZone = DateTimeZoneProviders.Tzdb[timeZone]; ZonedDateTime targetZoned = dtInstant.InZone(targetZone); return targetZoned.ToDateTimeOffset();
内容的提问来源于stack exchange,提问作者Praveen Patel G
相关产品推荐
相关产品推荐

