ZonedDateTime 未通过 DateTimeFormatter

问题描述

我有一个时区为 EST 的日期输入。

我将其解析为 zoneddatetime,但在格式化时,它显示GMT-04:00,而不是我期望的 EST

为什么会发生这种情况 - 我可以让它显示我期望的时区吗?

示例

final String dateString = "16/07/2017 19:28:33 EST";
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss z");

System.out.println(messageformat.format("Input - {0}",dateString));
System.out.println(messageformat.format("Parsed - {0}",formatter.format(zoneddatetime.parse(dateString,formatter))));

输出

Input - 16/07/2017 19:28:33 EST
Parsed - 16/07/2017 19:28:33 GMT-04:00

我的时区是 GMT。采用 OpenJDK 14.0.2.12,en_GB 语言环境。

就上下文而言,我试图在 Amazon Corretto 11 的最新版本中更好地理解此问题 - https://github.com/corretto/corretto-11/issues/147

解决方法

tl;博士

你说:

它显示为 GMT-04:00,而不是我预期的 EST。

此类详细信息取决于 Locale.UK 是否有效。

  • 16/07/2017 19:28:33 GMT-04:00Locale.UK
  • 16/07/2017 19:28:33 EDTLocale.US
  • 16/07/2017 19:28:33 HAELocale.CANADA_FRENCH

➥ 对于文本日期时间数据交换,(a) 坚持使用 ISO 8601 标准格式,并且 (b) 尽可能使用零偏移量。这样做没有意义Issue # 147

详情

顺便说一句,尽量避免使用 2-4 个字母的伪区域解析日期时间文本,例如 ESTEDTIST,CST。这些是非标准的、非唯一的(!),试图暗示时区以及 Daylight Saving Time (DST) 是否有效。

仅使用 real time zones,格式为 Continent/Region,例如 Europe/London


你说:

而不是我期望的 EST

夏令时 (DST) 在 America/New_York 而非 Standard Time 时区的该日期时间生效。所以你应该期待 EDT 而不是 EST


我建议您不要通过在 println 语句中嵌入调用来使问题复杂化。

您应该指定 Locale 而不是隐式依赖 JVM 的当前默认语言环境,该语言环境可以在运行时随时更改。所以请注意我如何将 .withLocale( locale ) 附加到 DateTimeFormatter 对象的形成中。我指定了 Locale.UK,因为您在评论中提到了 en_GB

那么让我们将您的代码修改为:

final Locale locale = Locale.US ;  // Locale.UK versus Locale.US yield different outputs.
final String input = "16/07/2017 19:28:33 EST";
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "dd/MM/yyyy HH:mm:ss z" ).withLocale( locale ) ;
final ZonedDateTime zdt = ZonedDateTime.parse( input,formatter ) ;
final String zdtToString = zdt.toString() ;
final String zdtFormatted = zdt.format( formatter ) ;

……和:

// Dump to console.
System.out.println( "input: " + input ) ;
System.out.println( "zdt: " + zdt ) ;
System.out.println( "zdtToString: " + zdtToString ) ;
System.out.println( "zdtFormatted: " + zdtFormatted ) ;

请参阅有关 Java 12 的 code run live at IdeOne.com

input: 16/07/2017 19:28:33 EST
zdt: 2017-07-16T19:28:33-04:00[America/New_York]
zdtToString: 2017-07-16T19:28:33-04:00[America/New_York]
zdtFormatted: 16/07/2017 19:28:33 GMT-04:00

如果我们将该区域设置从 Locale.UK 更改为 Locale.US,我们会得到不同的结果。

zdtFormatted: 16/07/2017 19:28:33 EDT
,

tl;博士

切勿使用没有 Locale 的日期时间解析器/格式化程序类型(类)。

import java.text.MessageFormat;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

class Main {
    public static void main(String[] args) {
        final String dateString = "16/07/2017 19:28:33 EST";
        final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss z",Locale.ENGLISH);

        System.out.println(MessageFormat.format("Input - {0}",dateString));
        System.out.println(
                MessageFormat.format("Parsed - {0}",formatter.format(ZonedDateTime.parse(dateString,formatter))));
    }
}

输出:

Input - 16/07/2017 19:28:33 EST
Parsed - 16/07/2017 19:28:33 EDT

ONLINE DEMO

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...