1

I'm trying to create the ISO 8601 formatted DateTime from the Instant object as per the reference in this article I used the format YYYY-MM-DD'T'hh:mm:ss'T'ZD to parse the Instant date as below.

But it's generating the time in wrong format:

2022-06-172T06:08:13T-0500172

The expected format should be:

2022-06-21T13:31:49-05:00

My code:

DateTimeFormatter formatter = DateTimeFormatter
            .ofPattern("YYYY-MM-DD'T'hh:mm:ss'T'ZD")
            .withZone(ZoneId.systemDefault());

formatter.format(Instant.now())

How can I produce the formatted time as shown below?

2022-06-21T13:31:49-05:00
Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
OTUser
  • 3,788
  • 19
  • 69
  • 127
  • Check out the [`DateTimeFormatter` docs](https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html) to see what `Y`, `D` and `h` mean. In any case, it looks like you're looking for the default format used by `parse()` and `toString()`, so the custom formatter is unnecessary. – shmosel Jun 21 '22 at 23:25
  • How far away are you with `System.out.println(ZonedDateTime.now());` ? – g00se Jun 21 '22 at 23:34
  • @g00se Not exactly. Time representation will not match, and there would be a time-zone ID (which OP doesn't need) after the zone-offset. – Alexander Ivanchenko Jun 22 '22 at 00:40

2 Answers2

5

tl;dr

help with producing the time formatted as 2022-06-21T13:31:49-05:00

OffsetDateTime.now().toString()

2022-06-22T04:38:55.902569200+03:00

ISO 8601

No need to define a formatting pattern.

Your desired output complies with ISO 8601 standard of date-time formats. The java.time classes use these standard formats by default when parsing/generating text.

OffsetDateTime

To represent a moment as seen in a particular offset, use OffsetDateTime.

OffsetDateTime odt = OffsetDateTime.now() ;

Generate your text by calling toString.

String output = odt.toString() ;

2022-06-22T04:38:55.902569200+03:00

If you want to discard the fractional second, truncate.

OffsetDateTime
.now()
.truncatedTo( ChronoUnit.SECONDS )
.toString()

2022-06-22T04:38:55+03:00

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
3

I guess the pattern you need is "yyyy-MM-dd'T'hh:mm:ssxxx"

  • y - year (not Y - week-based-year);
  • d - day of the month (not D - day of the year);
  • x - zone-offset (not ZD);
  • There's no need in T in the end if you don't want it to be present in the formatted string.

Quote from the documentation regarding the zone-offset formatting:

Offset X and x: This formats the offset based on the number of pattern letters. One letter outputs just the hour, such as '+01', unless the minute is non-zero in which case the minute is also output, such as '+0130'. Two letters outputs the hour and minute, without a colon, such as '+0130'. Three letters outputs the hour and minute, with a colon, such as +01:30.

DateTimeFormatter formatter = DateTimeFormatter
    .ofPattern("yyyy-MM-dd'T'hh:mm:ssxxx")
    .withZone(ZoneId.systemDefault());
    
System.out.println(formatter.format(Instant.now()));

Output:

2022-06-22T03:05:43+03:00
Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
  • Thanks for the answer, Its pretty close but the expected output should have a colon in the timezone `2022-06-22T02:41:51+03:00` – OTUser Jun 21 '22 at 23:46
  • 1
    @OTUser I've managed to format the zone offset with a colon. – Alexander Ivanchenko Jun 22 '22 at 00:12
  • This is the correct answer. Lowercase `dd` instead of `DD` sets the pattern as you expect. As @AlexanderIvanchenko said, the uppercase `D` represents day of the year`. The lowercase `d` represents day of the month. This should be the excepted answer. – tbatch Aug 30 '22 at 20:58