有没有办法将 .Net TimeZoneInfo 转换为 Java ZonedDateTime?
Is there a way to convert from .Net TimeZoneInfo to Java ZonedDateTime?
这是 的后续。我正在构建一个 RESTful 服务器(在 C# 中,但核心引擎是 Java(通过 IKVM))。我们正在用 C# Java 等编写客户端
因此对于 C# 客户端的特定情况,如果他们想要服务器端的 ZonedDateTime,我需要传递类似于 "2018-10-21T08:11:55-06:00[America/Denver]"。对于这种情况,我认为我应该让他们传给我一个 (DateTime, TimeZoneInfo) 并从中构建字符串。
为此,我需要从 TimeZoneInfo 的设置中获取 Java“America/Denver”。有什么办法可以得到这种转化。
据我了解,没有用于唯一标识时区的 ISO 或其他广泛使用的设置。
"America/Denver" 是该时区的 IANA 名称。 Time Zone Database (tzdb) 包含这些名称及其规则(可以随时间变化)。 NodaTime 使用 tzdb 数据来执行其逻辑。
您可以使用 TimeZoneConverter 包将 TimeZoneInfo
转换为 tzdb 时区 ID。
你问了几个与此相关的问题,我想在这里为你整理一些。
野田时代一路走下去
如果可行,您应该让消费者给您递一份 ZonedDateTime
。它是一个单一值,包含基于 Java 的核心引擎所需的所有信息,这正是您所要求的 ()。使用已在域中验证的单个值(与组成部分的自定义容器相反)将容易出错的活动推迟给消费者,他们比您更适合解决它们并且必须在致电您的客户之前完成。这样您就不必为与您无关的事情相关的任何错误或错误负责。
假设您有一个 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 类型,那没关系。接收 DateTimeOffset
和 TimeZoneInfo
也可以。您可以在您的客户端中将它们转换为 ZonedDateTime
,无需太多仪式。
// Given: DateTimeOffset dateTimeOffset, TimeZoneInfo timeZoneInfo
DateTimeZone dateTimeZone = DateTimeZoneProviders.Tzdb[TZConvert.WindowsToIana(timeZoneInfo.Id)];
ZonedDateTime zonedDateTime = OffsetDateTime.FromDateTimeOffset(dateTimeOffset).InZone(dateTimeZone);
这样做的潜在问题是集体输入 尚未 在域中得到验证。 可以传递的偏移量对于所提供的时区来说是不正确的。准备好添加验证或 try/catch,这样您就可以用非常清晰的语言告诉消费者他们做错了什么。
接受暧昧的时光
您 可以 接受 DateTime
但您将被迫对您 and/or 消费者可能无法接受的模棱两可的时间做出假设。然后你要对与你的 API 的功能无关的逻辑负责。
为了完整起见,我将其包含在此处,但这不是任何形式的背书。
// Given: DateTime dateTime, TimeZoneInfo timeZoneInfo
DateTimeZone dateTimeZone = DateTimeZoneProviders.Tzdb[TZConvert.WindowsToIana(timeZoneInfo.Id)];
ZonedDateTime zonedDateTime = LocalDateTime.FromDateTime(dateTime).InZoneLeniently(dateTimeZone);
InZoneLeniently
是那里的大红旗。遇到模棱两可的时候,它会“照办”,不一定对。请记住,“只是”是一个 4 个字母的单词。
这是
因此对于 C# 客户端的特定情况,如果他们想要服务器端的 ZonedDateTime,我需要传递类似于 "2018-10-21T08:11:55-06:00[America/Denver]"。对于这种情况,我认为我应该让他们传给我一个 (DateTime, TimeZoneInfo) 并从中构建字符串。
为此,我需要从 TimeZoneInfo 的设置中获取 Java“America/Denver”。有什么办法可以得到这种转化。
据我了解,没有用于唯一标识时区的 ISO 或其他广泛使用的设置。
"America/Denver" 是该时区的 IANA 名称。 Time Zone Database (tzdb) 包含这些名称及其规则(可以随时间变化)。 NodaTime 使用 tzdb 数据来执行其逻辑。
您可以使用 TimeZoneConverter 包将 TimeZoneInfo
转换为 tzdb 时区 ID。
你问了几个与此相关的问题,我想在这里为你整理一些。
野田时代一路走下去
如果可行,您应该让消费者给您递一份 ZonedDateTime
。它是一个单一值,包含基于 Java 的核心引擎所需的所有信息,这正是您所要求的 (
假设您有一个 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 类型,那没关系。接收 DateTimeOffset
和 TimeZoneInfo
也可以。您可以在您的客户端中将它们转换为 ZonedDateTime
,无需太多仪式。
// Given: DateTimeOffset dateTimeOffset, TimeZoneInfo timeZoneInfo
DateTimeZone dateTimeZone = DateTimeZoneProviders.Tzdb[TZConvert.WindowsToIana(timeZoneInfo.Id)];
ZonedDateTime zonedDateTime = OffsetDateTime.FromDateTimeOffset(dateTimeOffset).InZone(dateTimeZone);
这样做的潜在问题是集体输入 尚未 在域中得到验证。
接受暧昧的时光
您 可以 接受 DateTime
但您将被迫对您 and/or 消费者可能无法接受的模棱两可的时间做出假设。然后你要对与你的 API 的功能无关的逻辑负责。
为了完整起见,我将其包含在此处,但这不是任何形式的背书。
// Given: DateTime dateTime, TimeZoneInfo timeZoneInfo
DateTimeZone dateTimeZone = DateTimeZoneProviders.Tzdb[TZConvert.WindowsToIana(timeZoneInfo.Id)];
ZonedDateTime zonedDateTime = LocalDateTime.FromDateTime(dateTime).InZoneLeniently(dateTimeZone);
InZoneLeniently
是那里的大红旗。遇到模棱两可的时候,它会“照办”,不一定对。请记住,“只是”是一个 4 个字母的单词。