Java SimpleDateFormat(“ yyyy-MM-dd'T'HH:mm:ss'Z'”)给出时区为IST


148

我有SimpleDateFormat构造函数作为

SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")

我正在解析字符串 "2013-09-29T18:46:19Z".

我读到这里Z代表GMT/UTC时区。但是,当我在控制台上打印此日期时,它会为返回的日期打印IST timezne。

现在我的问题是我的输出是对还是错?


3
是的,这就是“ Z”代表的意思。Z-时区
伍迪

5
Z =祖鲁时间=> GMT + 0,您显然没有为您的国家服务;)
MushyPeas

Answers:


251

您尚未将时区设置为仅将a添加Z到日期/时间的末尾,因此它看起来像是GMT日期/时间,但这不会更改其值。

将时区设置为GMT,这将是正确的。

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));

3
如果您有日期,请说2012-12-06T06:00:00不带Z,是否表示格林尼治标准时间?
binarygiant 2014年

3
@binarygiant您必须询问发送它的人。可能是发件人的当地时间。
彼得·劳瑞

2
时区可以设置为“ UTC”
Prashanth 2015年

2
不要在许多地方为不同的库设置时区并避免与机器/笔记本电脑时区冲突,而应始终通过设置user.timezone系统属性来设置JVM的默认时区:java -Duser.timezone = GMT ...
kisna,

100

'T''Z'在此处视为常量。您需要Z不带引号通过。此外,您需要在输入字符串中指定时区。

示例:2013-09-29T18:46:19-0700 格式为"yyyy-MM-dd'T'HH:mm:ssZ"


Subir,谢谢您的回答,但是输入字符串后面会加上“ 0700”吗?
Pradip Borde

-0700是时区,即-7:00小时
Subir Kumar Sao 2013年

12
为-07:00小时而不是-0700小时,它将是以下内容:yyyy-MM-dd'T'HH:mm:ss.SSSXXX
Deliciousbrownies

48

从ISO 8601字符串到Java日期对象

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
sdf.parse("2013-09-29T18:46:19Z"); //prints-> Mon Sep 30 02:46:19 CST 2013

如果您没有设置TimeZone.getTimeZone("GMT"),它将输出Sun Sep 29 18:46:19 CST 2013

从Java日期对象到ISO 8601字符串

并将Date对象转换为ISO 8601 Standard(yyyy-MM-dd'T'HH:mm:ss'Z'),请使用以下代码

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));           
System.out.println(sdf.format(new Date())); //-prints-> 2015-01-22T03:23:26Z

另请注意,没有' 'Z yyyy-MM-dd'T'HH:mm:ssZ打印2015-01-22T03:41:02+0000


2
它给了我java.text.ParseException:无法解析的日期:“ 2018-05-01T18:30:00.000Z” @AZ_
Mansuu ....

41

如果你想处理“ 标准日” JSON表示,则最好使用此模式:"yyyy-MM-dd'T'HH:mm:ssX"

请注意X最后。 它将处理ISO 8601标准中的时区,而ISO 8601正是使用Javascript产生此语句的原因new Date().toJSON()

与其他答案相比,它具有一些优点:

  1. 您无需要求客户以格林尼治标准时间发送日期
  2. 您无需使用以下命令将Date对象显式转换为GMT: sdf.setTimeZone(TimeZone.getTimeZone("GMT"));

1
我正在使用play的自动表单绑定,并使用@Format.DateTime注释。使用默认模式Z在结尾处似乎不正确。更改为后X,它可以工作。非常感谢
transang '16

如果您的日期以兼容RFC822的方式(例如“ -0500”)指定时区,则可以正常工作。但是对于诸如“ 2013-07-15T10:22:17-05:00”(也有效的ISO8601 TZ)之类的日期,此方法会中断。在这种情况下,您需要使用“ yyyy-MM-dd'T'HH:mm:ssXXX”。
Lambart

23

tl; dr

从Java 8开始,其他答案已过时。

Instant                           // Represent a moment in UTC. 
.parse( "2013-09-29T18:46:19Z" )  // Parse text in standard ISO 8601 format where the `Z` means UTC, pronounces “Zulu”.
.atZone(                          // Adjust from UTC to a time zone. 
    ZoneId.of( "Asia/Kolkata" )
)                                 // Returns a `ZonedDateTime` object. 

ISO 8601

您的字符串格式恰好符​​合ISO 8601标准。该标准定义了用于将各种日期时间值表示为文本的合理格式。

java.time

Java 8和更高版本中内置的java.time框架已取代了旧的java.util.Date/ .Calendarjava.text.SimpleDateFormat类。请参阅教程避免使用老式的类,因为事实证明它们的设计拙劣,令人困惑和麻烦。

旧类中的一些较差的设计使您不胜其烦,该toString方法在生成实际以UTC(GMT)表示的日期时间值的文本表示时,将应用JVM当前的默认时区。好主意但令人困惑。

解析/生成日期时间值的文本表示时,java.time类默认使用ISO 8601格式。因此,无需指定解析模式。

一个Instant是在时间轴上的一个时刻UTC

Instant instant = Instant.parse( "2013-09-29T18:46:19Z" );

您可以根据需要应用时区来生成ZonedDateTime对象。

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( zoneId );

Java中的日期时间类型表(现代和旧式)


22

如果您没有选择继续使用Java8的选项,最好使用'yyyy-MM-dd'T'HH:mm:ssX XX ',因为它会再次正确解析(而只有一个X可能不是这种情况。 ..取决于您的解析功能)

X生成:+01

XXX产生:+01:00


0

对于Java 8: 您可以使用内置的java.time.format.DateTimeFormatter方法减少输入错误的可能性,例如

DateTimeFormatter formatter = DateTimeFormatter.ISO_ZONED_DATE_TIME;

ISO_ZONED_DATE_TIME表示2011-12-03T10:15:30+01:00[Europe/Paris]是Oracle 链接提供的捆绑的标准DateTime格式之一

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.