gpt4 book ai didi

java - 将PST转换为CST和EST无法提供正确的输出

转载 作者:行者123 更新时间:2023-12-01 19:52:29 26 4
gpt4 key购买 nike

我正在尝试为我的应用程序创建适当的转换方法,该方法会将输入作为PST并将其转换为CST或EST,并且还支持夏时制。

这是问题所在。检查下面的代码和输出。我只是将我的PST日期转换为CST和EST并进行打印。但是在输出中CST和EST是相同的。需要相差1小时,但这并不能反映出来。

    System.out.println("CURRENT in PST : " + new Date());
SimpleDateFormat utcDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
utcDateFormat.setTimeZone(TimeZone.getTimeZone("PST"));
System.out.println("convert in PST : " + utcDateFormat.format( new Date()));

utcDateFormat.setTimeZone(TimeZone.getTimeZone("CST"));
System.out.println("convert in CST : " + utcDateFormat.format(new Date()));

utcDateFormat.setTimeZone(TimeZone.getTimeZone("EST"));
System.out.println("convert in EST : " + utcDateFormat.format(new Date()));


输出:

CURRENT in PST : Wed Jun 13 15:14:15 PDT 2018
convert in PST : 2018-06-13T15:14:15Z
convert in CST : 2018-06-13T17:14:15Z
convert in EST : 2018-06-13T17:14:15Z


那么任何人都可以让我知道为什么吗?以及如何在美国所有时区完美地进行此转换。

我使用EST5EDT,它可以工作,但不知道夏时制开始或结束时它是否会支持。
我可以使用JAVA 8。

最佳答案

tl; dr


  如何在美国所有时区完美地进行此转换。


Instant now = Instant.now() ;  // Capture current moment in UTC.
ZonedDateTime zdtLosAngeles = now.atZone( ZoneId.of( "America/Los_Angeles" ) ) ;
ZonedDateTime zdtChicago = now.atZone( ZoneId.of( "America/Chicago" ) ) ;
ZonedDateTime zdtNewYork = now.atZone( ZoneId.of( "America/New_York" ) ) ;
ZonedDateTime zdtGuam = now.atZone( ZoneId.of( "America/Guam" ) ) ;
ZonedDateTime zdtHonolulu = now.atZone( ZoneId.of( "America/Los_Angeles" ) ) ;
ZonedDateTime zdtAnchorage = now.atZone( ZoneId.of( "America/Anchorage" ) ) ;
ZonedDateTime zdtIndianapolis = now.atZone( ZoneId.of( "America/Indiana/Indianapolis" ) ) ;
ZonedDateTime zdtPortOfSpain = now.atZone( ZoneId.of( "America/Port_of_Spain" ) ) ;
ZonedDateTime zdtPhoenix = now.atZone( ZoneId.of( "America/Phoenix" ) ) ;


…依此类推,通过美国的 list of the many time zones

Date是UTC


  “ PST中的CURRENT:” +新的Date()


这是不正确的。该代码的行为与您显然期望的不一样。您可能会得到一个字符串,例如 Wed Jun 13 15:58:37 PDT 2018,否则可能不会。

根据定义, java.util.Date始终为UTC。定义为自UTC 1970年第一时刻的纪元参考以来的毫秒数。您生成的输出字符串可能在西海岸时间,但这仅仅是偶然的。

令人困惑的是,不幸的是, Date::toString方法被设计为动态生成JVM的当前默认时区,同时生成表示该 Date对象值的字符串。如果您的JVM恰好具有某个区域(例如 America/Los_Angeles)的当前默认时区,则您将获得一个带有美国西海岸时间的字符串。但是,如果否则设置默认时区,则您的结果将在运行时发生变化,并且您的“ PST中的电流:”标签将不正确。请记住,JVM的当前默认时区可以在运行时随时通过JVM中任何应用程序的任何线程中的任何代码进行更改。

传统的日期时间类充斥着如此糟糕的设计选择。避免使用这些类。

java.time

现代方法使用java.time类,而不是那些麻烦的旧旧的日期时间类。

Instant替换 java.util.DateInstant类代表 UTC在时间轴上的时刻,分辨率为 nanoseconds(最多九(9)个十进制小数位)。

Instant instant = Instant.now() ;  // Capture the current moment in UTC.


应用 time zoneZoneId)以获得 ZonedDateTime对象。时间轴上的同一时刻,同一点,但通过某个地区的人们使用的挂钟时间进行查看。

continent/region的格式指定 proper time zone name,例如 America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用3-4个字母的伪区域,例如 ESTIST,因为它们不是真实的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "America/Los_Angeles" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;


作为一种快捷方式,可以通过调用 Instant并传递 ZonedDateTime.now来跳过 ZoneId对象。

ZonedDateTime zdt = ZonedDateTime.now( z ) ;



  以及如何在美国所有时区完美地进行此转换。


首先,上面从未讨论过伪区域“ PST”,“ CST”,“ EST”。使用实时区域。

在美国,有三个以上的区域,例如 America/ChicagoAmerica/New_YorkAmerica/Fort_WaynePacific/HonoluluAmerica/Puerto_Rico等。为什么那么多?因为当前和过去的做法各不相同。例如,美国的某些地方选择退出 Daylight Saving Time (DST)的愚蠢行为。各地都有不同的历史,该区域中的 offset-from-UTC被人们在其历史上不同点处改变了。

其次,保持您的时区定义为最新。大多数软件系统使用IANA发布的 tzdata(以前称为Olson数据库)的副本。您的主机操作系统, JVM实现和数据库服务器都可能拥有tzdata的副本,如果您关心的任何区域的规则发生变化,都必须保持tzdata的最新状态。

永远不要忽略区域/偏移


  “ yyyy-MM-dd'T'HH:mm:ss'Z'”


Z周围加上单引号时,您的格式化模式是一个可怕的选择。 Z表示UTC,发音为Zulu。您的单引号会告诉格式化程序忽略该特定字符串,就好像它毫无意义。但这并不是没有意义的,它是有关您选择忽略和丢弃的输入数据的重要信息。

另一件事…该特定格式由 ISO 8601标准定义。解析/生成字符串时,java.time类默认使用这些标准格式。

Instant.parse( "2018-01-23T12:34:56Z" )  // Parse standard ISO 8601 string into a `Instant` object.

instant.toString() // Yields "2018-01-23T12:34:56Z".




关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧 legacy日期时间类,例如 java.util.DateCalendarSimpleDateFormat

现在位于 Joda-Time中的 maintenance mode项目建议迁移到 java.time类。

要了解更多信息,请参见 Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为 JSR 310

您可以直接与数据库交换java.time对象。使用与 JDBC driver或更高版本兼容的 JDBC 4.2。不需要字符串,不需要 java.sql.*类。

在哪里获取java.time类?


Java SE 8Java SE 9Java SE 10和更高版本


内置的
标准Java API的一部分,具有捆绑的实现。
Java 9添加了一些次要功能和修复。

Java SE 6Java SE 7


ThreeTen-Backport中的许多java.time功能都已反向移植到Java 6和7。

Android


更高版本的Android捆绑了java.time类的实现。
对于较早的Android(<26), ThreeTenABP项目改编为 ThreeTen-Backport(如上所述)。请参见 How to use ThreeTenABP…



ThreeTen-Extra项目使用其他类扩展了java.time。该项目是将来可能向java.time添加内容的试验场。您可能会在这里找到一些有用的类,例如 IntervalYearWeekYearQuartermore

关于java - 将PST转换为CST和EST无法提供正确的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50847105/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com