SimpleDateFormat setTimeZone 不工作
SimpleDateFormat setTimeZone not working
我正在使用下面的代码将时间转换为 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
class 相反,来自 java.time
的 OffsetDateTime
,现代的 Java 日期和时间 API,确实包含 UTC 偏移量,顾名思义。我没有使用 Groovy 的经验,所以很抱歉不得不相信你会翻译我的 Java 代码。
如果您想确保获得特定时区而不管字符串中有哪个偏移量:
ZoneId zone = ZoneId.of("Europe/Brussels");
ZonedDateTime dateTime = OffsetDateTime.parse(dt).atZoneSameInstant(zone);
这次的结果是:
2018-03-19T06:00+01:00[Europe/Brussels]
不要依赖像 CET 这样的三个字母的时区缩写。 CET 是许多欧洲时区的标准时间一半(没有夏季的部分 time/DST)的通用名称,这些时区通常共享时间,但并不总是这样做,并且在涉及历史时往往不同意时间日期。其他三个字母的缩写是模棱两可的,因此会导致更多的混乱。始终将时区指定为 region/city,就像我对 Europe/Brussels 所做的那样。当然,选择符合您所需时区的城市。
如果您认为自己需要 java.sql.Timestamp
— 您可能不需要。如果使用 JDBC 4.2 或更高版本或类似的现代 JPA 实现,最好将 Instant
或 LocalDateTime
存储到数据库中。选择取决于您的确切要求和数据库列的确切数据类型。
Instant inst = dateTime.toInstant();
System.out.println(inst);
输出
2018-03-19T05:00:00Z
Instant
s 始终以 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
因为我的时区与 date-time 对象中的时区一致,所以我从两次转换中得到相同的结果。在其他时区结果可能不一样,您需要注意选择正确的。
你的代码出了什么问题?
当您使用 SimpleDateFormat
解析其中包含 UTC 偏移量的字符串时,它会使用该偏移量来确定时间点。在这种情况下,它不会使用您通过 setTimeZone
设置的时区。而且它不会在 Date
和 returns 中放置任何时区或偏移量,因为 Date
不能包含时区。这只是一个时间点。
让很多人感到困惑的是 Date.toString()
的结果似乎包含时区缩写,如输出 Mon Mar 19 05:00:00 UTC 2018
中的 UTC。发生的事情是 toString()
使用 JVM 的时区设置来生成字符串。这就是 TimeZone.setDefault()
影响您获得的输出的原因:它设置 JVM 设置,影响同一 JVM 中的所有程序 运行。它不会影响 Date
对象本身,但是只会影响其 toString()
.
的结果
TimeZone
、Date
和 Timestamp
class 早就过时了。 SimpleDateFormat
太麻烦了。我建议您根本不要使用那些 classes。 java.time
更好用。
Link
Oracle tutorial: Date Time 解释如何使用 java.time
.
我正在使用下面的代码将时间转换为 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
class 相反,来自 java.time
的 OffsetDateTime
,现代的 Java 日期和时间 API,确实包含 UTC 偏移量,顾名思义。我没有使用 Groovy 的经验,所以很抱歉不得不相信你会翻译我的 Java 代码。
如果您想确保获得特定时区而不管字符串中有哪个偏移量:
ZoneId zone = ZoneId.of("Europe/Brussels");
ZonedDateTime dateTime = OffsetDateTime.parse(dt).atZoneSameInstant(zone);
这次的结果是:
2018-03-19T06:00+01:00[Europe/Brussels]
不要依赖像 CET 这样的三个字母的时区缩写。 CET 是许多欧洲时区的标准时间一半(没有夏季的部分 time/DST)的通用名称,这些时区通常共享时间,但并不总是这样做,并且在涉及历史时往往不同意时间日期。其他三个字母的缩写是模棱两可的,因此会导致更多的混乱。始终将时区指定为 region/city,就像我对 Europe/Brussels 所做的那样。当然,选择符合您所需时区的城市。
如果您认为自己需要 java.sql.Timestamp
— 您可能不需要。如果使用 JDBC 4.2 或更高版本或类似的现代 JPA 实现,最好将 Instant
或 LocalDateTime
存储到数据库中。选择取决于您的确切要求和数据库列的确切数据类型。
Instant inst = dateTime.toInstant();
System.out.println(inst);
输出
2018-03-19T05:00:00Z
Instant
s 始终以 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
因为我的时区与 date-time 对象中的时区一致,所以我从两次转换中得到相同的结果。在其他时区结果可能不一样,您需要注意选择正确的。
你的代码出了什么问题?
当您使用 SimpleDateFormat
解析其中包含 UTC 偏移量的字符串时,它会使用该偏移量来确定时间点。在这种情况下,它不会使用您通过 setTimeZone
设置的时区。而且它不会在 Date
和 returns 中放置任何时区或偏移量,因为 Date
不能包含时区。这只是一个时间点。
让很多人感到困惑的是 Date.toString()
的结果似乎包含时区缩写,如输出 Mon Mar 19 05:00:00 UTC 2018
中的 UTC。发生的事情是 toString()
使用 JVM 的时区设置来生成字符串。这就是 TimeZone.setDefault()
影响您获得的输出的原因:它设置 JVM 设置,影响同一 JVM 中的所有程序 运行。它不会影响 Date
对象本身,但是只会影响其 toString()
.
TimeZone
、Date
和 Timestamp
class 早就过时了。 SimpleDateFormat
太麻烦了。我建议您根本不要使用那些 classes。 java.time
更好用。
Link
Oracle tutorial: Date Time 解释如何使用 java.time
.