我正在使用下面的代码将时间转换为UTC
import java.text.SimpleDateFormat;
import static java.util.Calendar.*
def dt = "2018-03-19T06:00:00+01:00"
def format = "yyyy-MM-dd'T'HH:mm:ssX"
TimeZone tz = TimeZone.getDefault(); //getting up local time zone
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
SimpleDateFormat sdf = new SimpleDateFormat(format);
Date d = sdf.parse(dt);
TimeZone.setDefault(tz);
println d //output: 2018-03-19T05:00:00Z
println d.toTimestamp(); //Output: 2018-03-19 06:00:00.0
但是,当我使用
TimeZone.setTimeZone(TimeZone.getTimeZone("UTC"));
时,它不起作用。它仅适用于
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
为什么这样?
评论后更新:输出必须在CET中,但必须在UTC中
def dt = "2018-03-19T06:00:00+01:00"
def format = "yyyy-MM-dd'T'HH:mm:ssX"
SimpleDateFormat sdf = new SimpleDateFormat(format);
sdf.setTimeZone(TimeZone.getTimeZone("CET"))
Date d = sdf.parse(dt);
println d
println d.toTimestamp();
输出:
Mon Mar 19 05:00:00 UTC 2018
2018-03-19 05:00:00.0
最佳答案
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
类相反,现代Java日期和时间API OffsetDateTime
中的java.time
确实包含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
或LocalDateTime
存储到数据库中。选择取决于您的确切要求和数据库列的确切数据类型。 Instant inst = dateTime.toInstant();
System.out.println(inst);
输出量
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()
的结果似乎包含时区缩写,如输出Mon Mar 19 05:00:00 UTC 2018
中的UTC。发生的情况是toString()
使用JVM的时区设置来生成字符串。这就是TimeZone.setDefault()
影响您获得的输出的原因:它设置JVM设置,从而影响在同一JVM中运行的所有程序。它不会影响Date
对象本身,但是只会影响其toString()
的结果。TimeZone
,Date
和Timestamp
类早已过时。 SimpleDateFormat
也太麻烦了。我建议您完全不要使用这些类。 java.time
更好用。链接
Oracle tutorial: Date Time解释如何使用
java.time
。