javadatetimedatetimeformatterjava.time.instant

Does Instant.MAX need to be manually formatted?


DateTimeFormatter fails on valid Instants. How it is meant to format those below and above LocalDateTime.MIN and LocalDateTime.MAX? Manually?

DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(ZoneOffset.UTC).format(Instant.MAX)

EDIT: For all future readers

The answer to this question is YES. It has to be done manually for the year of difference between LocalDateTime.MAX and Instant.MAX, and the same for the MIN range. Hence, Instants has to be manually kept inside LocalDateTime valid range if ofPattern() is involved.

EDIT: Exception Thrown

The expression throws a DateTimeException with the message Invalid value for EpochDay (valid values -365243219162 - 365241780471): 365241780837 and a stack trace like the following.

Exception in thread "main" java.time.DateTimeException: Invalid value for EpochDay (valid values -365243219162 - 365241780471): 365241780837
    at java.base/java.time.temporal.ValueRange.checkValidValue(ValueRange.java:319)
    at java.base/java.time.temporal.ChronoField.checkValidValue(ChronoField.java:721)
    at java.base/java.time.LocalDate.ofEpochDay(LocalDate.java:345)
    at java.base/java.time.LocalDateTime.ofEpochSecond(LocalDateTime.java:424)
    at java.base/java.time.ZonedDateTime.create(ZonedDateTime.java:458)
    at java.base/java.time.ZonedDateTime.ofInstant(ZonedDateTime.java:411)
    at java.base/java.time.chrono.IsoChronology.zonedDateTime(IsoChronology.java:401)
    at java.base/java.time.chrono.IsoChronology.zonedDateTime(IsoChronology.java:127)
    at java.base/java.time.format.DateTimePrintContext.adjust(DateTimePrintContext.java:150)
    at java.base/java.time.format.DateTimePrintContext.<init>(DateTimePrintContext.java:119)
    at java.base/java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:1903)
    at java.base/java.time.format.DateTimeFormatter.format(DateTimeFormatter.java:1879)
    at Main.main(Main.java:17)

Solution

  • tl;dr

    String result = Instant.MAX.truncatedTo( ChronoUnit.SECONDS ).toString().replace( "T" , " " ) ;
    

    Just an Instant, but with a large year number

    Instant.MAX is just an Instant object, like any other Instant object.

    ISO 8601

    You can generate text to represent its value merely by calling toString. The result is in standard ISO 8601 format. That would be: 1000000000-12-31T23:59:59.999999999Z. The Z is short for +00:00, meaning an offset from the temporal meridian of UTC of zero hours-minutes-seconds.

    Notice the year is 1,000,000,000. Your custom formatting pattern does not fit, having specified four digits rather than ten.

    String#replace

    If you want text without the T in the middle, the simplest solution is string manipulation.

    Instant.MAX.toString().replace( "T" , " " )
    

    Truncate

    If you don’t want the fractional second, truncate.

    Instant
        .MAX
        .truncatedTo( ChronoUnit.SECONDS )
        .toString()
        .replace( "T" , " " )