simpledateformat使用'Z'文字解析日期

Dan*_*nDC 73 java timezone datetime parsing simpledateformat

我试图解析一个看起来像这样的日期:

yyyy-MM-dd'T'HH:mm:ss
Run Code Online (Sandbox Code Playgroud)

这是http://www.ietf.org/rfc/rfc3339.txt的有效日期."Z"字面意思"暗示UTC是指定时间内的首选参考点."

如果我尝试使用SimpleDateFormat和此模式解析它:

yyyy-MM-dd'T'HH:mm:ssz
yyyy-MM-dd'T'HH:mm:ssZ
Run Code Online (Sandbox Code Playgroud)

它将被解析为2010年4月5日17:16:00美国东部时间2010年

SimpleDateFormat无法使用以下模式解析字符串:

yyyy-MM-dd'T'HH:mm:ss
Run Code Online (Sandbox Code Playgroud)

我可以显式设置TimeZone在SimpleDateFormat上使用以获得预期的输出,但我不认为这是必要的.有什么我想念的吗?有替代日期解析器吗?

Ale*_*lex 51

Java无法正确解析ISO日期.

与McKenzie的答案类似.

只需Z在解析之前修复它.

String string = "2013-03-05T18:05:05.000Z";
String defaultTimezone = TimeZone.getDefault().getID();
Date date = (new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")).parse(string.replaceAll("Z$", "+0000"));

System.out.println("string: " + string);
System.out.println("defaultTimezone: " + defaultTimezone);
System.out.println("date: " + (new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")).format(date));
Run Code Online (Sandbox Code Playgroud)

结果

string: 2013-03-05T18:05:05.000Z
defaultTimezone: America/New_York
date: 2013-03-05T13:05:05.000-0500
Run Code Online (Sandbox Code Playgroud)

  • Java 7添加了模式字母X来解析ISO日期. (20认同)
  • "Java无法正确解析ISO日期." - 好吧,旧的Java没有.但是,新的Java(Java 8及更高版本).请参阅新的[java.time](http://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html)框架. (2认同)
  • 不幸的是,我们许多人必须支持较旧的Java,例如Android 7之前的Android手机(Z模式字母在Android 6上引发异常)。 (2认同)

Dav*_*son 40

您要解析的日期是ISO8601格式.

在java 7中,应该读取要读取和应用时区后缀的模式 yyyy-MM-dd'T'HH:mm:ssX

  • 这应该是正确的答案,而不是接受的答案. (11认同)

Pau*_*zie 30

在该模式中,包含'z'日期时间组件表示时区格式需要符合通用时区 "标准",其示例是Pacific Standard Time; PST; GMT-08:00.

"Z"表示时区符合RFC 822时区标准,例如-0800.

我想你需要一个DatatypeConverter ......

@Test
public void testTimezoneIsGreenwichMeanTime() throws ParseException {
    final Calendar calendar = javax.xml.bind.DatatypeConverter.parseDateTime("2010-04-05T17:16:00Z");
    TestCase.assertEquals("gotten timezone", "GMT+00:00", calendar.getTimeZone().getID());
}
Run Code Online (Sandbox Code Playgroud)


Bas*_*que 21

TL;博士

Instant.parse ( "2010-04-05T17:16:00Z" )
Run Code Online (Sandbox Code Playgroud)

ISO 8601标准

您的String符合ISO 8601标准(其中提到的RFC 3339是配置文件).

避免juDate

与Java捆绑在一起的java.util.Date和.Calendar类非常麻烦.避免他们.

而是使用Java 8中的Joda-Time库或新的java.time包.两者都使用ISO 8601作为解析和生成日期时间值的字符串表示的默认值.

java.time

Java 8及更高版本中内置的java.time框架取代了麻烦的旧java.util.Date/.Calendar类.新课程的灵感来自非常成功的Joda-Time框架,旨在作为其继承者,在概念上类似但重新设计.由JSR 310定义.由ThreeTen-Extra项目扩展.请参阅教程.

Instantjava.time中的类表示UTC时区中时间轴上的时刻.

Z你输入字符串的结束意味着Zulu它代表UTC.这样的字符串可以由Instant类直接解析,而不需要指定格式化程序.

String input = "2010-04-05T17:16:00Z";
Instant instant = Instant.parse ( input );
Run Code Online (Sandbox Code Playgroud)

转储到控制台.

System.out.println ( "instant: " + instant );
Run Code Online (Sandbox Code Playgroud)

时间:2010-04-05T17:16:00Z

从那里你可以应用时区(ZoneId)将其调整Instant为a ZonedDateTime.搜索Stack Overflow以进行讨论和示例.

如果必须使用java.util.Date对象,则可以通过调用添加到旧类(如静态方法)的新转换方法进行转换java.util.Date.from( Instant ).

java.util.Date date = java.util.Date.from( instant );
Run Code Online (Sandbox Code Playgroud)

乔达时间

Joda-Time 2.5中的示例.

DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" ):
DateTime dateTime = new DateTime( "2010-04-05T17:16:00Z", timeZone );
Run Code Online (Sandbox Code Playgroud)

转换为UTC.

DateTime dateTimeUtc = dateTime.withZone( DateTimeZone.UTC );
Run Code Online (Sandbox Code Playgroud)

如有必要,转换为java.util.Date.

java.util.Date date = dateTime.toDate();
Run Code Online (Sandbox Code Playgroud)


Leg*_*gna 15

根据Java 7 API日期和时间模式表的最后一行

X时区ISO 8601时区-08; -0800; -08:00

对于ISO 8601时区,您应该使用:

  • X代表(-08或Z),
  • XX为(-0800或Z),
  • XXX代表(-08:00或Z);

所以要解析你的"2010-04-05T17:16:00Z"你可以使用 "yyyy-MM-dd'T'HH:mm:ssX"或"yyyy-MM-dd'T'HH:mm:ssXX"或"yyyy-MM-dd'T'HH:mm:ssXXX".

    System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX").parse("2010-04-05T17:16:00Z"));
    System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXX").parse("2010-04-05T17:16:00Z"));
    System.out.println(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX").parse("2010-04-05T17:16:00Z"));
Run Code Online (Sandbox Code Playgroud)

将正确打印出'Mon Apr 05 13:16:00 EDT 2010'


小智 7

在 Java 8 下使用预定义的 DateTimeFormatter.ISO_DATE_TIME

 DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;
 ZonedDateTime result = ZonedDateTime.parse("2010-04-05T17:16:00Z", formatter);
Run Code Online (Sandbox Code Playgroud)

我想这是最简单的方法


小智 6

'X'仅在部分秒不存在时才有效:即SimpleDateFormat模式

"YYYY-MM-dd'T'HH:MM:SSX"

将正确解析

"2008-01-31T00:00:00Z"

"YYYY-MM-dd'T'HH:MM:ss.SX"

不会解析

"2008-01-31T00:00:00.000Z"

可悲但真实,带有部分秒数的日期时间似乎不是有效的ISO日期:http://en.wikipedia.org/wiki/ISO_8601

  • 这非常烦人. (2认同)