java 8 ZonedDateTime不会打印EST当前时间。我在这做错了什么

问题描述 投票:0回答:2

下面是我必须打印当前EST日期时间的代码,但它在我的时区打印出时间,即亚利桑那时间。我在这段代码中遗漏了什么。谢谢!

public static void main(String args[]) {
    LocalDateTime datetime = LocalDateTime .now();

    ZonedDateTime zdtNewYork = ZonedDateTime.of ( datetime , ZoneId.of ( "America/New_York" ) );
    System.out.println(zdtNewYork.format(DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss.SSS")));
}
java datetime java-8 localdate zoneddatetime
2个回答
2
投票

tl;dr

你捕获了亚利桑那州的日期和时间,然后拍了一个时区来声称(错误地)纽约在那一刻有相同的时间。

因此,当您生成显示这些值的文本时,您会看到在亚利桑那州首次捕获的时间。在任何时候你都没有从亚利桑那州调整到纽约。

LocalDateTime is the wrong class

切勿使用LocalDateTime来跟踪时刻。根据定义,该类不能代表特定时刻,即时间轴上的一个点。它包含日期和时间,但缺少时区或从UTC偏移的上下文。如果我们不知道你是在日本东京,加尔各答印度,巴黎法国还是蒙特利尔魁北克中旬,那么“在今年1月23日中午”告诉我们是没有意义的 - 所有这些都是非常不同的时刻,相隔几小时。

Always specify time zone

为了使用错误的类,您调用了LocalDateTime.now而未指定时区。因此,隐式应用了JVM的当前默认时区。您声称默认值是亚利桑那州的某个时区。所以这将是区域应用。

因此,您捕获了亚利桑那州的日期和时间。但是你丢弃了这个值在亚利桑那州时区的事实,因为你使用了LocalDateTime。丢弃时区是LocalDateTime类的全部要点。有些情况下这很有用,但肯定不适合你的情况。

然后你拿走了亚利桑那州的日期和时间,并声称这是纽约的日期和时间。纽约的实际时间比预先提前了几个小时,所以你告诉了一下。最后,您生成了显示fib的文本。

换句话说,显然你认为这一行:

ZonedDateTime.of ( datetime , ZoneId.of ( "America/New_York" ) )

...从亚利桑那州调整到纽约。但datetime论证不再知道它来自亚利桑那州,因为LocalDateTime没有区域/偏移的概念。没有进行任何调整。

你可以这样想:

LocalDateTime =日期+时间

OffsetDateTime =日期+时间+偏移量

ZonedDateTime =日期+时间+区域

Instant =日期+时间+ UTC

相反,我建议您始终明确指定所需/预期的时区。即使您想要当前的默认时区,也可以通过调用ZoneId.systemDefault明确说明,这样任何阅读代码的程序员都清楚地了解您的意图。让时区或从UTC偏移是可选的是我在java.time中发现的其他惊人的类设计中要改变的少数几件事之一。使所需的区域/偏移量参数有助于教育更多程序员关于日期时间处理。

ZonedDateTime is the right class

要表示通过特定区域(时区)的人使用的挂钟时间看到的时刻,请使用ZonedDateTime

ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;

看到这个code run live at IdeOne.com

zdt.toString():2019-03-04T18:17:08.014-05:00 [America / New_York]

Generate text

我们可以轻松生成您想要的文本。

DateTimeFormatter f = DateTimeFormatter.ofPattern( "MM/dd/uuuu HH:mm:ss.SSS" ) ;
String output = zdt.format( f ) ;

看到这个code run live at IdeOne.com

03/04/2019 18:17:08.014

Adjusting zones

如果您确实想要在区域之间进行调整,请调用ZonedDateTime::withZoneSameInstant方法。

ZonedDateTime zdtPhoenix = ZoneDateTime.now( ZoneId.of( "America/Phoenix" ) ) ;
ZonedDateTime zdtNewYork = zdtPhoenix.withZoneSameInstant( ZoneId.of( "America/New_York" ) ) ;  // Same moment, same point on the timeline, different wall-clock time.

注意短语SameInstant意味着你想要相同的时刻,时间轴上的同一个点,但是你想要通过纽约地区人们使用的挂钟时间看到它。

Time zones

打印出当前的EST日期时间

proper time zone name的格式指定Continent/Region,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用或引用2-4字母缩写,例如ESTIST,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。


0
投票

尝试类似的东西:

 LocalDateTime datetime = LocalDateTime .now(ZoneId.of ( "America/New_York" ));

       System.out.println(datetime.format(DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss.SSS")));
© www.soinside.com 2019 - 2024. All rights reserved.