What is the equivalent format string of DateTimeFormatter.ISO_OFFSET_DATE_TIME?
Asked Answered
P

2

12

Do we know if there is an equivalent format string that outputs the same result as DateTimeFormatter.ISO_OFFSET_DATE_TIME?

i.e.

ZonedDateTime dateTime = ZonedDateTime.now();
System.out.println(dateTime.format(DateTimeFormatter.ofPattern(pattern)));
System.out.println(dateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));

would output the same

Planck answered 3/10, 2018 at 3:39 Comment(8)
What have you tried, and in what way was that incorrect?Curve
@Curve I could get mostly the front parts right with "yyyy-MM-dd'T'HH:mm:ss" but the last bits I don't know how.Planck
pattern = "uuuu-MM-dd'T'HH:mm:ss.SSSSSSSXXX", but that is fixed at 7 fractional seconds. You can't get dynamic number of fractional seconds with a pattern.Curve
@Curve yes, the dynamic precision of ISO_OFFSET_DATE_TIME mainly why I couldn't get it right. Feel free to answer this question with a "No".Planck
@Curve can you explain why you need three X's? I don't understand this from the documentation. Why does one X not work here? Thanks - appreciate this is an old question but thought the context here warranted just a comment rather than a whole new question.Praetorian
@Praetorian That is because 1, 2, or 4 X's is the offset without colon, and 3, or 5 X's is the offset with colon (e.g. -0500 vs -05:00).Curve
@Curve thanks for responding. To clarify, are 1, 2 and 4 X’s interchangeable? i.e. they all mean the same? Are 3 and 5 also interchangeable? So in your response above you just chose the shortest possible correct amount of X’s?Praetorian
@Praetorian For parsing, correct, they are interchangeable.Curve
L
10

No, this is not possible

On request: Yes, we know that there is no equivalent format pattern string of DateTimeFormatter.ISO_OFFSET_DATE_TIME.

DateTimeFormatter.ISO_OFFSET_DATE_TIME omits the seconds and/or nano of second if they are zero. If the nanos are non-zero “As many digits will be output as required.” There is no pattern letter or combination of pattern letters that will give you the same behaviour.

Deep inside DateTimeFormatter, ISO_OFFSET_DATE_TIME uses an ISO_LOCAL_TIME, which in turn is defined in this way:

    ISO_LOCAL_TIME = new DateTimeFormatterBuilder()
            .appendValue(HOUR_OF_DAY, 2)
            .appendLiteral(':')
            .appendValue(MINUTE_OF_HOUR, 2)
            .optionalStart()
            .appendLiteral(':')
            .appendValue(SECOND_OF_MINUTE, 2)
            .optionalStart()
            .appendFraction(NANO_OF_SECOND, 0, 9, true)
            .toFormatter(ResolverStyle.STRICT, null);

Which is the way to obtain the dynamic behaviour: using a DateTimeFormatterBuilder and its optionalStart and appendFraction methods.

As an aside, you don’t want to copy the behaviour of ISO_OFFSET_DATE_TIME exactly. You will want to use the built-in formatter.

Lambertson answered 3/10, 2018 at 10:27 Comment(1)
Thanks for showing the behind the scene code as well!Planck
P
14

This worked for me:

    ZonedDateTime dateTime = ZonedDateTime.now();
    System.out.println(dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX")));
    System.out.println(dateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));

2018-10-03T07:24:14.772+03:00 
2018-10-03T07:24:14.772+03:00

Though it will not always produce the same result because ISO_OFFSET_DATE_TIME prints fraction of second with different length depending on nanos value, while .SSS has fixed lengh = 3

     ZonedDateTime dateTime = ZonedDateTime.of(2001, 1, 1, 0, 0, 0, 1, ZoneId.systemDefault());
     System.out.println(dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX")));
     System.out.println(dateTime.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));   

     2001-01-01T00:00:00.000+02:00
     2001-01-01T00:00:00.000000001+02:00
Poteet answered 3/10, 2018 at 4:26 Comment(3)
Thanks. I guess this is right about 90% but not when the milli second has trailing zeros.Planck
So if you believe there is no pattern that fully mimics ISO_OFFSET_DATE_TIME, feel free to answer "No" and I can accept yours as the answer.Planck
@Evgeniy Dorofeev Can you explain why you need three X's? I don't understand this from the documentation. Why does one X not work here? Thanks - appreciate this is an old question but thought the context here warranted just a comment rather than a whole new question.Praetorian
L
10

No, this is not possible

On request: Yes, we know that there is no equivalent format pattern string of DateTimeFormatter.ISO_OFFSET_DATE_TIME.

DateTimeFormatter.ISO_OFFSET_DATE_TIME omits the seconds and/or nano of second if they are zero. If the nanos are non-zero “As many digits will be output as required.” There is no pattern letter or combination of pattern letters that will give you the same behaviour.

Deep inside DateTimeFormatter, ISO_OFFSET_DATE_TIME uses an ISO_LOCAL_TIME, which in turn is defined in this way:

    ISO_LOCAL_TIME = new DateTimeFormatterBuilder()
            .appendValue(HOUR_OF_DAY, 2)
            .appendLiteral(':')
            .appendValue(MINUTE_OF_HOUR, 2)
            .optionalStart()
            .appendLiteral(':')
            .appendValue(SECOND_OF_MINUTE, 2)
            .optionalStart()
            .appendFraction(NANO_OF_SECOND, 0, 9, true)
            .toFormatter(ResolverStyle.STRICT, null);

Which is the way to obtain the dynamic behaviour: using a DateTimeFormatterBuilder and its optionalStart and appendFraction methods.

As an aside, you don’t want to copy the behaviour of ISO_OFFSET_DATE_TIME exactly. You will want to use the built-in formatter.

Lambertson answered 3/10, 2018 at 10:27 Comment(1)
Thanks for showing the behind the scene code as well!Planck

© 2022 - 2024 — McMap. All rights reserved.