我有一种情况,我想将其转换DateTime
为Instant
.我相信DateTime
的Kind
会Local
.
鉴于它DateTime
在一个被调用的变量中time
,我在库中找到的最接近的是:
Instant.FromDateTimeUtc(time.ToUniversalTime())
Run Code Online (Sandbox Code Playgroud)
这似乎是合理的,但我想确定这是完全可靠的,并且没有数据丢失或损坏的风险.我不确定这是否是进行转换的最佳方式,或者是否有更可靠的方法.
我查看了NodaTime的BCL转换页面,它说了以下关于这种情况:
请注意,没有转换到
DateTime
某种类型Local
- 这实际上是系统默认时区,您通常应该明确开始.
Mat*_*int 18
你错过了一个关键点:A DateTime
的类型Local
并不总是完全代表一个独特的时刻.这就是为什么没有直接映射到Instant
.
在后退DST过渡期间,本地DateTime
可以表示两个可能的时刻中的任何一个.如果您要将其转换为a Instant
,那么您需要决定应该选择哪个时刻.
在你给出的答案中,我假设你timezone
从下列之一获得:
var timezone = DateTimeZoneProviders.Tzdb.GetSystemDefault();
Run Code Online (Sandbox Code Playgroud)
要么
var timezone = DateTimeZoneProviders.Bcl.GetSystemDefault();
Run Code Online (Sandbox Code Playgroud)
这个任务都可以.那你给的代码:
var localTime = LocalDateTime.FromDateTime(time);
var zonedTime = localTime.InZoneStrictly(timeZone);
return zonedTime.ToInstant();
Run Code Online (Sandbox Code Playgroud)
这是完全正确的,但自从您使用后InZoneStrictly
,您将AmbiguousTimeException
在后退过渡期间得到一个.
您可以通过使用来避免这种情况InZoneLeniently
,这将选择后两种可能性(通常是"标准"时间).但更重要的是,您可以使用InZone
并提供标准或自定义解析器来更精确地控制行为.
关于你原来的方法:
Instant.FromDateTimeUtc(time.ToUniversalTime())
Run Code Online (Sandbox Code Playgroud)
这没关系,也不会破坏你的数据,但要明白它将依赖于BCL的本地转换行为.它是相同的InZoneLeniently
,因为模糊值将被视为"标准"时间.
这是NodaTime如何提供更精确的API的一个很好的例子.您没有做出假设,而是有机会具体并提供自定义行为.最终,您获得了相同的结果,但它将此问题置于前台而不是隐藏它.