如何在 Java8+ 中将 UTC 转换为 EST java.util.date?

How to convert UTC to EST java.util.date in Java8+?

下面是我的代码,可将 UTC 转换为 EST。但是,如何将 ZonedDateTime 从下面的代码连同这种格式 (yyyy-MM-dd'T'HH:mm:ss) 转换为 java.util.Date?

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
String f = "yyyy-MM-dd'T'HH:mm:ss";
String timestamp = "2022-03-01T16:29:03"; //sample input

TemporalAccessor temporalAccessor = formatter.parse(timestamp);
LocalDateTime localDateTime = LocalDateTime.from(temporalAccessor);
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, ZoneId.systemDefault());
Instant result = Instant.from(zonedDateTime);
ZonedDateTime nyTime = result.atZone(ZoneId.of("Canada/Eastern"));
DateTimeFormatter format = DateTimeFormatter.ofPattern(f);
System.out.println("Date EST : " + format.format(nyTime));

一旦 ZonedDateTime 处于正确的时区,将其转换为 Instant,然后使用 class 日期的方法 public static Date from(Instant instant)

Instant instant = Instant.from(zonedDateTime);
Date date = Date.from(instant);

但是,如果可以,请避免使用已过时(双关语意)包 java.time 的日期 class 以及 class 等 ZonedDateTimeInstant 和其他人应该使用

您发表评论:

I need to populate this in DB column. So I need to convert a string which is in UTC to EST then converting ZonedDateTime back to java.util.Date in this format (yyyy-MM-dd'T'HH:mm:ss)

永远不要使用 Date class。仅使用 java.time classes。 JDBC 4.2 及更高版本支持 java.time 与数据库交换 date-time 值。

  • 对于类似于 SQL-standard 类型 TIMESTAMP WITHOUT TIME ZONE 的列,使用 java.time.LocalDateTime.
  • 对于类似于 SQL-standard 类型 TIMESTAMP WITH TIME ZONE 的列,使用 java.time.OffsetDateTime.

您输入的字符串:

String timestamp = "2022-03-01T16:29:03";

... 命名错误。该值缺少时区指示符或 offset-from-UTC。所以它不能代表一个时刻。我们无法知道 hat 是否在日本东京、法国图卢兹或美国俄亥俄州托莱多 4:30 PM 左右——所有这些时间都相隔几个小时。所以称其为“时间戳”具有误导性。

将该输入字符串解析为 LocalDateTime。无需指定格式化模式。该字符串符合 ISO 8691,在 java.time classses when parsing/generating 文本中默认使用。

LocalDateTime ldt = LocalDateTime.parse( "2022-03-01T16:29:03" ) ;

此时您的代码似乎很复杂。您为此 date-with-time 分配默认时区。但这似乎不太可能说得通。我猜你的意图是让这个特定的 date-with-time 代表在特定时区看到的特定时刻。

显然您需要加拿大东部时区。 proper name for that zoneAmerica/Toronto.

ZoneId z = ZoneId.of( "America/Toronto" ) ;

分配该区域以生成 ZonedDateTime 对象。

ZonedDateTime zdt = ldt.atZone( z ) ;

现在我们有一个时刻,时间轴上的一个特定点。

但要写入类似于 SQL-standard TIMESTAMP WITH TIME ZONE 类型的数据库列,我们需要使用 OffsetDateTime.

OffsetDateTime odt = zdt.toOffsetDateTime() ;

稍后您评论说输入字符串旨在表示 UTC 中的时刻。所以分配一个ZoneOffset对象,常量UTC,得到一个OffsetDateTime.

OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ) ;

发送到数据库。

myPreparedStatement.setObject( … , odt ) ;

检索。

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;

如果必须使用java.util.Date与尚未更新为java.time的旧代码进行互操作,可以来回转换。查看添加到旧 classes 的新 to…from… 方法。

java.util.Date d = Date.from( odt.toInstant() ) ;
java.util.Date d = Date.from( zdt.toInstant() ) ;

走向另一个方向。

Instant instant = myJavaUtilDate.toInstant() ;

所有这些主题都已在 Stack Overflow 上多次提及。搜索以了解更多信息。