Java 日期字符串转换为不同格式但具有相同时区

Java date string conversion to different format but with the same timezone

SimpleDateFormat from = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
SimpleDateFormat to = new SimpleDateFormat("MM/dd/yyyy Z");
Date date = from.parse("2017-08-10T00:00:00.000+0000");
String newDateStr = to.format(date);

newDateStr 是 08/09/2017 -0500。我希望 newDataStr 可以与原始日期字符串 (0000) 具有相同的时区 -- 08/10/2017 -0000。我应该怎么做才能实现这一目标?

您可以使用 Java 8 Date API,它提供了一组很好的功能 将日期转换为字符串(包括时区支持)。

一个例子:

    ZonedDateTime dateTime = ZonedDateTime.parse("2017-08-10T00:00:00.000+0000", DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));
    String newDateStr = dateTime.format(DateTimeFormatter.ofPattern("dd/MM/yyyy Z"));

更多信息可以看:

使用 java.time 现代 Java 日期和时间 API:

可以更容易地保留原始字符串的偏移量
    DateTimeFormatter from = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSZ");
    DateTimeFormatter to = DateTimeFormatter.ofPattern("MM/dd/yyyy Z");
    String newDateStr = OffsetDateTime.parse("2017-08-10T00:00:00.000+0000", from)
            .format(to);
    System.out.println(newDateStr);

这会打印

08/10/2017 +0000

这不是建议改用现代 API 的唯一原因。您使用的 Date class 早已过时,尤其是 SimpleDateFormat 以使用起来麻烦而闻名。我总是建议在 2018 年远离那些 classes。现代 API 通常要好得多。并且由于您已经在使用 Java 8,所以绝对没有理由不想要它(对于阅读和使用 Java 6 或 7 的任何人,新的 API 已经也向后移植到那些 Java 版本。

出了什么问题?

老式的 Date 对象只是一个时间点,它不包含时区或偏移量。因此,在您将字符串解析为 Date 之后,偏移信息不再存在。因此,新的格式化程序 Dateto 都无法知道原始字符串中的偏移量或时区。相反,新的格式化程序使用了自己的时区。由于您没有在格式化程序上明确设置时区,因此它的时区是您的 JVM 的时区,这显然是一个时区,在 2017 年 9 月的这些天与 UTC 的偏移量为 -5。

有一些棘手的方法可以解决过时的 classes 问题,但正如我可能已经说过的那样,我不想打扰。

"Call requires API Level 26" 对于 Android

@Ponomarenko Oleh 在评论中写道:

Pay attention: "Call requires API Level 26" for Android.

但是,java.time 在新旧 Android 设备上都能很好地工作。它只需要至少 Java 6.

  • 在 Java 8 和更高版本以及较新的 Android 设备(从 API 级别 26)中,现代 API 是内置的。这也是评论中引用的消息的预期含义。
  • In-Android Java 6 和 7 获得 ThreeTen Backport,现代 classes 的 backport(ThreeTen 用于 JSR 310;请参阅底部的链接) .
  • 在(较旧的)Android 使用 ThreeTen Backport 的 Android 版本。它叫做 ThreeTenABP。并确保使用子包从 org.threeten.bp 导入日期和时间 classes。

链接