【问题标题】:ZonedDateTime not displaying Time Zone expected via DateTimeFormatterZonedDateTime 不显示通过 DateTimeFormatter 预期的时区
【发布时间】:2021-06-18 13:41:09
【问题描述】:

我有一个时区为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

我的时区是格林威治标准时间。采用OpenJDK 14.0.2.12,en_GB 语言环境。

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

【问题讨论】:

  • 我认为你可以将.withZone(ZoneId.of("EST")) 添加到DateTimeFormatter.ofPattern(...)
  • 您当前所在的时区是 GMT-4 吗?
  • @daniu no - 我在格林威治标准时间。
  • @Savior AdoptOpenJDK 14.0.2.12,en_GB 语言环境。
  • 我使用Locale.UK 复制。有趣的。它解析为2017-07-16T19:28:33-04:00[America/New_York],这并不奇怪,但随后格式化为16/07/2017 19:28:33 GMT-04:00,坦率地说,这对我来说是这样。

标签: java date java-time zoneddatetime


【解决方案1】:

tl;博士

你说:

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

这些细节取决于Locale.UK 是否有效。

  • 16/07/2017 19:28:33 GMT-04:00 ⇐ Locale.UK
  • 16/07/2017 19:28:33 EDT ⇐ Locale.US
  • 16/07/2017 19:28:33 HAE ⇐ Locale.CANADA_FRENCH

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

详情

顺便说一句,尽量避免使用 2-4 个字母的伪区域来解析日期时间文本,例如 EST、EDT、IST、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

【讨论】:

    【解决方案2】:

    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

    【讨论】:

    • 您的回答让我意识到问题中显示的输入实际上是不正确的,使用EST 而不是EDT。
    猜你喜欢
    • 1970-01-01
    • 2020-08-11
    • 2019-04-11
    • 2018-09-16
    • 2016-05-02
    • 2014-06-29
    • 1970-01-01
    • 1970-01-01
    • 2017-11-06
    相关资源
    最近更新 更多