使用 Noda Time 解析不明确的日期时间
Parsing ambiguous datetime with Noda Time
我用的是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
消息:
The local date/time is ambiguous in the target time zone
据我了解,问题是由于夏令时,这个特定时间可能会出现两次。在 02:00,时钟拨回一小时 01:00。 NodaTime 不知道字符串指的是 01:00 中的哪个 "version",因此会抛出异常。
对我来说,解析结果是哪个版本的时间并不重要,我只是想避免异常,并获得尽可能接近实际的日期。少一小时或多一小时都可以。最好的方法是什么?
我能想到的唯一办法就是拆分字符串,逐个解析,然后加上一个小时,但感觉完全不对。有更好的解决方案吗?
每个 https://github.com/nodatime/nodatime/blob/2.2.x/src/NodaTime.Web/Markdown/2.0.x/zoneddatetime-patterns.md(或生成到的任何地方)
If the pattern does not contain an offset specifier ("o<...>") the local date and time represented by the text is interpreted according to the ZoneLocalMappingResolver associated with the pattern. A new pattern can be created from an existing one, just with a different resolver, using the WithResolver method. If the resolver throws a SkippedTimeException or AmbiguousTimeException, these are converted into UnparsableValueException results. Note that a pattern without an offset specifier will always lead to potential data loss when used with time zones which aren't a single fixed offset, due to the normal issues of time zone transitions (typically for daylight saving time).
建议
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);
ZonedDateTimePattern
class有个Resolver
属性。解析器的作用是执行分区 date/times 的映射并处理跳过和不明确的时间 - 无法映射的时间,因为它们将发生 never(跳过)或 不止一次(不明确)由于夏令时。
ZonedDateTimePattern source code shows that the default resolver is Resolvers.StrictResolver
。正如您已经发现的那样,如果映射不明确或被跳过,此解析器将抛出异常。
各种resolvers are available. The best match for your "just give me a valid date and time please!" requirement is likely to be the LenientResolver
,其行为如下:
Ambiguity is handled by returning the earlier occurrence, and skipped
times are shifted forward by the duration of the gap.
我们可以通过在 ZonedDateTimePattern
实例上附加对 WithResolver()
的调用来指定此解析器(Resolver
属性 没有 public 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)
我用的是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
消息:
The local date/time is ambiguous in the target time zone
据我了解,问题是由于夏令时,这个特定时间可能会出现两次。在 02:00,时钟拨回一小时 01:00。 NodaTime 不知道字符串指的是 01:00 中的哪个 "version",因此会抛出异常。
对我来说,解析结果是哪个版本的时间并不重要,我只是想避免异常,并获得尽可能接近实际的日期。少一小时或多一小时都可以。最好的方法是什么?
我能想到的唯一办法就是拆分字符串,逐个解析,然后加上一个小时,但感觉完全不对。有更好的解决方案吗?
每个 https://github.com/nodatime/nodatime/blob/2.2.x/src/NodaTime.Web/Markdown/2.0.x/zoneddatetime-patterns.md(或生成到的任何地方)
If the pattern does not contain an offset specifier ("o<...>") the local date and time represented by the text is interpreted according to the ZoneLocalMappingResolver associated with the pattern. A new pattern can be created from an existing one, just with a different resolver, using the WithResolver method. If the resolver throws a SkippedTimeException or AmbiguousTimeException, these are converted into UnparsableValueException results. Note that a pattern without an offset specifier will always lead to potential data loss when used with time zones which aren't a single fixed offset, due to the normal issues of time zone transitions (typically for daylight saving time).
建议
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);
ZonedDateTimePattern
class有个Resolver
属性。解析器的作用是执行分区 date/times 的映射并处理跳过和不明确的时间 - 无法映射的时间,因为它们将发生 never(跳过)或 不止一次(不明确)由于夏令时。
ZonedDateTimePattern source code shows that the default resolver is Resolvers.StrictResolver
。正如您已经发现的那样,如果映射不明确或被跳过,此解析器将抛出异常。
各种resolvers are available. The best match for your "just give me a valid date and time please!" requirement is likely to be the LenientResolver
,其行为如下:
Ambiguity is handled by returning the earlier occurrence, and skipped times are shifted forward by the duration of the gap.
我们可以通过在 ZonedDateTimePattern
实例上附加对 WithResolver()
的调用来指定此解析器(Resolver
属性 没有 public 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)