java.time
String dt = "2018-03-19T06:00:00+01:00";
OffsetDateTime dateTime = OffsetDateTime.parse(dt);
System.out.println(dateTime);
这打印
2018-03-19T06:00+01:00
与过时的相反Date
类,一个OffsetDateTime
from java.time
,现代 Java 日期和时间 API,确实包含 UTC 偏移量,正如其名称所示。我没有使用 Groovy 的经验,因此很抱歉必须信任您来翻译我的 Java 代码。
如果您想确保获得特定时区,无论字符串中的偏移量如何:
ZoneId zone = ZoneId.of("Europe/Brussels");
ZonedDateTime dateTime = OffsetDateTime.parse(dt).atZoneSameInstant(zone);
这次的结果是:
2018-03-19T06:00+01:00[欧洲/布鲁塞尔]
不要依赖 CET 等三字母时区缩写。 CET 是许多欧洲时区标准时间一半(没有夏令时/DST 的部分)的通用名称,这些时区通常共享时间,但并不总是这样做,并且在涉及历史日期时往往在时间上存在分歧。其他三个字母的缩写是不明确的,因此会导致更多的混乱。始终将时区指定为地区/城市,就像我对欧洲/布鲁塞尔所做的那样。当然,选择与您所需时区相匹配的城市。
如果您认为您需要一个java.sql.Timestamp
——你可能不需要那个。如果使用 JDBC 4.2 或更高版本或类似的现代 JPA 实现,最好存储Instant
or a LocalDateTime
到您的数据库。选择取决于您的具体要求以及数据库列的具体数据类型。
Instant inst = dateTime.toInstant();
System.out.println(inst);
Output
2018-03-19T05:00:00Z
Instant
始终以 UTC 格式打印。如果足够新的 JDBC 驱动程序不可用,您可以转换为Timestamp
有两种方式之一:
System.out.println(Timestamp.from(inst));
System.out.println(Timestamp.valueOf(dateTime.toLocalDateTime()));
2018-03-19 06:00:00.0
2018-03-19 06:00:00.0
由于我的时区与日期时间对象中的时区一致,因此两次转换得到的结果相同。在其他时区,结果可能会有所不同,您需要小心选择正确的结果。
你的代码出了什么问题?
当你使用SimpleDateFormat
为了解析其中包含 UTC 偏移量的字符串,它使用该偏移量来确定时间点。在这种情况下,它不使用您设置的时区setTimeZone
为了任何东西。并且它不会将任何时区或偏移量放入Date
它返回是因为Date
不能包含时区。这只是一个时间点。
让很多人感到困惑的是,结果Date.toString()
似乎包含时区缩写,如输出中的 UTCMon Mar 19 05:00:00 UTC 2018
。发生的事情是这样的toString()
使用 JVM 的时区设置来生成字符串。这就是为什么TimeZone.setDefault()
影响你得到的输出:它设置 JVM 设置,影响在同一 JVM 中运行的所有程序。它不影响Date
然而,对象本身只是其结果toString()
.
The TimeZone
, Date
and Timestamp
课程早已过时。SimpleDateFormat
太麻烦了,同时也是出了名的麻烦。我建议你根本不要使用这些类。java.time
合作起来更加愉快。
Link
Oracle 教程:日期时间 https://docs.oracle.com/javase/tutorial/datetime/解释如何使用java.time
.