你错过了一个关键点:ADateTime
的种类Local
并不总是完全代表一个独特的时刻。这就是为什么没有直接映射到Instant
.
在回退 DST 转换期间,本地DateTime
可以代表两个可能的时刻中的任何一个。如果您要将其转换为Instant
,那么您需要在某个地方决定您应该选择哪个时刻。
在您给出的答案中,我假设您timezone
从以下其中一项获得:
var timezone = DateTimeZoneProviders.Tzdb.GetSystemDefault();
或者
var timezone = DateTimeZoneProviders.Bcl.GetSystemDefault();
任何一个都可以完成这项任务。然后你给出的代码:
var localTime = LocalDateTime.FromDateTime(time);
var zonedTime = localTime.InZoneStrictly(timeZone);
return zonedTime.ToInstant();
这是完全正确的,但是由于您使用InZoneStrictly
了 ,您将AmbiguousTimeException
在回退过渡期间得到一个。
您可以使用 来避免这种情况InZoneLeniently
,它将选择两种可能性中的后者(通常是“标准”时间)。但更重要的是,您可以改为使用InZone
并提供标准或自定义解析器来更精确地控制行为。
关于您的原始方法:
Instant.FromDateTimeUtc(time.ToUniversalTime())
这没关系,不会损坏您的数据,但要了解它将依赖 BCL 的本地到通用转换的行为。它与 相同InZoneLeniently
,因为模棱两可的值将被视为“标准”时间。
这是 NodaTime 如何提供更精确的 API 的一个很好的例子。您不必做出假设,而是有机会具体化并提供自定义行为。最后你得到了同样的结果,但它把这个问题带到了前台而不是隐藏它。