我应该如何将本地DateTime转换为Instant?

时间:2013-10-17 03:40:00

标签: .net nodatime

我有一种情况,我希望将DateTime转换为Instant。我相信DateTime的{​​{1}}将是Kind

鉴于Local位于名为DateTime的变量中,我在库中找到的最接近的是:

time

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

我查看了NodaTime的BCL Conversions页面,并说明了以下有关此方案的内容:

  

请注意,Instant.FromDateTimeUtc(time.ToUniversalTime()) 没有DateTime的转换 - 这实际上适用于系统默认时区,您通常应明确开始使用。

2 个答案:

答案 0 :(得分:17)

您错过了一个关键点:DateTime类型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()) 并提供标准或自定义resolver来更精确地控制行为。

关于你的原始方法:

InZoneLeniently

这没关系,也不会破坏你的数据,但要明白它将依赖于BCL的本地转换行为。它与{{1}}相同,因为模糊值将被视为“标准”时间。

这是NodaTime如何提供更精确的API的一个很好的例子。您没有做出假设,而是有机会具体并提供自定义行为。最后你获得了相同的结果,但它把这个问题带到了前台而不是隐藏它。

答案 1 :(得分:1)

我刚刚意识到我可以将本地时间转换为NodaTime LocalDateTime,然后使用其中一个InZone方法后跟ToInstant将其映射到一个瞬间。这是一个例子,假设timeZone中提供了时区的时区,如果时间无效,您希望抛出错误:

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

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