2

An online API is requiring this format:

string

completion formatted as ISO 8601 timestamp - 'YYYY-MM-DDTHH:mm:ss.sssZ'
2018-11-21T22:38:15.000Z

I am trying to get any LocalDate at noon to satisfy the requirement, however, when Java looks at Noon or the start of day, it truncates the subseconds. For example:

DateTimeFormatter.ISO_DATE_TIME
                    .withZone(ZoneOffset.UTC)
                    .format(LocalDate.now().atTime(LocalTime.NOON).atZone(ZoneOffset.UTC))

produces:

2021-03-08T12:00:00Z

The api needs the subseconds. Is there a way for me to force the precision?

I tried building one:

DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ") but the Z is missing from the output.

trilogy
  • 1,738
  • 15
  • 31

3 Answers3

3

You can make use of your own DateTimeFormatter:

private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX");

And then use that to format your date:

ZonedDateTime zdt = LocalDate.now().atTime(LocalTime.NOON).atZone(ZoneOffset.UTC);
String formatted = DTF.format(zdt);
System.out.println(formatted); // 2021-03-08T12:00:00.000Z
Lino
  • 19,604
  • 6
  • 47
  • 65
  • I did try creating one... but yours uses a lower case Z ... it may solve my problem ... I'll try – trilogy Mar 08 '21 at 16:20
  • Can you explain what the difference between z and X ? – trilogy Mar 08 '21 at 16:26
  • 1
    @trilogy in your case it doesn't really make a difference. `z` prints the time zone name, whereas `X` will use values like `-08; -0830; -08:30;`, with the exception of UTC where it simply prints `Z` instead – Lino Mar 08 '21 at 16:28
  • We should use 'u' instead of 'y' as well? – trilogy Mar 08 '21 at 16:29
  • @trilogy You shouldn't care about `u`, unless you work with dates before the year `0` – Lino Mar 08 '21 at 16:32
  • z resulted in Z not GMT.... both worked in this case. – trilogy Mar 08 '21 at 16:34
  • @user15244370 – GMT? Or Europe/London (or something similar that has currently +00:00 off set to UTC)? – tquadrat Mar 08 '21 at 16:42
  • @user15244370 – Refer to https://stackoverflow.com/questions/7303580/understanding-the-etc-gmt-time-zone, first answer … you are on Etc/GMT time zone, not on GMT ... – tquadrat Mar 08 '21 at 16:45
1

What about using your own format instead of ISO_DATE_TIME?

Have look to DateTimeFormatterBuilder on how to build your own format with the required precision.

And by the way, the format you use does not truncate "the last 0", is just does not show the milliseconds ...

tquadrat
  • 3,033
  • 1
  • 16
  • 29
  • I tried building one, but the Z is missing `DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ` it provides an Offset of +00 instead – trilogy Mar 08 '21 at 16:17
  • The "Z" is the time zone ("Zulu Time" or UTC). And do not use `DateTimeFormatter.ofPattern()`, use the `DateTimeFormatterBuilder` … – tquadrat Mar 08 '21 at 16:22
  • I know what Z means.. but the api specifically wants the Z in the output. It is a UTC date. – trilogy Mar 08 '21 at 16:23
  • @tquadrat why shouldn't you use the `ofPattern` method? What is the advantage of using the builder? – Lino Mar 08 '21 at 16:24
  • @Lino – The builder gives you more control, what is helpful in *this* case. But in general you can also use the `ofPattern()` method when you are sure about the pattern. In particular with the time zone stuff, the pattern is … difficult sometimes. – tquadrat Mar 08 '21 at 16:30
0

No worries

LocalDateTime and ZonedDateTime have nanosecond precision always. So the milliseconds are not gone, they are just zero. And are not printed from toString() when they are zero.

Edit: I understand from your comment that the following paragraph does not apply to your situation. I am letting it stand for others to whom it may be useful. You most probably do not need to worry. Your API needs ISO 8601 format. In ISO 8601 the milliseconds (and smaller) are optional when they are zero. Most APIs that accept ISO 8601 (and all that I have met), also accept the string without the milliseconds.

Links

Related questions:

And the central link:

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • 1
    I did look at the Wiki article. I first thought the company wasn't following ISO 8601 by forcing the issue, but then I read in there: "However, the number of decimal places needs to be agreed to by the communicating parties. " ... The API rejected anything less than 3 decimal places... – trilogy Mar 09 '21 at 17:30