NinjaMester
NinjaMester

Reputation: 73

Java 8 DateTimeFormatter: confusion with 'z' and 'Z ' pattern letters

I have the date string "2015-01-12T13:00:00.000+02:00". Looking at the JavaDoc I see the following:

z       time-zone name              zone-name         Pacific Standard Time; PST
Z       zone-offset                 offset-Z          +0000; -0800; -08:00;


So I would suspect that to parse it I would have to use upper-case 'Z' because I have the Zone format given in +02:00:

DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.000Z");

But with that I get a parse error.

If I use lower-case 'z' it works:

DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.000z")


Does anyone know what is going on?


CODE:

DateTimeFormatter changetimeParser_Z = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.000Z");
DateTimeFormatter changetimeParser_z = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.000z");

String time = "2015-01-12T13:00:00.000+02:00";

ZonedDateTime time1 = ZonedDateTime.parse(time, changetimeParser_z);
System.out.println(time1);
ZonedDateTime time2 = ZonedDateTime.parse(time, changetimeParser_Z);

System.out.println(time2);


Exception stack trace:

2015-01-12T13:00+02:00
java.time.format.DateTimeParseException: Text '2015-01-12T13:00:00.000+02:00' could not be parsed at index 23
    at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949)
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
    at java.time.ZonedDateTime.parse(ZonedDateTime.java:597)

Upvotes: 5

Views: 17673

Answers (2)

Arvind Kumar Avinash
Arvind Kumar Avinash

Reputation: 79580

You do not need a DateTimeFormatter

Your date-time string, 2015-01-12T13:00:00.000+02:00 is in the default format (based on ISO 8601 standard) used by OffsetDateTime#parse:

Obtains an instance of OffsetDateTime from a text string such as 2007-12-03T10:15:30+01:00.

So, you do not need to use a DateTimeFormatter explicitly.

What symbol should I use to parse a zone offset string?

You should use X to parse the zone offset in an offset-date-time string that is not in the default format.

Example of zone offset format Pattern
-08 X
-0830 XX
-08:30 XXX
-08:30:15 XXXXX

Check the documentation to learn more about it.

Demo:

class Main {
    public static void main(String args[]) {
        OffsetDateTime odt = OffsetDateTime.parse("2015-01-12T13:00:00.000+02:00");
        System.out.println(odt);

        // Examples of parsing an offset-date-time string that is not in the
        // default format:
        System.out.println(
                OffsetDateTime.parse("12/01/2015 13:00:00.000+02",
                        DateTimeFormatter.ofPattern("dd/MM/uuuu HH:mm:ss.SSSX")));
        System.out.println(
                OffsetDateTime.parse("12/01/2015 13:00:00.000+0200",
                        DateTimeFormatter.ofPattern("dd/MM/uuuu HH:mm:ss.SSSXX")));
        System.out.println(
                OffsetDateTime.parse("12/01/2015 13:00:00.000+02:00",
                        DateTimeFormatter.ofPattern("dd/MM/uuuu HH:mm:ss.SSSXXX")));
        System.out.println(
                OffsetDateTime.parse("12/01/2015 13:00:00.000-08:30:15",
                        DateTimeFormatter.ofPattern("dd/MM/uuuu HH:mm:ss.SSSXXXXX")));
    }
}

Output:

2015-01-12T13:00+02:00
2015-01-12T13:00+02:00
2015-01-12T13:00+02:00
2015-01-12T13:00+02:00
2015-01-12T13:00-08:30:15

Online Demo

Learn more about the modern Date-Time API from Trail: Date Time.

Upvotes: 3

SubOptimal
SubOptimal

Reputation: 22993

I would believe it's an error in the Javadoc and this part is a mistake

Symbol  Meaning                     Presentation      Examples<br>
------  -------                     ------------      -------
Z       zone-offset                 offset-Z          +0000; -0800; -08:00;

because if you read further you find the explanation of the offset Z

Offset Z: This formats the offset based on the number of pattern letters. One, two or three letters outputs the hour and minute, without a colon, such as '+0130'. The output will be '+0000' when the offset is zero. Four letters outputs the full form of localized offset, equivalent to four letters of Offset-O. The output will be the corresponding localized offset text if the offset is zero. Five letters outputs the hour, minute, with optional second if non-zero, with colon. It outputs 'Z' if the offset is zero. Six or more letters throws IllegalArgumentException.

Which complies RFC 822.

For me the pattern should behave same as for SimpleDateFormat

Upvotes: 7

Related Questions