14

我有一种情况,我想将 a 转换DateTimeInstant. 我相信会DateTime的。KindLocal

鉴于DateTimeis 在一个名为 的变量中time,我在库中能找到的最接近的是:

Instant.FromDateTimeUtc(time.ToUniversalTime())

这似乎是合理的,但我想确定这是完全可靠的,并且没有数据丢失或损坏的风险。我不确定这是否是进行转换的最佳方式,或者是否有更可靠的方法来实现。

我查看了 NodaTime 的BCL Conversions页面,它对这种情况说了以下内容:

请注意,没有DateTime与 a 的转换Local- 这实际上适用于系统默认时区,您通常应该明确地开始使用它。

4

2 回答 2

25

你错过了一个关键点: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 的一个很好的例子。您不必做出假设,而是有机会具体化并提供自定义行为。最后你得到了同样的结果,但它把这个问题带到了前台而不是隐藏它。

于 2013-10-19T05:19:01.410 回答
1

我刚刚意识到我可以将本地时间转换为 a ,然后使用后面NodaTime LocalDateTime的方法之一将其映射到瞬间。这是一个示例,假设提供了时间的时区,并且您希望在时间无效时引发错误:InZoneToInstanttimeZone

var localTime = LocalDateTime.FromDateTime(time);
var zonedTime = localTime.InZoneStrictly(timeZone);
return zonedTime.ToInstant();

请记住,这是假设time确实是Local. 如果不是,我相信结果是不正确的。

于 2013-10-17T04:26:01.283 回答