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

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
user1589188
  • 5,316
  • 17
  • 67
  • 130
  • 1
    What have you tried, and in what way was that incorrect? – Andreas Oct 03 '18 at 03:57
  • @Andreas 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. – user1589188 Oct 03 '18 at 04:07
  • 3
    `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. – Andreas Oct 03 '18 at 04:08
  • @Andreas 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". – user1589188 Oct 03 '18 at 04:28
  • 1
    @Andreas 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. – adrem7 Aug 09 '21 at 21:27
  • @adrem7 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`). – Andreas Sep 06 '21 at 09:01
  • @Andreas 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? – adrem7 Sep 07 '21 at 13:52
  • @adrem7 For parsing, correct, they are interchangeable. – Andreas Sep 08 '21 at 03:32

2 Answers2

13

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
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
  • Thanks. I guess this is right about 90% but not when the milli second has trailing zeros. – user1589188 Oct 03 '18 at 04:29
  • 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. – user1589188 Oct 03 '18 at 05:56
  • @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. – adrem7 Aug 09 '21 at 21:28
9

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.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161