我有一种情况,我希望将DateTime
转换为Instant
。我相信DateTime
的{{1}}将是Kind
。
鉴于Local
位于名为DateTime
的变量中,我在库中找到的最接近的是:
time
这似乎是合理的,但我想确定这是完全可靠的,并且没有数据丢失或损坏的风险。我不确定这是否是进行转换的最佳方式,或者是否有更可靠的方法。
我查看了NodaTime的BCL Conversions页面,并说明了以下有关此方案的内容:
请注意,
Instant.FromDateTimeUtc(time.ToUniversalTime())
没有DateTime
的转换 - 这实际上适用于系统默认时区,您通常应明确开始使用。
答案 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
。如果不是,我相信结果是不正确的。