simpledateformat用'Z'文字parsingdate

我试图parsing一个看起来像这样的date:

2010-04-05T17:16:00Z 

这是每个http://www.ietf.org/rfc/rfc3339.txt的有效date。 “Z”字面意味着UTC是指定时间的首选参考点。

如果我尝试使用SimpleDateFormat和这种模式parsing它:

 yyyy-MM-dd'T'HH:mm:ss 

它将被parsing为2010年4月5日星期一17:16:00

SimpleDateFormat无法parsing这些模式的string:

 yyyy-MM-dd'T'HH:mm:ssz yyyy-MM-dd'T'HH:mm:ssZ 

我可以明确地设置TimeZone使用SimpleDateFormat来获得预期的输出,但我不认为这是必要的。 有什么我失踪? 有没有其他dateparsing器?

在该模式中,包含“z”date时间分量表示时区格式需要符合通用时区 “标准”,例如Pacific Standard Time; PST; GMT-08:00 Pacific Standard Time; PST; GMT-08:00 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()); } 

Java不能正确parsingISOdate。

类似麦肯齐的答案。

parsing之前只需修复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)); 

结果

 string: 2013-03-05T18:05:05.000Z defaultTimezone: America/New_York date: 2013-03-05T13:05:05.000-0500 

你parsing的date是ISO8601格式。

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

TL;博士

 Instant.parse ( "2010-04-05T17:16:00Z" ) 

ISO 8601标准

您的string符合ISO 8601标准(其中提到的RFC 3339是一个configuration文件)。

避免juDate

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

而是使用Java 8中的Joda-Time库或新的java.time包。两者都使用ISO 8601作为parsing和生成date – 时间值的string表示的默认值。

java.time

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

java.time中的Instant类表示UTC时区中时间轴上的某一时刻。

inputstring末尾的Z表示代表UTC Zulu 。 这样的string可以直接由Instant类parsing,不需要指定格式化程序。

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

转储到控制台。

 System.out.println ( "instant: " + instant ); 

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

从那里你可以申请一个时区( ZoneId )来调整这个InstantZonedDateTime 。 search堆栈溢出的讨论和例子。

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

 java.util.Date date = java.util.Date.from( instant ); 

乔达时间

Joda-Time 2.5中的例子

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

转换为UTC。

 DateTime dateTimeUtc = dateTime.withZone( DateTimeZone.UTC ); 

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

 java.util.Date date = dateTime.toDate(); 

“X”只有在部分秒不存在的情况下才有效:即SimpleDateFormat模式

“YYYY-MM-dd'T'HH:MM:SSX”

将正确parsing

“2008-01-31T00:00:00Z”

“YYYY-MM-dd'T'HH:MM:ss.SX”

不会parsing

“2008-01-31T00:00:00.000Z”

可悲的是,具有部分秒的date时间似乎不是一个有效的ISOdate: http : //en.wikipedia.org/wiki/ISO_8601

根据Java 7 API的Date and Time Patterns表中的最后一行

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

对于ISO 8601时区,您应该使用X(-08或Z); XX(-0800或Z); 和XXX(-08:00或Z)来parsing你的“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")); 

将正确打印出“2010年4月5日13:16:00美国东部时间2010年”

时区应该类似于“GMT + 00:00”或0000,以便被SimpleDateFormat正确parsing – 您可以用此构造replaceZ.

restlet项目包括一个可以parsingRFC 3339date的InternetDateFormat类。

Restlet InternetDateFormat

虽然,你可能只是想在parsing它之前用“UTC”replace尾随的“Z”。

我提供了另外一个答案,我通过api-client-library了Google

 try { DateTime dateTime = DateTime.parseRfc3339(date); dateTime = new DateTime(new Date(dateTime.getValue()), TimeZone.getDefault()); long timestamp = dateTime.getValue(); // get date in timestamp int timeZone = dateTime.getTimeZoneShift(); // get timezone offset } catch (NumberFormatException e) { e.printStackTrace(); } 

安装指南,
https://developers.google.com/api-client-library/java/google-api-java-client/setup#download

这里是API参考,
https://developers.google.com/api-client-library/java/google-http-java-client/reference/1.20.0/com/google/api/client/util/DateTime

DateTime类的源代码,
https://github.com/google/google-http-java-client/blob/master/google-http-client/src/main/java/com/google/api/client/util/DateTime.java

DateTimeunit testing,
https://github.com/google/google-http-java-client/blob/master/google-http-client/src/test/java/com/google/api/client/util/DateTimeTest.java#L121

关于JSR-310,另一个感兴趣的项目可能是三年 。

JSR-310为Java SE 8提供了一个新的date和时间库。该项目是Java SE 6和7的后端。

如果您正在使用Android项目,则可能需要签出ThreeTenABP库 。

 compile "com.jakewharton.threetenabp:threetenabp:${version}" 

JSR-310作为java.time。*包被包含在Java 8中。 它完全取代了Java和Android中的日历和日历API。 JSR-310被其创build者Stephen Colebourne从Java库中移植到了Java 6,该库从此被改编。

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

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

我想它是最简单的方法

由于Java 8只是使用ZonedDateTime.parse("2010-04-05T17:16:00Z")