0

According to Baeldung it is not possible to do this (Kotlin code):

DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ").format(Instant.ofEpochMilli(0L))

That is absolutely correct, as the execution results in:

java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: YearOfEra

As I understand an Instant, it is a moment in time, measured as the number of milliseconds since 1970-01-01T00:00:00.000Z. And the Instant's ms are specifically counted using UTC as a globally unique reference. So why can I not print an Instant in UTC?

I have found numerous examples online that state exactly the same as Baeldung, you need a time zone to format an Instant. For example this SO question. But none of them explain why it does not work. The only reason given is usually something along the lines of:

Without a time-zone, the formatter does not know how to convert the instant to human date-time fields.

That is not an answer to my question. I gave a pattern specifically stating UTC (Z), yet the formatting fails. Since an Instant contains UTC data, it should be able to be formatted as an ISO-8601 string. In this case the formatter should know how to convert the instant to human date-time fields.

I expect the above code to result in

"1970-01-01T00:00:00.000Z"

Why is this not the case? What is the design choice behind this?

AplusKminus
  • 1,542
  • 1
  • 19
  • 32
  • 3
    "why can I not print an Instant in UTC?" -- because you must tell that you want the time in UTC (not really a time zone, but the computer must know at which time zone or zone offset you want the time - the same instant has different readings around the world, and the specifiers or developers [apparently] preferred not to use/define a default if none is given) – user16320675 Aug 03 '23 at 20:43
  • There are (at least) 2 things I can think that line _might_ do (if it didn't throw an exception): it might print the time in UTC; it might print the time in the JVM's time zone. It's ambiguous, because you are passing it just "an instantaneous point on the time-line" - that is, a physical time - but you're asking it to print in a particular time zone - that is, a civil time. Rather than making an arbitrary choice about what you mean, the API forces you to _say_ what you mean. – Andy Turner Aug 03 '23 at 20:46
  • 1
    BTW, you can print an Instant to an ISO8601 string: just call `toString()` on it. – Andy Turner Aug 03 '23 at 20:47
  • 1
    BTW, or `DateTimeFormatter.ISO_INSTANT.format(Instant.ofEpochMilli(0L))` - see the [javadoc](https://docs.oracle.com/en/java/javase/20/docs/api/java.base/java/time/format/DateTimeFormatter.html#ISO_INSTANT) of `ISO_INSTANT`: "... The Instant class is designed to only represent a point in time and internally stores a value in nanoseconds from a fixed epoch of 1970-01-01Z. As such, an Instant cannot be formatted as a date or time without providing some form of time-zone. ... " – user16320675 Aug 03 '23 at 20:52
  • Does this answer your question? [UnsupportedTemporalTypeException when formatting Instant to String](https://stackoverflow.com/questions/25229124/unsupportedtemporaltypeexception-when-formatting-instant-to-string) – Turing85 Aug 03 '23 at 20:58
  • @Turing85, no it does not. I am specifically asking for why it doesn't work, not how to make it work. – AplusKminus Aug 03 '23 at 20:59
  • 2
    You just showed that you did not look at the post and its answers at all. The first paragraph of the accepted answer literally says; "*To format an `Instant` a time-zone is required. Without a time-zone, the formatter does not know how to convert the instant to human date-time fields, and therefore throws an exception.*" – Turing85 Aug 03 '23 at 21:00
  • 1
    I think my questions stems from a misunderstanding of the formatter patterns. I assumed that specifying 'Z' in the pattern would instruct the formatter to use UTC. If that is not the case then the linked answer makes sense and explains the situation. Since none of the provided comments highlight that fact, I believe this is worth a separate answer. – AplusKminus Aug 03 '23 at 21:11
  • Not really. The [documentation](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/text/SimpleDateFormat.html) is pretty clear on this: "*... Text can be quoted using single quotes (') to avoid interpretation. ...*" – Turing85 Aug 03 '23 at 21:17
  • The documentation states that the letter `Z` in a format string is for the timezone. I have corrected my question, as the quotations around the Z were mistaken. Yet, it still does not work. – AplusKminus Aug 03 '23 at 21:22
  • Please read the documentation, and read what `Z` in a format means. It boils down to this: to format a `Temporal`, the parser needs to know the timezone of the system it is operating on (or - at least - a timezone it should assume), even if the timezone for the specific format would not be necessary. – Turing85 Aug 03 '23 at 21:38
  • Yes, I did. I understand it now. Many questions on this site boil down to exactly that (explaining the documentation to the asking person). Could you please re-open the question so I can provide an appropriate answer? I think it would help others making the same mistake that I made. Because that mistake is not simply answered with the linked answer. If the assumption is that Z makes it UTC, then the linked answer doesn't help at all. My mistake was making that assumption, and I believe others might make the same. Isn't that what this site is about? Helping others learn from your own mistakes? – AplusKminus Aug 03 '23 at 21:57
  • I am voting to re-open. – Rohit Gupta Aug 13 '23 at 03:38

0 Answers0