Java 8 - 使用时区从LocalDateTime创建Instant

55

我在数据库中以字符串格式ddMMyyyy和hh:mm以及时区存储了一个日期。我想根据这些信息创建一个Instant对象,但是我不知道怎么做。

类似以下的方式:

LocalDateTime dateTime = LocalDateTime.of(2017, Month.JUNE, 1, 13, 39);
Instant instant = dateTime.toInstant(TimeZone.getTimeZone("ECT"));

1
你的意思是 ZonedDateTime.ofInstant(instant, TimeZone.getDefault()) 吗? - soorapadman
2
@soorapadman 这将返回一个ZonedDateTime。OP想要一个Instant。 - Jean-François Savard
8
不要使用3-4个字符的缩写来表示时区。这些并不是真正的时区,也不是标准化的,甚至不是唯一的!请使用真正的时区名称,格式为大陆/地区,例如Europe/LondonEurope/ParisAsia/KolkataPacific/Auckland。如果你所指的“ECT”是指厄瓜多尔时间,请使用ZoneId.of("America/Guayaquil")。如果你所指的是中欧时间,请使用适当的Europe/...时区名称。 - Basil Bourque
4
这个问题与链接问题不重复。这个问题与毫秒计数无直接联系。 - Basil Bourque
1
我在数据库中以字符串格式(ddMMyyyy和hh:mm)和时区存储了一个日期。不,你没有,如果你在定义数据库列时使用了日期时间数据类型,比如TIMESTAMP WITH TIME ZONE(正如你应该做的)。日期时间列没有“格式”,因为它们不是字符串/文本。将日期时间值作为日期时间对象而不是字符串检索出来。Instant instant = myResultSet.getObject( … , Instant.class ); - Basil Bourque
3个回答

98
你可以先使用该时区创建一个ZonedDateTime,然后调用toInstant方法:

您可以先使用该时区创建ZonedDateTime,然后调用toInstant方法:

LocalDateTime dateTime = LocalDateTime.of(2017, Month.JUNE, 15, 13, 39);
Instant instant = dateTime.atZone(ZoneId.of("Europe/Paris")).toInstant();
System.out.println(instant); // 2017-06-15T11:39:00Z

我也根据Basil的建议改用完整的时区名称,因为这样更清晰明了。


10
几乎是完美的答案,但你不应该鼓励使用3-4字母的伪时区代码。相反,应该使用“洲/地区”格式中的真实时区名称。我猜作者想表达“Ecuador Time”为“ECT”。可以使用ZoneId.of( "America/Guayaquil" )来代替。 - Basil Bourque
1
@BasilBourque “ECT”实际上是欧洲中央时间(Europe/Paris),所以我可以理解为什么使用全名会更好;) - Jorn Vernee
4
我只看过"CET"表示中欧时间。但这正是问题所在,这些由3-4个字母组成的代码非常容易引起歧义,应该像避开瘟疫一样尽量避免使用。 - Basil Bourque
1
@Line 日期不明确。在法国巴黎午夜后几分钟就是新的一天,而在加拿大魁北克省蒙特利尔仍然是“昨天”。如果您打算使用UTC时间,请使用OffsetDateTime来确定一个时刻:OffsetDateTime.of(LocalDate.of(2018, 1, 23), LocalTime.MIN, ZoneOffset.UTC) - Basil Bourque
1
因为2-4个字母的缩写(如ET、PST、EST、CST、IST等)不是真正的时区,也没有标准化,并且不是唯一的。例如:IST可以代表冰岛标准时间、爱尔兰标准时间、印度标准时间等等。请参考维基百科上以“大陆/地区”格式列出的标准时区名称列表。 - Basil Bourque
显示剩余7条评论

11

不要再使用旧的TimeZone类,而应该使用ZoneId,因为它是线程安全的,您可以使用一个final静态字段来存储时区。

LocalDateTime dateTime = LocalDateTime.of(2017, Month.JUNE, 1, 13, 39);
ZonedDateTime.of(dateTime, ZoneId.of("ECT")).toInstant();

-4
我认为以下代码应该可以工作:
LocalDateTime time = LocalDateTime.of(2017, Month.JUNE, 15, 13, 39);
ZonedDateTime.of(time, TimeZone.getTimeZone("ZONE").toZoneId()).toInstant();

你只需要用你需要的时区替换掉“ZONE”即可。


9
不,TimeZone是传统类,现在已被ZoneId和ZoneOffset取代。避免使用传统的日期时间类,并且一定不要将传统类与java.time类混合使用。请更正或删除你的答案。 - Basil Bourque

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接