这是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或其他广泛使用的设置。
答案 0 :(得分:1)
“美国/丹佛”是该时区的IANA名称。 Time Zone Database (tzdb)包含这些名称及其规则(可以随时间更改)。 NodaTime使用tzdb数据执行其逻辑。
您可以使用TimeZoneConverter包将TimeZoneInfo
转换为tzdb时区ID。
您已经问了一些与此相关的问题,我想在这里为您整理一些问题。
如果可行的话,您应该让消费者将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类型,那就可以了。接收DateTimeOffset
和TimeZoneInfo
也可以。您可以在没有太多仪式的情况下将它们转换为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个字母的单词。