tl;博士
LocalDateTime
.parse(
"2021-04-26 08:28:56"
.replace( " " , "T" )
)
.atZone(
ZoneId.of( "America/New_York" )
)
.toInstant()
.toString()
.replace( "T" , " " )
.replace( "Z" , "" )
看到这个code run live at IdeOne.com。
2021-04-26 12:28:56
您的预期结果不正确。如果EST 是指America/New_York 之类的时区,那么此时该时区比UTC 晚四个小时。因此,要从上午 8 点开始,您必须添加 4 小时,才能获得中午 12 点,而不是前一天预期的上午 10 点。
详情
将您的输入解析为 LocalDateTime,因为它缺少时区指示符或与 UTC 的偏移量。我们通过将中间的空格替换为T,将您的输入转换为符合 ISO 8601。
LocalDateTime 不代表一个时刻,不是时间轴上的一个点。此类仅表示日期和时间。如果没有时区的上下文或与 UTC 的偏移量,我们不知道那个时间点在哪个时钟。
您声称知道此字符串旨在表示日期时间,如 EST 中所示。不幸的是,EST 不是real time zone name。您是指北美东海岸时间,例如America/New_York?如果是这样,您的预期输出不正确。
如果是这样,请获取该时区的ZoneId。应用时区以获得ZonedDateTime。现在我们已经定义了一个时刻,时间线上的一个特定点。
您希望在 UTC 中看到相同的时刻。适应 UTC 的一种简单方法是从 ZonedDateTime 对象中简单地提取 Instant。根据定义,Instant 对象始终采用 UTC。
您想要的输出类似于Instant 的toString 方法中默认使用的标准ISO 8601 格式。只需从日期和时间之间删除T,并在末尾删除代表零时分秒偏移量的Z。顺便说一句,我建议不要删除Z 以使含义一目了然。删除 Z 会引入歧义。
String input = "2021-04-26 08:28:56".replace( " " , "T" ) ;
LocalDateTime ldt = LocalDateTime.parse( input ) ;
ZoneId z = ZoneId.of( "America/New_York" ) ;
ZonedDateTime zdt = ldt.atZone( z ) ;
Instant instant = zdt.toInstant() ; // Adjust to UTC by extracting an `Instant` object. `Instant` is always in UTC, by definition.
String output = instant.toString().replace( "T" , " " ).replace( "Z" , "" ) ;
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date、Calendar 和 SimpleDateFormat。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。
您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。 Hibernate 5 & JPA 2.2 支持 java.time。
从哪里获取 java.time 类?