c# - 有没有办法将 .Net TimeZoneInfo 转换为 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 名称。时区数据库 (tzdb)包含这些名称及其规则(可能随时间而变化)。NodaTime 使用 tzdb 数据来执行其逻辑。
您可以使用TimeZoneConverter包将 a 转换TimeZoneInfo
为 tzdb 时区 ID。
你已经问了一些与此相关的问题,我想在这里为你拼凑一些。
NodaTime 一路向下
如果这样做是可行的,你应该让消费者给你一个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);
根据您之前的问题,您似乎需要一个文字“ Z
”来表示 UTC 而不是“ +00:00
”。" Z-HH':'mm
" 子模式就是这样做的。如果您需要不同的东西,请查看偏移模式文档。
现在您可以使用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);
这样做的潜在问题是集体输入尚未在域中得到验证。 Matt Johnson-Pint 在他的回答中指出,可以传递一个偏移量,这对于提供的时区是不正确的。准备好添加验证或尝试/捕获,这样您就可以用非常清晰的语言告诉消费者他们做错了什么。
接受模棱两可的时代
您可以接受,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 个字母的单词。
推荐阅读
- php - 如何从它的孩子那里得到父母的名字?
- windows - 用于 Windows 的 ipref3 dll
- java - 为什么当我转换包含变量的对象时它不显示变量的值?
- ruby-on-rails - 在 Rails 5 中反序列化没有 gems 或 PostgreSQL 的 JSON
- linux - 你如何改变一个命令在linux终端中的作用?
- java - 与 Apache Phoenix 相关的错误
- dart - Flutter - JSON 和时间序列图表
- java - Spring Scheduling - 每个月晚上 11 点结束的 Cron 表达式?
- powerbi - Power BI服务在没有网关的情况下连接mysql
- sql - 如何在超过 2000 万行的 sql 中加快查询速度