用Noda Time解析模棱两可的日期时间

问题描述 投票:5回答:2

我使用Noda Time,并具有以下代码:

var pattern = ZonedDateTimePattern.CreateWithInvariantCulture(
    "yyyy-MM-dd HH:mm:ss z", 
    DateTimeZoneProviders.Tzdb);

var parsed = pattern.Parse("2017-11-05 01:00:00 America/Los_Angeles");
Console.WriteLine(parsed.Value);

这导致UnparsableValueException消息:

目标时区的本地日期/时间不明确

据我所知,问题是由于夏令时,这个特定时间可能会发生两次。在02:00,时钟返回1小时到01:00。 NodaTime不知道字符串引用的01:00的哪个“版本”,并且因此引发了异常。

对我而言,解析导致的时间版本并不重要,我只想避免异常,并获得尽可能接近现实的日期。少了一个小时就可以了。最好的方法是什么?

我能想到的唯一方法是分割字符串并单独解析部分,然后再添加一个小时,但这感觉完全错误。有更好的解决方案吗?

c# .net nodatime
2个回答
4
投票

ZonedDateTimePattern类有Resolver属性。解析器的作用是执行映射到分区日期/时间并处理跳过和模糊的时间 - 由于DST而无法映射的时间,因为它们将永远不会(跳过)或不止一次(模糊)。

ZonedDateTimePattern source code显示默认的解析器是Resolvers.StrictResolver。正如您已经发现的,如果映射不明确或被跳过,则此解析程序会抛出异常。

有各种各样的resolvers可供选择。最适合您的“请给我一个有效的日期和时间!”要求可能是LenientResolver,其行为如下:

通过返回较早的出现来处理歧义,并且跳过的时间向前移动间隙的持续时间。

我们可以通过在WithResolver()实例上附加对ZonedDateTimePattern的调用来指定此解析器(Resolver属性没有公共setter):

var pattern = ZonedDateTimePattern.CreateWithInvariantCulture(
    "yyyy-MM-dd HH:mm:ss z",
    DateTimeZoneProviders.Tzdb).WithResolver(Resolvers.LenientResolver);

var parsed = pattern.Parse("2017-11-05 01:00:00 America/Los_Angeles");
Console.WriteLine(parsed.Value);

输出:

2017-11-05T01:00:00 America / Los_Angeles(-07)


3
投票

每个https://github.com/nodatime/nodatime/blob/2.2.x/src/NodaTime.Web/Markdown/2.0.x/zoneddatetime-patterns.md(或生成的任何地方)

如果模式不包含偏移说明符(“o <...>”),则根据与模式关联的ZoneLocalMappingResolver解释文本表示的本地日期和时间。可以使用WithResolver方法从现有模式创建新模式,只需使用不同的解析程序。如果解析器抛出SkippedTimeException或AmbiguousTimeException,则会将这些转换为UnparsableValueException结果。请注意,由于时区转换的正常问题(通常用于夏令时),没有偏移说明符的模式在与不是单个固定偏移的时区一起使用时将始终导致潜在的数据丢失。

提示

var lenientpattern = ZonedDateTimePattern
                    .CreateWithInvariantCulture("yyyy-MM-dd HH:mm:ss z", DateTimeZoneProviders.Tzdb)
                    .WithResolver(Resolvers.LenientResolver); //or any of the other resolvers
var parsed = lenientpattern.Parse("2017-11-05 01:00:00 America/Los_Angeles");
Console.WriteLine(parsed.Value);
© www.soinside.com 2019 - 2024. All rights reserved.