【问题标题】:joda DateTimeFormat local timezone formatting questionjoda DateTimeFormat 本地时区格式问题
【发布时间】:2020-06-05 10:34:18
【问题描述】:

我从 org.joda.time.DateTime 开始,我想用与本地时区等效的时区偏移量输出它。这确实是为了方便用户用眼睛查看时间(而不是使用适当的 ISO8601 解析器进行解析)。

val tz = DateTimeZone.getDefault()
val formatter = JacksonJodaDateFormat(DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ssZ").withZone(tz))

我得到的是这样的:

2020-02-01T05:00:00+0000

我想要的是这个:

2020-02-01T00:00:00-0500

它输出的内容对于我的时区实际上是正确的,但我告诉它 .withZone(tz) 并且我(通过调试器)确认 tz 实际上是 America/New_York。

我正在使用 jodatime 2.10.2。我也在这里混合了jackson-format-jodatime,但我在jackson之外尝试了这个,它的行为是一样的。

The Documents 这样说:

When printing, this zone will be used in preference to the zone from the datetime that would otherwise be used. 

否则会打印的是 UTC,但这不是我想要的。

我是否解释了 javadocs 所说的错误?

【问题讨论】:

  • 快速澄清:(1) val 不是 Java 关键字 - 来自 Lombok 吗? (2) 您使用的是什么版本的 Java? (从 Java 8 开始,java.time 优于 Joda-Time - 但迁移可能不是您的选择)。
  • 这是 kotlin,抱歉。我现在在 java 和 kotlin 之间来回走动,甚至都没有考虑过。是的,我使用的是 GraalVM 11,所以我绝对可以改用 java.time,现在大多数人真的认为这是首选(即 joda 被认为已过时)吗?
  • Joda Time 背后的好人在实施java.time 方面发挥了重要作用。他们建议不再使用 Joda Time。请参阅他们的笔记here(“为什么选择 Joda Time”部分)。

标签: jodatime


【解决方案1】:

如果您不反对 Java 答案(也许您的代码 sn-p 是 Kotlin?),以下将根据需要格式化日期字符串,并处理时区变化。

为简单起见,我也没有使用您提到的 Jackson 库。

您显然可以将下面的时区 ID 替换为起点所需的任何内容 - 例如 "UTC"。或者对于系统默认值,使用 Joda-Time:

DateTimeZone defaultZone = DateTimeZone.getDefault();

乔达时间

//
// Using Joda-Time 2.10.2:
//

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormatter;
import org.joda.time.format.DateTimeFormat;

...

String pattern = "yyyy-MM-dd'T'HH:mm:ssZ";
String dateString;

DateTime dtOne = new DateTime("2020-02-21T09:30:45.678+00:00");
DateTimeFormatter fmt = DateTimeFormat.forPattern(pattern);

DateTime dtTwo = dtOne.withZone(DateTimeZone.forID("America/New_York"));
dateString = fmt.print(dtTwo);   // "2020-02-21T04:30:45-0500":

DateTime dtThree = dtOne.withZone(DateTimeZone.forID("Europe/Paris"));
dateString = fmt.print(dtThree); // "2020-02-21T10:30:45+0100"

java.time

对于 Java 8 及更高版本,如果您可以使用 java.time,则 withZoneSameInstant() 会相应地移动日期和时间:

//
// Using java.time (Java 8 onwards):
//

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;

...
String pattern = "yyyy-MM-dd'T'HH:mm:ssZ";
String dateString;

DateTimeFormatter format = DateTimeFormatter.ofPattern(pattern);
LocalDateTime localDateTime = LocalDateTime.parse("2020-02-21T09:30:45.123");
ZonedDateTime zonedDateTimeA = localDateTime.atZone(ZoneId.of("Europe/Paris"));

dateString = zonedDateTimeA.format(format); // "2020-02-21T09:30:45+0100"

ZonedDateTime zonedDateTimeB = zonedDateTimeA
        .withZoneSameInstant(ZoneId.of("America/New_York"));    
dateString = zonedDateTimeB.format(format); // "2020-02-21T03:30:45-0500"

对于使用java.time 的默认时区,它是ZoneId.systemDefault()

另外,this 是一个令人惊叹的概述。

编辑:使用 java.time 而不是 Joda Time

问题的 cmets 中提到了以下内容,但也需要在此答案中说明:

如果可以,您绝对应该在 Joda Time 上使用 java.time

来自乔达时间homepage

请注意,从 Java SE 8 开始,用户被要求迁移到 java.time (JSR-310) - JDK 的核心部分,它取代了这个项目。

来自Stephen Colebourne,Joda Time 的创建者之一:

我使用 java.time 是“受 Joda-Time 启发”的措辞,而不是精确的推导,但是许多概念都是熟悉的。

【讨论】:

    猜你喜欢
    • 2020-07-18
    • 2021-05-22
    • 2013-09-03
    • 2019-02-27
    • 1970-01-01
    • 1970-01-01
    • 2013-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多