问题
I am trying to convert a valid ISO 8601 string to a consistent format so that sort and search using simple lexicographical order is possible.
My application could receive a date/time in any of the following formats, for example:
2015-02-05T02:05:17.000+00:00
2015-02-05T02:05:17+00:00
2015-02-05T02:05:17Z
These all represent the same date/time and I would like to convert them all to a canonical form for storage, say:
2015-02-05T02:05:17.000Z
My first thought was to just parse them using a technique from Converting ISO 8601-compliant String to java.util.Date, and then convert back to the desired string, but this breaks down when dealing with less precise date/times, for example:
2015-02-05T02:05:17Z
2015-02-05T02:05Z
2015-02-05Z
2015-02Z
2015Z
The imprecision of these times should be preserved. They should not be converted to:
2015-02-05T00:00:00.000Z
I've looked Java 8 and Joda-Time, but they seem to want to treat everything as specific points in time, and can't model the imprecise nature or partial dates/times.
UPDATE:
Using Java 8, I can do:
OffsetDateTime dateTime = OffsetDateTime.parse("2015-02-05T02:05:17+00:00");
System.out.println(dateTime.toString());
which gives me:
2015-02-05T02:05:17Z
which is what I want, but:
OffsetDateTime dateTime = OffsetDateTime.parse("2015-02-05T02:05:17.000+00:00");
System.out.println(dateTime.toString());
also gives me:
2015-02-05T02:05:17Z
Notice that java has thrown away the millisecond precision. Specifying 000 is treated the same as not specifying anything, which doesn't seem quite right.
回答1:
In Java 8, you can use LocalDate.parse() or LocalDateTime.parse() on a String
without providing it with a pattern, if the String is in ISO 8601 format.
parse()
, Obtains an instance of LocalDate from a text string such as 2007-12-03. The string must represent a valid date and is parsed using DateTimeFormatter.ISO_LOCAL_DATE.
and,
DateTimeFormatter.ISO_LOCAL_DATE
, This returns an immutable formatter capable of formatting and parsing the ISO 8601
for example,
String strDate = "2015-08-04";
LocalDate aLD = LocalDate.parse(strDate);
System.out.println("Date: " + aLD);
String strDatewithTime = "2015-08-04T10:11:30";
LocalDateTime aLDT = LocalDateTime.parse(strDatewithTime);
System.out.println("Date with Time: " + aLDT);
gives,
Date: 2015-08-04
Date with Time: 2015-08-04T10:11:30
Update:
your date, i.e "2015-02-05T02:05:17.000+00:00"
would only throw zeros away when
they are all zeros, if the value of nano seconds is other than zeros then it will display just fine, however, if you want to display zeros too then you can simply add if/else
block and append zeros to your date if
your nano-of-seconds are zeros (yourdate.getNano()==0
), else
print it as it is,
String dateTimestr = "2015-02-05T02:05:17.000+00:00";
OffsetDateTime dateTime = OffsetDateTime.parse(dateTimestr);
if ((dateTime.getNano() == 0) && (dateTimestr.length() > 25 ))
System.out.println(dateTime.toLocalDateTime() + ".000Z");
else
System.out.println(dateTime.toString());
will give,
2015-02-05T02:05:17.000Z
changing your date to,
String dateTimestr = "2015-02-05T02:05:17+00:00";
gives,
2015-02-05T02:05:17Z
changing date to,
String dateTimestr = "2015-02-05T02:05:17.100+00:00";
gives,
2015-02-05T02:05:17.100Z
changing it to,
String dateTimestr = "2015-02-05T02:05:17Z";
gives,
2015-02-05T02:05:17Z
回答2:
You have to understand that the preservation of precision can only happen in textual space but not in value space. So a different degree of precision can be expressed in a textual way (see your input), but not in the value object (here of type OffsetDateTime
). Latter only stores the date-time-value but not any extra precision information. If you really want to achieve this goal then you have no other choice than to write your own class as wrapper around an OffsetDateTime
and the precision (expressed as ChronoUnit
-enum).
Otherwise, if you always want to preserve the precision in milliseconds for your output then you should not use the toString()
-method but a dedicated formatter. In Java-8 this would be like:
OffsetDateTime odt = OffsetDateTime.parse("2015-02-05T02:05:17+00:00");
String dateTimeWithMilliSecondPrecision =
odt.format(DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSxxx"));
System.out.println(dateTimeWithMilliSecondPrecision);
// output: 2015-02-05T02:05:17.000+00:00
来源:https://stackoverflow.com/questions/28352493/convert-iso-8601-date-to-a-standard-string-format