我已经切换到threeten来处理日期和时间,但我仍然有一个使用joda将带时区的时间戳写入数据库的第三方工具,我需要将格式从一个转换为另一个。最好的方法是什么?
作为解决办法,我尝试了DateTime.parse(zdt.toString),但它失败了,因为joda不喜欢这种时区格式。
无效格式:“2015-01-25T23:35:07.684Z[Europe/London]”在“[Europe / London]”处存在格式问题。
请注意,使用DateTimeZone.forID(...)不是安全的,因为通常ZoneOffset.UTC具有ID"Z",无法被DateTimeZone识别,可能会抛出DateTimeParseException异常。
为了将ZonedDateTime转换为DateTime,我建议采用以下方式:
return new DateTime(
zonedDateTime.toInstant().toEpochMilli(),
DateTimeZone.forTimeZone(TimeZone.getTimeZone(zonedDateTime.getZone())));
ZonedDateTime zdt =
ZonedDateTime.of(
2015, 1, 25, 23, 35, 7, 684000000,
ZoneId.of("Europe/London"));
System.out.println(zdt); // 2015-01-25T23:35:07.684Z[Europe/London]
System.out.println(zdt.getZone().getId()); // Europe/London
System.out.println(zdt.toInstant().toEpochMilli()); // 1422228907684
DateTimeZone london = DateTimeZone.forID(zdt.getZone().getId());
DateTime dt = new DateTime(zdt.toInstant().toEpochMilli(), london);
System.out.println(dt); // 2015-01-25T23:35:07.684Z
如果区域 id 转换可能因任何不支持或无法识别的 id 而崩溃,我建议
通常这比只是静默地回退到任意 tz 偏移更好。
TimeZone.getTimeZone(...)
的人,请三思而后行。对于不支持的id切换回UTC可能比崩溃更糟糕。 - Meno Hochschildfun ZonedDateTime.toDateTime(): DateTime =
DateTime(this.toInstant().toEpochMilli(),
DateTimeZone.forTimeZone(TimeZone.getTimeZone(this.zone)))
TimeZone.getTimeZone(zoneId)
对于表示UTC的Z文字面值可能比Joda-Time更有效,但这样的表达式对于其他ID可能会无声失败,而不是抛出异常而是任意回退到UTC(这甚至更糟),请参见API文档:“返回:指定的TimeZone,或者如果无法理解给定的ID,则为GMT区域”,我的回答仅涉及OP在问题中提出的特殊示例,但我不保证它适用于每个时区标识符。 - Meno HochschildTimeZone.getTimeZone(zoneId)
切换到 UTC - 没有任何例外。Joda-Time 和 JDK 的基础时区存储库知道不同的有效 id 集,而这个事实不能被任何“聪明”的转换代码所修复。 - Meno Hochschild