Java 了解特定UTC时间格式YYYY-MM-DDTHH:MM:SS.SSSZ
我有两个相关的问题 假设在BST中运行的程序以UTC YYYY-MM-DDTHH:MM:SS.SSSZ格式为当前时间生成日期时间值 同时假设伦敦的当前时间为2016-06-01 12:33:54Java 了解特定UTC时间格式YYYY-MM-DDTHH:MM:SS.SSSZ,java,utc,iso8601,gmt,Java,Utc,Iso8601,Gmt,我有两个相关的问题 假设在BST中运行的程序以UTC YYYY-MM-DDTHH:MM:SS.SSSZ格式为当前时间生成日期时间值 同时假设伦敦的当前时间为2016-06-01 12:33:54 如果程序给出的当前时间为2016-06-01T11:33:54.000Z,程序是否错误 在YYYY-MM-DDTHH:MM:SS.SSSZ的相应时间格式中,如何记录BST的夏季偏移量 我假设YYYY-MM-DDTHH:MM:SS+0001我是否正确?首先请阅读iso8601信息。处理不同时区(例如服
我假设YYYY-MM-DDTHH:MM:SS+0001我是否正确?首先请阅读iso8601信息。处理不同时区(例如服务器时区和客户端时区)的时间变得越来越普遍,该标准非常有用 请特别阅读UTC或“祖鲁”时间
SimpleDataFormat
,则支持时区并将打印出来
下面是一个代码示例
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(formatter.format(new Date()));
formatter.setTimeZone(TimeZone.getTimeZone("Europe/London"));
System.out.println(formatter.format(new Date()));
输出
2016-06-02T12:53:14.924Z
2016-06-02T13:53:14.925+01:00
当然,如果您使用的是不同的日期/时间库,例如joda time
,那么实现细节将有所不同
编辑:正如@DerrylThomas在SimpleDateFormat
中指出的那样,明智地使用小写y连年-除非它打算使用week year-在对类似问题的另一个回答中进行了详细解释
如果程序给出的当前时间为2016-06-01T11:33:54.000Z,
程序错了吗
格式正确且符合,但不代表欧洲/伦敦时间。在伦敦,DST开始于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
date-time API及其格式化APISimpleDataFormat
已经过时,并且容易出错。建议完全停止使用它们,并切换到java.time
,即*
即使是Joda Time也不应再使用。请注意下面的注释
Joda Time是Java事实上的标准日期和时间库
在JavaSE8之前。现在要求用户迁移到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]
2016-03-01T11:33:54Z[Europe/London]
2016-06-01T11:33:54+01:00[Europe/London]
2016-03-01T11:33:54+01:00
2016-06-01T11:33:54+01:00
输出:
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]
2016-03-01T11:33:54Z[Europe/London]
2016-06-01T11:33:54+01:00[Europe/London]
2016-03-01T11:33:54+01:00
2016-06-01T11:33:54+01:00
如何处理夏令时(DST)?
如前所述,日期时间字符串2016-06-01T11:33:54.000Z
也可以解析为java.time.OffsetDateTime
,而无需日期时间解析/格式化类型。然而,OffsetDateTime
被设计用于处理固定的时区偏移,而zoneDateTime
被设计用于处理时区,因此它会自动处理DST。如果需要,可以使用将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);
}
}
输出:
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]
2016-03-01T11:33:54Z[Europe/London]
2016-06-01T11:33:54+01:00[Europe/London]
2016-03-01T11:33:54+01:00
2016-06-01T11:33:54+01:00
请注意,时区偏移是如何自动从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);
}
}
输出:
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]
2016-03-01T11:33:54Z[Europe/London]
2016-06-01T11:33:54+01:00[Europe/London]
2016-03-01T11:33:54+01:00
2016-06-01T11:33:54+01:00
在这种情况下,您不谈论时区(例如欧洲/伦敦);相反,您谈论的是固定时区偏移量+01:00
小时
从了解有关现代日期时间API的更多信息
*无论出于何种原因,如果您必须坚持使用Java6或Java7,您可以使用哪个backport将大部分Java.time功能移植到Java6&7。如果您正在为Android项目工作,并且您的Android API级别仍然不符合Java-8,请检查并确认。
1)没有,因为存在夏季补偿。UTC不随夏季偏移量变化。2) YYYY-MM-DDTHH:MM:SS+01:00那么上面例子中程序给出的时间应该是2016-06-01T11:33:54.000+01:00,你是说?不应该是
2016-06-01T11:33:54.000Z
或者2016-06-01T12:33:54.000+01:00
或者2016-06-01T13:33:54.000+02:00
什么都行!!这有帮助。2)不,你不能。ISO 8601明确指出零偏移量仅为Z
。在您的符号中SS.SSS
是毫秒而不是微秒。但是你可以使用任何你喜欢的分数,这完全取决于程序中代码的工作方式。您是否可以访问该程序的代码,我们是否可以查看它是否使用了SimpleDataFormat
,如果是,字符串是什么?在任何情况下,2016-06-01T11:33:54.000Z
和2016-06-01T12:33:54.000+01:00
都是正确的,因为它们是相同的时间点!对一个或另一个的偏好完全取决于您的程序和您正在处理的问题域(您有规范吗?)。看起来您的程序总是以祖鲁语和