“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 个字母的单词。