如果程序给出的当前时间是 2016-06-01T11:33:54.000Z ,
程序错了吗?
格式正确且符合ISO 8601,但不代表欧洲/伦敦时间。在伦敦,in 2016,夏令时开始于 3 月 27 日星期日凌晨 1:00,结束于 10 月 30 日星期日凌晨 2:00,因此是一个日期- 在此期间欧洲/伦敦的时间表示应具有+01:00 小时的时区偏移量。最后的Z 指定Zulu 时间,这是UTC 时间,因此时区偏移量为+00:00 小时。对于欧洲/伦敦,同一时刻可以表示为2016-06-01T12:33:54+01:00。
java.time
java.util 日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用它们并切换到java.time,modern date-time API* 。
甚至 Joda-Time 也不应该再使用了。请注意Home Page of Joda-Time中的以下注释
Joda-Time 是 Java 的事实上的标准日期和时间库
在 Java SE 8 之前。现在要求用户迁移到 java.time
(JSR-310)。
java.time API 基于ISO 8601 和日期时间字符串,2016-06-01T11:33:54.000Z 可以解析为java.time.ZonedDateTime 和java.time.OffsetDateTime,而不需要日期时间解析/格式化类型。
演示:
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
ZonedDateTime zdt = ZonedDateTime.parse("2016-06-01T11:33:54.000Z");
System.out.println(zdt);
ZoneId zoneId = ZoneId.of("Europe/London");
ZonedDateTime zdtInLondon = zdt.withZoneSameInstant(zoneId);
System.out.println(zdtInLondon);
}
}
输出:
2016-06-01T11:33:54Z
2016-06-01T12:33:54+01:00[Europe/London]
如何处理夏令时(DST)?
如前所述,日期时间字符串2016-06-01T11:33:54.000Z 也可以解析为java.time.OffsetDateTime,而不需要日期时间解析/格式化类型。然而,OffsetDateTime 被设计用于处理固定的时区偏移,而ZonedDateTime 被设计用于处理时区 因此它会自动处理 DST。如果需要,您可以使用ZonedDateTime#toOffsetDateTime 将ZonedDateTime 转换为OffsetDateTime。
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSS z", Locale.ENGLISH);
String strDateTime = "2016-03-01T11:33:54.000 Europe/London";
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtf);
System.out.println(zdt);
strDateTime = "2016-06-01T11:33:54.000 Europe/London";
zdt = ZonedDateTime.parse(strDateTime, dtf);
System.out.println(zdt);
}
}
输出:
2016-03-01T11:33:54Z[Europe/London]
2016-06-01T11:33:54+01:00[Europe/London]
请注意时区偏移如何自动从 Z 更改为 01:00 以反映 DST 更改。另一方面,
import java.time.OffsetDateTime;
public class Main {
public static void main(String[] args) {
String strDateTime = "2016-03-01T11:33:54.000+01:00";
OffsetDateTime odt = OffsetDateTime.parse(strDateTime);
System.out.println(odt);
strDateTime = "2016-06-01T11:33:54.000+01:00";
odt = OffsetDateTime.parse(strDateTime);
System.out.println(odt);
}
}
输出:
2016-03-01T11:33:54+01:00
2016-06-01T11:33:54+01:00
在这种情况下,您不谈论时区(例如欧洲/伦敦);相反,您谈论的是+01:00 小时的固定时区偏移量。
从 Trail: Date Time 了解有关现代日期时间 API 的更多信息。
* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 和 7 . 如果您正在为一个 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaring 和 How to use ThreeTenABP in Android Project。