Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DateTimeFormatter.ISO_LOCAL_DATE vs DateTimeFormatter.ofPattern("yyyy-MM-dd") in Java 8+

I have a date I’ve created using ZonedDateTime.now(ZoneOffset.of("+2:00")).minusDays(5). Now I want to format it as yyyy-MM-dd.

In Java 8+, is DateTimeFormatter.ISO_LOCAL_DATE the equivalent of DateTimeFormatter.ofPattern("yyyy-MM-dd")?

The output appears identical and looks like, from the docs, they should be the same. However, the "LOCAL" part of that gave me pause. Notice I have an offset and I'm using ZonedDateTime. I wanted to make sure there were no any gotchas or "they're the same except under these special circumstances since you're dealing with offsets, etc".

like image 894
JL Gradley Avatar asked Dec 07 '17 15:12

JL Gradley


People also ask

What is the Java time format DateTimeFormatter?

format. DateTimeFormatterBuilder Class in Java. DateTimeFormatterBuilder Class is a builder class that is used to create date-time formatters. DateTimeFormatter is used as a Formatter for printing and parsing date-time objects.

What is the difference between DateTimeFormatter and SimpleDateFormat?

DateTimeFormatter is a replacement for the old SimpleDateFormat that is thread-safe and provides additional functionality.

What is ISO_LOCAL_DATE?

ISO_LOCAL_DATE. public static final DateTimeFormatter ISO_LOCAL_DATE. The ISO date formatter that formats or parses a date without an offset, such as '2011-12-03'. This returns an immutable formatter capable of formatting and parsing the ISO-8601 extended local date format.

Is DateTimeFormatter ofPattern thread-safe?

DateTimeFormatter is immutable and thread-safe. DateTimeFormatter formats a date-time using user defined format such as "yyyy-MMM-dd hh:mm:ss" or using predefined constants such as ISO_LOCAL_DATE_TIME. A DateTimeFormatter can be created with desired Locale, Chronology, ZoneId, and DecimalStyle.


1 Answers

For formatting a date-time denoting 5 days ago the two formatters will be equivalent. They will not be equivalent for all possible dates, neither for formatting nor for parsing.

Let’s try them out:

    DateTimeFormatter yyyyMmDd = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    int[] yearsToTest = { -900_000_000, -10_000, -2, 0, 1, 2017, 2099, 9999, 10_000, 900_000_000 };
    for (int year : yearsToTest) {
        LocalDate date = LocalDate.of(year, Month.DECEMBER, 2);
        String dateFormattedIso = date.format(DateTimeFormatter.ISO_LOCAL_DATE);
        String dateFormattedYyyyMmDd = date.format(yyyyMmDd);
        String diff = dateFormattedIso.equals(dateFormattedYyyyMmDd) ? "Same" : "Different";
        System.out.format("%-18s%-18s%s%n", dateFormattedIso, dateFormattedYyyyMmDd, diff);
    }

The above snippet prints:

-900000000-12-02  +900000001-12-02  Different
-10000-12-02      +10001-12-02      Different
-0002-12-02       0003-12-02        Different
0000-12-02        0001-12-02        Different
0001-12-02        0001-12-02        Same
2017-12-02        2017-12-02        Same
2099-12-02        2099-12-02        Same
9999-12-02        9999-12-02        Same
+10000-12-02      +10000-12-02      Same
+900000000-12-02  +900000000-12-02  Same

So for formatting it seems they are equivalent for years in the common era (“AD”), but not for years before the common era. yyyy respects that there is no year 0, so a year of 0 in the LocalDate is rendered as year 1. It is understood that it is BCE, this information is not printed. The ISO formatter takes the year literally, with sign and all.

You may obtain the behaviour of ISO_LOCAL_DATE by using uuuu instead of yyyy.

“Local” here just means without time zone, in turn meaning that the time zone information from your ZonedDateTime isn’t printed, which you wouldn’t have expected anyway.

like image 87
Ole V.V. Avatar answered Sep 22 '22 15:09

Ole V.V.