Closed jodastephen closed 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);
+ }
+
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
The standard formatters, which are most of the static methods on
DTFormatter
, such asISO_LOCAL_DATE
, are all intended for use with ISO. However, passing aFooDate
to the formatter does not by default do any conversion.Change the formatters to have the equivalent of
f.withChronology(ISOChronology.INSTANCE)
setup.