有没有一种方法可以将.Net TimeZoneInfo转换为Java ZonedDateTime?

时间:2020-07-11 21:44:23

标签: c# datetime timezone zoneddatetime

这是this question的后续版本。我正在构建RESTful服务器(在C#中,但核心引擎是Java(通过IKVM))。我们正在用C#Java等编写客户端。

因此对于C#客户端的特定情况,如果他们希望在服务器端使用ZonedDateTime,则需要传递类似于“ 2018-10-21T08:11:55-06:00 [America / Denver] ”。对于这种情况,我认为我应该让他们给我传递一个(DateTime,TimeZoneInfo)并从中构建字符串。

为此,我需要从TimeZoneInfo的设置中获取Java“ America / Denver”。有什么办法可以实现这种转换。

据我了解,没有用于唯一标识时区的ISO或其他广泛使用的设置。

1 个答案:

答案 0 :(得分:1)

“美国/丹佛”是该时区的IANA名称。 Time Zone Database (tzdb)包含这些名称及其规则(可以随时间更改)。 NodaTime使用tzdb数据执行其逻辑。

您可以使用TimeZoneConverter包将TimeZoneInfo转换为tzdb时区ID。

您已经问了一些与此相关的问题,我想在这里为您整理一些问题。

NodaTime一直下降

如果可行的话,您应该让消费者将ZonedDateTime传递给您。它是一个单一值,包含基于Java的核心引擎所需的所有信息,而这正是您要的(here)。使用已经在域中验证的单个值(而不是组成部分的自定义容器),将错误的活动推迟给消费者,与您相比,消费者更适合于解决这些问题并必须先致电给客户。这样一来,您就不必为与您无关的某些错误或错误负责。

假设您有一个ZonedDateTime实例,现在只需要一个自定义模式即可为您提供Java端期望的格式的字符串。

ZonedDateTimePattern customPattern = ZonedDateTimePattern.Create(
    "uuuu'-'MM'-'dd'T'HH':'mm':'sso<Z-HH':'mm>'['z']'",
    CultureInfo.InvariantCulture,
    mapping => mapping.LocalDateTime.InZoneLeniently(mapping.Zone),
    DateTimeZoneProviders.Tzdb,
    default);

根据您之前的问题,看来您需要UTC的文字“ Z”而不是“ +00:00”。 “ Z-HH':'mm”子模式可以做到这一点。如果需要其他功能,请查看Offset patterns文档。

现在,您可以使用customPattern创建需要发送的字符串。

string formatted = customPattern.Format(zonedDateTime);

如有必要,可以使用相同的模式将这样的字符串解析回ZonedDateTime

仅在内部使用NodaTime

如果您不能期望使用者使用NodaTime类型,那就可以了。接收DateTimeOffsetTimeZoneInfo也可以。您可以在没有太多仪式的情况下将它们转换为ZonedDateTime

// Given: DateTimeOffset dateTimeOffset, TimeZoneInfo timeZoneInfo

DateTimeZone dateTimeZone = DateTimeZoneProviders.Tzdb[TZConvert.WindowsToIana(timeZoneInfo.Id)];

ZonedDateTime zonedDateTime = OffsetDateTime.FromDateTimeOffset(dateTimeOffset).InZone(dateTimeZone);

与此相关的潜在问题是,尚未在域中验证集体输入 Matt Johnson-Pint pointed out in his answer可能会传递一个偏移量,该偏移量对于所提供的时区不正确。准备添加验证或尝试/捕获,以便您可以以非常清晰的语言告诉消费者他们做错了什么。

接受模棱两可的时间

可以接受DateTime,但是您将被迫对可能导致您和/或消费者无法接受的模糊时间做出假设。然后,您将负责与API功能无关的逻辑。

出于完整性考虑,我将其包括在这里,但这并不是任何形式的认可。

// Given: DateTime dateTime, TimeZoneInfo timeZoneInfo

DateTimeZone dateTimeZone = DateTimeZoneProviders.Tzdb[TZConvert.WindowsToIana(timeZoneInfo.Id)];

ZonedDateTime zonedDateTime = LocalDateTime.FromDateTime(dateTime).InZoneLeniently(dateTimeZone);

InZoneLeniently是那里的大红旗。当遇到不明确的时间时,它将“只是做”,这可能是不正确的。请记住,“ just”是4个字母的单词。