简体   繁体   中英

Convert ISO 8601 Date to a Standard String Format

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.

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, ie "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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM