可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
This question already has an answer here:
-
Converting ISO 8601-compliant String to java.util.Date
25 answers
I am trying to parse a date that looks like this:
2010-04-05T17:16:00Z
This is a valid date per http://www.ietf.org/rfc/rfc3339.txt. The \'Z\' literal \"imply that UTC
is the preferred reference point for the specified time.\"
If I try to parse it using SimpleDateFormat and this pattern:
yyyy-MM-dd\'T\'HH:mm:ss
It will be parsed as a Mon Apr 05 17:16:00 EDT 2010
SimpleDateFormat is unable to parse the string with these patterns:
yyyy-MM-dd\'T\'HH:mm:ssz
yyyy-MM-dd\'T\'HH:mm:ssZ
I can explicitly set the TimeZone to use on the SimpleDateFormat to get the expected output, but I don\'t think that should be necessary. Is there something I am missing? Is there an alternative date parser?
回答1:
In the pattern, the inclusion of a \'z\' date-time component indicates that timezone format needs to conform to the General time zone \"standard\", examples of which are Pacific Standard Time; PST; GMT-08:00
.
A \'Z\' indicates that the timezone conforms to the RFC 822 time zone standard, e.g. -0800
.
I think you need a 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());
}
回答2:
Java doesn\'t parse ISO dates correctly.
Similar to McKenzie\'s answer.
Just fix the Z
before parsing.
Code
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));
Result
string: 2013-03-05T18:05:05.000Z
defaultTimezone: America/New_York
date: 2013-03-05T13:05:05.000-0500
回答3:
The date you are parsing is in ISO8601 format.
In java 7 the pattern to read and apply the timezone suffix should read yyyy-MM-dd\'T\'HH:mm:ssX
回答4:
tl;dr
Instant.parse ( \"2010-04-05T17:16:00Z\" )
ISO 8601 Standard
Your String complies with the ISO 8601 standard (of which the mentioned RFC 3339 is a profile).
Avoid j.u.Date
The java.util.Date and .Calendar classes bundled with Java are notoriously troublesome. Avoid them.
Instead use either the Joda-Time library or the new java.time package in Java 8. Both use ISO 8601 as their defaults for parsing and generating string representations of date-time values.
java.time
The java.time framework built into Java 8 and later supplants the troublesome old java.util.Date/.Calendar classes. The new classes are inspired by the highly successful Joda-Time framework, intended as its successor, similar in concept but re-architected. Defined by JSR 310. Extended by the ThreeTen-Extra project. See the Tutorial.
The Instant
class in java.time represents a moment on the timeline in UTC time zone.
The Z
at the end of your input string means Zulu
which stands for UTC
. Such a string can be directly parsed by the Instant
class, with no need to specify a formatter.
String input = \"2010-04-05T17:16:00Z\";
Instant instant = Instant.parse ( input );
Dump to console.
System.out.println ( \"instant: \" + instant );
instant: 2010-04-05T17:16:00Z
From there you can apply a time zone (ZoneId
) to adjust this Instant
into a ZonedDateTime
. Search Stack Overflow for discussion and examples.
If you must use a java.util.Date
object, you can convert by calling the new conversion methods added to the old classes such as the static method java.util.Date.from( Instant )
.
java.util.Date date = java.util.Date.from( instant );
Joda-Time
Example in Joda-Time 2.5.
DateTimeZone timeZone = DateTimeZone.forID( \"Europe/Paris\" ):
DateTime dateTime = new DateTime( \"2010-04-05T17:16:00Z\", timeZone );
Convert to UTC.
DateTime dateTimeUtc = dateTime.withZone( DateTimeZone.UTC );
Convert to a java.util.Date if necessary.
java.util.Date date = dateTime.toDate();
回答5:
According to last row on the Date and Time Patterns table of the Java 7 API
X Time zone ISO 8601 time zone -08; -0800; -08:00
For ISO 8601 time zone you should use:
- X for (-08 or Z),
- XX for (-0800 or Z),
- XXX for (-08:00 or Z);
so to parse your \"2010-04-05T17:16:00Z\" you can use either
\"yyyy-MM-dd\'T\'HH:mm:ssX\" or \"yyyy-MM-dd\'T\'HH:mm:ssXX\" or \"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\"));
will correctly print out \'Mon Apr 05 13:16:00 EDT 2010\'
回答6:
The \'X\' only works if partial seconds are not present: i.e. SimpleDateFormat pattern of
\"yyyy-MM-dd\'T\'HH:mm:ssX\"
Will correctly parse
\"2008-01-31T00:00:00Z\"
but
\"yyyy-MM-dd\'T\'HH:mm:ss.SX\"
Will NOT parse
\"2008-01-31T00:00:00.000Z\"
Sad but true, a date-time with partial seconds does not appear to be a valid ISO date: http://en.wikipedia.org/wiki/ISO_8601
回答7:
The time zone should be something like \"GMT+00:00\" or 0000 in order to be properly parsed by the SimpleDateFormat - you can replace Z with this construction.
回答8:
The restlet project includes an InternetDateFormat class that can parse RFC 3339 dates.
Restlet InternetDateFormat
Though, you might just want to replace the trailing \'Z\' with \"UTC\" before you parse it.
回答9:
I provide another answer that I found by api-client-library
by 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();
}
Installation guide,
https://developers.google.com/api-client-library/java/google-api-java-client/setup#download
Here is API reference,
https://developers.google.com/api-client-library/java/google-http-java-client/reference/1.20.0/com/google/api/client/util/DateTime
Source code of DateTime
Class,
https://github.com/google/google-http-java-client/blob/master/google-http-client/src/main/java/com/google/api/client/util/DateTime.java
DateTime
unit tests,
https://github.com/google/google-http-java-client/blob/master/google-http-client/src/test/java/com/google/api/client/util/DateTimeTest.java#L121
回答10:
With regards to JSR-310 another project of interest might be threetenbp.
JSR-310 provides a new date and time library for Java SE 8. This project is the backport to Java SE 6 and 7.
In case you are working on an Android project you might want to checkout the ThreeTenABP library.
compile \"com.jakewharton.threetenabp:threetenabp:${version}\"
JSR-310 was included in Java 8 as the java.time.* package. It is a full replacement for the ailing Date and Calendar APIs in both Java and Android. JSR-310 was backported to Java 6 by its creator, Stephen Colebourne, from which this library is adapted.
回答11:
Under Java 8 use the predefined DateTimeFormatter.ISO_DATE_TIME
DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;
ZonedDateTime result = ZonedDateTime.parse(\"2010-04-05T17:16:00Z\", formatter);
I guess its the easiest way
回答12:
Since java 8 just use ZonedDateTime.parse(\"2010-04-05T17:16:00Z\")