ThreeTen / threeten

This project was the home of code used to develop a modern date and time library for JDK8. Development has moved to OpenJDK and a separate backport project, threetenbp.
http://threeten.github.io/
191 stars 37 forks source link

Standard formatters should have ISO chronology set #295

Closed jodastephen closed 11 years ago

jodastephen commented 11 years ago

The standard formatters, which are most of the static methods on DTFormatter, such as ISO_LOCAL_DATE, are all intended for use with ISO. However, passing a FooDate to the formatter does not by default do any conversion.

Change the formatters to have the equivalent of f.withChronology(ISOChronology.INSTANCE) setup.

jodastephen commented 11 years ago
# HG changeset patch
# User scolebourne
# Date 1364778004 -3600
# Node ID 9acd8d0c39dc4a09b61218955acf67bb93775054
# Parent  2cc0378b496358f2f5a82a4f40b66c127e1f8258
Ensure that standard ISO formatters actually are ISO by default

See #295

diff -r 2cc0378b4963 -r 9acd8d0c39dc src/share/classes/java/time/format/DateTimeFormatter.java
--- a/src/share/classes/java/time/format/DateTimeFormatter.java Mon Apr 01 01:59:00 2013 +0100
+++ b/src/share/classes/java/time/format/DateTimeFormatter.java Mon Apr 01 02:00:04 2013 +0100
@@ -491,7 +491,7 @@

     //-----------------------------------------------------------------------
     /**
-     * Returns a locale specific date format.
+     * Returns a locale specific date format for the ISO chronology.
      * <p>
      * This returns a formatter that will format or parse a date.
      * The exact format pattern used varies by locale.
@@ -504,17 +504,21 @@
      * Note that the localized pattern is looked up lazily.
      * This {@code DateTimeFormatter} holds the style required and the locale,
      * looking up the pattern required on demand.
+     * <p>
+     * The returned formatter has a chronology of ISO set to ensure dates in
+     * other calendar systems are correctly converted.
+     * The chronology is visible via {@link DateTimeFormatter#getChronology()}.
      *
      * @param dateStyle  the formatter style to obtain, not null
      * @return the date formatter, not null
      */
     public static DateTimeFormatter ofLocalizedDate(FormatStyle dateStyle) {
         Objects.requireNonNull(dateStyle, "dateStyle");
-        return new DateTimeFormatterBuilder().appendLocalized(dateStyle, null).toFormatter();
+        return new DateTimeFormatterBuilder().appendLocalized(dateStyle, null).toFormatterIso();
     }

     /**
-     * Returns a locale specific time format.
+     * Returns a locale specific time format for the ISO chronology.
      * <p>
      * This returns a formatter that will format or parse a time.
      * The exact format pattern used varies by locale.
@@ -527,18 +531,21 @@
      * Note that the localized pattern is looked up lazily.
      * This {@code DateTimeFormatter} holds the style required and the locale,
      * looking up the pattern required on demand.
+     * <p>
+     * The returned formatter has a chronology of ISO set to ensure dates in
+     * other calendar systems are correctly converted.
+     * The chronology is visible via {@link DateTimeFormatter#getChronology()}.
      *
      * @param timeStyle  the formatter style to obtain, not null
      * @return the time formatter, not null
      */
     public static DateTimeFormatter ofLocalizedTime(FormatStyle timeStyle) {
         Objects.requireNonNull(timeStyle, "timeStyle");
-        return new DateTimeFormatterBuilder().appendLocalized(null, timeStyle).toFormatter();
+        return new DateTimeFormatterBuilder().appendLocalized(null, timeStyle).toFormatterIso();
     }

     /**
-     * Returns a locale specific date-time formatter, which is typically of
-     * short length.
+     * Returns a locale specific date-time formatter for the ISO chronology.
      * <p>
      * This returns a formatter that will format or parse a date-time.
      * The exact format pattern used varies by locale.
@@ -551,17 +558,21 @@
      * Note that the localized pattern is looked up lazily.
      * This {@code DateTimeFormatter} holds the style required and the locale,
      * looking up the pattern required on demand.
+     * <p>
+     * The returned formatter has a chronology of ISO set to ensure dates in
+     * other calendar systems are correctly converted.
+     * The chronology is visible via {@link DateTimeFormatter#getChronology()}.
      *
      * @param dateTimeStyle  the formatter style to obtain, not null
      * @return the date-time formatter, not null
      */
     public static DateTimeFormatter ofLocalizedDateTime(FormatStyle dateTimeStyle) {
         Objects.requireNonNull(dateTimeStyle, "dateTimeStyle");
-        return new DateTimeFormatterBuilder().appendLocalized(dateTimeStyle, dateTimeStyle).toFormatter();
+        return new DateTimeFormatterBuilder().appendLocalized(dateTimeStyle, dateTimeStyle).toFormatterIso();
     }

     /**
-     * Returns a locale specific date and time format.
+     * Returns a locale specific date and time format for the ISO chronology.
      * <p>
      * This returns a formatter that will format or parse a date-time.
      * The exact format pattern used varies by locale.
@@ -574,6 +585,10 @@
      * Note that the localized pattern is looked up lazily.
      * This {@code DateTimeFormatter} holds the style required and the locale,
      * looking up the pattern required on demand.
+     * <p>
+     * The returned formatter has a chronology of ISO set to ensure dates in
+     * other calendar systems are correctly converted.
+     * The chronology is visible via {@link DateTimeFormatter#getChronology()}.
      *
      * @param dateStyle  the date formatter style to obtain, not null
      * @param timeStyle  the time formatter style to obtain, not null
@@ -582,7 +597,7 @@
     public static DateTimeFormatter ofLocalizedDateTime(FormatStyle dateStyle, FormatStyle timeStyle) {
         Objects.requireNonNull(dateStyle, "dateStyle");
         Objects.requireNonNull(timeStyle, "timeStyle");
-        return new DateTimeFormatterBuilder().appendLocalized(dateStyle, timeStyle).toFormatter();
+        return new DateTimeFormatterBuilder().appendLocalized(dateStyle, timeStyle).toFormatterIso();
     }

     //-----------------------------------------------------------------------
@@ -604,6 +619,10 @@
      * <li>Two digits for the {@link ChronoField#DAY_OF_MONTH day-of-month}.
      *  This is pre-padded by zero to ensure two digits.
      * </ul>
+     * <p>
+     * The returned formatter has a chronology of ISO set to ensure dates in
+     * other calendar systems are correctly converted.
+     * The chronology is visible via {@link DateTimeFormatter#getChronology()}.
      */
     public static final DateTimeFormatter ISO_LOCAL_DATE;
     static {
@@ -613,7 +632,7 @@
                 .appendValue(MONTH_OF_YEAR, 2)
                 .appendLiteral('-')
                 .appendValue(DAY_OF_MONTH, 2)
-                .toFormatter();
+                .toFormatterIso();
     }

     //-----------------------------------------------------------------------
@@ -630,6 +649,10 @@
      *  they will be handled even though this is not part of the ISO-8601 standard.
      *  Parsing is case insensitive.
      * </ul>
+     * <p>
+     * The returned formatter has a chronology of ISO set to ensure dates in
+     * other calendar systems are correctly converted.
+     * The chronology is visible via {@link DateTimeFormatter#getChronology()}.
      */
     public static final DateTimeFormatter ISO_OFFSET_DATE;
     static {
@@ -637,7 +660,7 @@
                 .parseCaseInsensitive()
                 .append(ISO_LOCAL_DATE)
                 .appendOffsetId()
-                .toFormatter();
+                .toFormatterIso();
     }

     //-----------------------------------------------------------------------
@@ -658,6 +681,10 @@
      * <p>
      * As this formatter has an optional element, it may be necessary to parse using
      * {@link DateTimeFormatter#parseBest}.
+     * <p>
+     * The returned formatter has a chronology of ISO set to ensure dates in
+     * other calendar systems are correctly converted.
+     * The chronology is visible via {@link DateTimeFormatter#getChronology()}.
      */
     public static final DateTimeFormatter ISO_DATE;
     static {
@@ -666,7 +693,7 @@
                 .append(ISO_LOCAL_DATE)
                 .optionalStart()
                 .appendOffsetId()
-                .toFormatter();
+                .toFormatterIso();
     }

     //-----------------------------------------------------------------------
@@ -773,6 +800,10 @@
      * <li>The letter 'T'. Parsing is case insensitive.
      * <li>The {@link #ISO_LOCAL_TIME}
      * </ul>
+     * <p>
+     * The returned formatter has a chronology of ISO set to ensure dates in
+     * other calendar systems are correctly converted.
+     * The chronology is visible via {@link DateTimeFormatter#getChronology()}.
      */
     public static final DateTimeFormatter ISO_LOCAL_DATE_TIME;
     static {
@@ -781,7 +812,7 @@
                 .append(ISO_LOCAL_DATE)
                 .appendLiteral('T')
                 .append(ISO_LOCAL_TIME)
-                .toFormatter();
+                .toFormatterIso();
     }

     //-----------------------------------------------------------------------
@@ -798,6 +829,10 @@
      *  they will be handled even though this is not part of the ISO-8601 standard.
      *  Parsing is case insensitive.
      * </ul>
+     * <p>
+     * The returned formatter has a chronology of ISO set to ensure dates in
+     * other calendar systems are correctly converted.
+     * The chronology is visible via {@link DateTimeFormatter#getChronology()}.
      */
     public static final DateTimeFormatter ISO_OFFSET_DATE_TIME;
     static {
@@ -805,7 +840,7 @@
                 .parseCaseInsensitive()
                 .append(ISO_LOCAL_DATE_TIME)
                 .appendOffsetId()
-                .toFormatter();
+                .toFormatterIso();
     }

     //-----------------------------------------------------------------------
@@ -826,6 +861,10 @@
      *  Parsing is case sensitive.
      * <li>A close square bracket ']'.
      * </ul>
+     * <p>
+     * The returned formatter has a chronology of ISO set to ensure dates in
+     * other calendar systems are correctly converted.
+     * The chronology is visible via {@link DateTimeFormatter#getChronology()}.
      */
     public static final DateTimeFormatter ISO_ZONED_DATE_TIME;
     static {
@@ -836,7 +875,7 @@
                 .parseCaseSensitive()
                 .appendZoneRegionId()
                 .appendLiteral(']')
-                .toFormatter();
+                .toFormatterIso();
     }

     //-----------------------------------------------------------------------
@@ -863,6 +902,10 @@
      * <p>
      * As this formatter has an optional element, it may be necessary to parse using
      * {@link DateTimeFormatter#parseBest}.
+     * <p>
+     * The returned formatter has a chronology of ISO set to ensure dates in
+     * other calendar systems are correctly converted.
+     * The chronology is visible via {@link DateTimeFormatter#getChronology()}.
      */
     public static final DateTimeFormatter ISO_DATE_TIME;
     static {
@@ -875,7 +918,7 @@
                 .parseCaseSensitive()
                 .appendZoneRegionId()
                 .appendLiteral(']')
-                .toFormatter();
+                .toFormatterIso();
     }

     //-----------------------------------------------------------------------
@@ -901,6 +944,10 @@
      * <p>
      * As this formatter has an optional element, it may be necessary to parse using
      * {@link DateTimeFormatter#parseBest}.
+     * <p>
+     * The returned formatter has a chronology of ISO set to ensure dates in
+     * other calendar systems are correctly converted.
+     * The chronology is visible via {@link DateTimeFormatter#getChronology()}.
      */
     public static final DateTimeFormatter ISO_ORDINAL_DATE;
     static {
@@ -911,7 +958,7 @@
                 .appendValue(DAY_OF_YEAR, 3)
                 .optionalStart()
                 .appendOffsetId()
-                .toFormatter();
+                .toFormatterIso();
     }

     //-----------------------------------------------------------------------
@@ -941,6 +988,10 @@
      * <p>
      * As this formatter has an optional element, it may be necessary to parse using
      * {@link DateTimeFormatter#parseBest}.
+     * <p>
+     * The returned formatter has a chronology of ISO set to ensure dates in
+     * other calendar systems are correctly converted.
+     * The chronology is visible via {@link DateTimeFormatter#getChronology()}.
      */
     public static final DateTimeFormatter ISO_WEEK_DATE;
     static {
@@ -953,7 +1004,7 @@
                 .appendValue(DAY_OF_WEEK, 1)
                 .optionalStart()
                 .appendOffsetId()
-                .toFormatter();
+                .toFormatterIso();
     }

     //-----------------------------------------------------------------------
@@ -1010,6 +1061,10 @@
      * <p>
      * As this formatter has an optional element, it may be necessary to parse using
      * {@link DateTimeFormatter#parseBest}.
+     * <p>
+     * The returned formatter has a chronology of ISO set to ensure dates in
+     * other calendar systems are correctly converted.
+     * The chronology is visible via {@link DateTimeFormatter#getChronology()}.
      */
     public static final DateTimeFormatter BASIC_ISO_DATE;
     static {
@@ -1020,7 +1075,7 @@
                 .appendValue(DAY_OF_MONTH, 2)
                 .optionalStart()
                 .appendOffset("+HHMMss", "Z")
-                .toFormatter();
+                .toFormatterIso();
     }

     //-----------------------------------------------------------------------
@@ -1062,6 +1117,10 @@
      * </ul>
      * <p>
      * Parsing is case insensitive.
+     * <p>
+     * The returned formatter has a chronology of ISO set to ensure dates in
+     * other calendar systems are correctly converted.
+     * The chronology is visible via {@link DateTimeFormatter#getChronology()}.
      */
     public static final DateTimeFormatter RFC_1123_DATE_TIME;
     static {
@@ -1110,7 +1169,7 @@
                 .optionalEnd()
                 .appendLiteral(' ')
                 .appendOffset("+HHMM", "GMT")  // should handle UT/Z/EST/EDT/CST/CDT/MST/MDT/PST/MDT
-                .toFormatter();
+                .toFormatterIso();
     }

     /**
diff -r 2cc0378b4963 -r 9acd8d0c39dc src/share/classes/java/time/format/DateTimeFormatterBuilder.java
--- a/src/share/classes/java/time/format/DateTimeFormatterBuilder.java  Mon Apr 01 01:59:00 2013 +0100
+++ b/src/share/classes/java/time/format/DateTimeFormatterBuilder.java  Mon Apr 01 02:00:04 2013 +0100
@@ -1892,7 +1892,8 @@

     //-----------------------------------------------------------------------
     /**
-     * Completes this builder by creating the DateTimeFormatter using the default locale.
+     * Completes this builder by creating the {@code DateTimeFormatter}
+     * using the default locale.
      * <p>
      * This will create a formatter with the {@link Locale#getDefault(Locale.Category) default FORMAT locale}.
      * Numbers will be printed and parsed using the standard non-localized set of symbols.
@@ -1906,11 +1907,12 @@
      * @return the created formatter, not null
      */
     public DateTimeFormatter toFormatter() {
-        return toFormatter(Locale.getDefault(Locale.Category.FORMAT));
+        return toFormatter(Locale.getDefault(Locale.Category.FORMAT), null);
     }

     /**
-     * Completes this builder by creating the DateTimeFormatter using the specified locale.
+     * Completes this builder by creating the {@code DateTimeFormatter}
+     * using the specified locale.
      * <p>
      * This will create a formatter with the specified locale.
      * Numbers will be printed and parsed using the standard non-localized set of symbols.
@@ -1925,12 +1927,43 @@
      * @return the created formatter, not null
      */
     public DateTimeFormatter toFormatter(Locale locale) {
+        return toFormatter(locale, null);
+    }
+
+    /**
+     * Completes this builder by creating the {@code DateTimeFormatter}
+     * using the default locale and setting the chronlogy to ISO.
+     * <p>
+     * This will create a formatter with the {@link Locale#getDefault(Locale.Category) default FORMAT locale}.
+     * Numbers will be printed and parsed using the standard non-localized set of symbols.
+     * The chronology will be set to ISO.
+     * <p>
+     * Calling this method will end any open optional sections by repeatedly
+     * calling {@link #optionalEnd()} before creating the formatter.
+     * <p>
+     * This builder can still be used after creating the formatter if desired,
+     * although the state may have been changed by calls to {@code optionalEnd}.
+     *
+     * @return the created formatter, not null
+     */
+    DateTimeFormatter toFormatterIso() {
+        return toFormatter(Locale.getDefault(Locale.Category.FORMAT), IsoChronology.INSTANCE);
+    }
+
+    /**
+     * Completes this builder by creating the formatter.
+     *
+     * @param locale  the locale to use for formatting, not null
+     * @param chrono  the chronology to use, may be null
+     * @return the created formatter, not null
+     */
+    private DateTimeFormatter toFormatter(Locale locale, Chronology chrono) {
         Objects.requireNonNull(locale, "locale");
         while (active.parent != null) {
             optionalEnd();
         }
         CompositePrinterParser pp = new CompositePrinterParser(printerParsers, false);
-        return new DateTimeFormatter(pp, resolveFields, locale, DateTimeFormatSymbols.STANDARD, null, null);
+        return new DateTimeFormatter(pp, resolveFields, locale, DateTimeFormatSymbols.STANDARD, chrono, null);
     }

     //-----------------------------------------------------------------------
diff -r 2cc0378b4963 -r 9acd8d0c39dc test/java/time/tck/java/time/format/TCKDateTimeFormatters.java
--- a/test/java/time/tck/java/time/format/TCKDateTimeFormatters.java    Mon Apr 01 01:59:00 2013 +0100
+++ b/test/java/time/tck/java/time/format/TCKDateTimeFormatters.java    Mon Apr 01 02:00:04 2013 +0100
@@ -84,8 +84,10 @@
 import java.time.ZoneOffset;
 import java.time.ZonedDateTime;
 import java.time.chrono.Chronology;
+import java.time.chrono.IsoChronology;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeParseException;
+import java.time.format.FormatStyle;
 import java.time.format.TextStyle;
 import java.time.temporal.IsoFields;
 import java.time.temporal.TemporalAccessor;
@@ -165,6 +167,29 @@
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
+    @Test
+    public void test_ofLocalizedDate_chronology() {
+        assertEquals(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).getChronology(), IsoChronology.INSTANCE);
+    }
+
+    @Test
+    public void test_ofLocalizedTime_chronology() {
+        assertEquals(DateTimeFormatter.ofLocalizedTime(FormatStyle.FULL).getChronology(), IsoChronology.INSTANCE);
+    }
+
+    @Test
+    public void test_ofLocalizedDateTime1_chronology() {
+        assertEquals(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).getChronology(), IsoChronology.INSTANCE);
+    }
+
+    @Test
+    public void test_ofLocalizedDateTime2_chronology() {
+        assertEquals(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL, FormatStyle.MEDIUM).getChronology(), IsoChronology.INSTANCE);
+    }
+
+    //-----------------------------------------------------------------------
+    //-----------------------------------------------------------------------
+    //-----------------------------------------------------------------------
     @DataProvider(name="sample_isoLocalDate")
     Object[][] provider_sample_isoLocalDate() {
         return new Object[][]{
@@ -249,6 +274,11 @@
         LocalDate.parse("-1000000000-08-06");
     }

+    @Test
+    public void test_isoLocalDate_chronology() {
+        assertEquals(DateTimeFormatter.ISO_LOCAL_DATE.getChronology(), IsoChronology.INSTANCE);
+    }
+
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
@@ -300,6 +330,11 @@
         }
     }

+    @Test
+    public void test_isoOffsetDate_chronology() {
+        assertEquals(DateTimeFormatter.ISO_OFFSET_DATE.getChronology(), IsoChronology.INSTANCE);
+    }
+
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
@@ -353,6 +388,11 @@
         }
     }

+    @Test
+    public void test_isoDate_chronology() {
+        assertEquals(DateTimeFormatter.ISO_DATE.getChronology(), IsoChronology.INSTANCE);
+    }
+
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
@@ -416,6 +456,11 @@
         }
     }

+    @Test
+    public void test_isoLocalTime_chronology() {
+        assertEquals(DateTimeFormatter.ISO_LOCAL_TIME.getChronology(), null);
+    }
+
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
@@ -479,6 +524,11 @@
         }
     }

+    @Test
+    public void test_isoOffsetTime_chronology() {
+        assertEquals(DateTimeFormatter.ISO_OFFSET_TIME.getChronology(), null);
+    }
+
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
@@ -544,6 +594,11 @@
         }
     }

+    @Test
+    public void test_isoTime_chronology() {
+        assertEquals(DateTimeFormatter.ISO_TIME.getChronology(), null);
+    }
+
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
@@ -616,6 +671,11 @@
         }
     }

+    @Test
+    public void test_isoLocalDateTime_chronology() {
+        assertEquals(DateTimeFormatter.ISO_LOCAL_DATE_TIME.getChronology(), IsoChronology.INSTANCE);
+    }
+
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
@@ -689,6 +749,11 @@
         }
     }

+    @Test
+    public void test_isoOffsetDateTime_chronology() {
+        assertEquals(DateTimeFormatter.ISO_OFFSET_DATE_TIME.getChronology(), IsoChronology.INSTANCE);
+    }
+
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
@@ -775,6 +840,11 @@
         }
     }

+    @Test
+    public void test_isoZonedDateTime_chronology() {
+        assertEquals(DateTimeFormatter.ISO_ZONED_DATE_TIME.getChronology(), IsoChronology.INSTANCE);
+    }
+
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
@@ -853,6 +923,11 @@
         }
     }

+    @Test
+    public void test_isoDateTime_chronology() {
+        assertEquals(DateTimeFormatter.ISO_DATE_TIME.getChronology(), IsoChronology.INSTANCE);
+    }
+
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
@@ -921,6 +996,11 @@
         assertParseMatch(DateTimeFormatter.ISO_ORDINAL_DATE.parseUnresolved("+123456-123", new ParsePosition(0)), expected);
     }

+    @Test
+    public void test_isoOrdinalDate_chronology() {
+        assertEquals(DateTimeFormatter.ISO_ORDINAL_DATE.getChronology(), IsoChronology.INSTANCE);
+    }
+
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
@@ -979,6 +1059,11 @@
         }
     }

+    @Test
+    public void test_basicIsoDate_chronology() {
+        assertEquals(DateTimeFormatter.BASIC_ISO_DATE.getChronology(), IsoChronology.INSTANCE);
+    }
+
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
@@ -1052,6 +1137,11 @@
         assertEquals(parsed.getLong(DAY_OF_WEEK), 5L);
     }

+    @Test
+    public void test_isoWeekDate_chronology() {
+        assertEquals(DateTimeFormatter.ISO_WEEK_DATE.getChronology(), IsoChronology.INSTANCE);
+    }
+
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
@@ -1083,6 +1173,11 @@
         DateTimeFormatter.RFC_1123_DATE_TIME.format(test);
     }

+    @Test
+    public void test_rfc1123_chronology() {
+        assertEquals(DateTimeFormatter.RFC_1123_DATE_TIME.getChronology(), IsoChronology.INSTANCE);
+    }
+
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
     //-----------------------------------------------------------------------
jodastephen commented 11 years ago

Fixed in http://hg.openjdk.java.net/threeten/threeten/jdk/rev/9acd8d0c39dc