diff -r 35cd9b3a98ff -r 8c100beabcc0 jdk/src/share/classes/java/time/format/DateTimeFormatter.java --- a/jdk/src/share/classes/java/time/format/DateTimeFormatter.java Wed May 15 15:01:59 2013 +0100 +++ b/jdk/src/share/classes/java/time/format/DateTimeFormatter.java Wed May 15 07:48:57 2013 -0700 @@ -77,6 +77,7 @@ import java.text.ParseException; import java.text.ParsePosition; import java.time.DateTimeException; +import java.time.Period; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.chrono.Chronology; @@ -121,7 +122,7 @@ * *
* In addition to the format, formatters can be created with desired Locale, - * Chronology, ZoneId, and formatting symbols. + * Chronology, ZoneId, and DecimalStyle. *
* The {@link #withLocale withLocale} method returns a new formatter that * overrides the locale. The locale affects some aspects of formatting and @@ -138,8 +139,8 @@ * with the requested ZoneId before formatting. During parsing the ZoneId is * applied before the value is returned. *
- * The {@link #withSymbols withSymbols} method returns a new formatter that - * overrides the {@link DateTimeFormatSymbols}. The symbols are used for + * The {@link #withDecimalStyle withDecimalStyle} method returns a new formatter that + * overrides the {@link DecimalStyle}. The DecimalStyle symbols are used for * formatting and parsing. *
* Some applications may need to use the older {@link Format java.text.Format} @@ -417,7 +418,65 @@ * that you want to output directly to ensure that future changes do not break * your application. * - *
+ * Five parsing methods are supplied by this class. + * Four of these perform both the parse and resolve phases. + * The fifth method, {@link #parseUnresolved(CharSequence, ParsePosition)}, + * only performs the first phase, leaving the result unresolved. + * As such, it is essentially a low-level operation. + *
+ * The resolve phase is controlled by two parameters, set on this class. + *
+ * The {@link ResolverStyle} is an enum that offers three different approaches, + * strict, smart and lenient. The smart option is the default. + * It can be set using {@link #withResolverStyle(ResolverStyle)}. + *
+ * The {@link #withResolverFields(TemporalField...)} parameter allows the + * set of fields that will be resolved to be filtered before resolving starts. + * For example, if the formatter has parsed a year, month, day-of-month + * and day-of-year, then there are two approaches to resolve a date: + * (year + month + day-of-month) and (year + day-of-year). + * The resolver fields allows one of the two approaches to be selected. + * If no resolver fields are set then both approaches must result in the same date. + *
+ * Resolving separate fields to form a complete date and time is a complex + * process with behaviour distributed across a number of classes. + * It follows these steps: + *
* This returns an immutable formatter capable of formatting and parsing * the ISO-8601 instant format. + * When formatting, the second-of-minute is always output. + * The nano-of-second outputs zero, three, six or nine digits digits as necessary. + * When parsing, time to at least the seconds field is required. + * Fractional seconds from zero to nine are parsed. + * The localized decimal style is not used. *
* This is a special case formatter intended to allow a human readable form * of an {@link java.time.Instant}. The {@code Instant} class is designed to @@ -1201,25 +1265,117 @@ .toFormatter(ResolverStyle.SMART, IsoChronology.INSTANCE); } + //----------------------------------------------------------------------- + /** + * A query that provides access to the excess days that were parsed. + *
+ * This returns a singleton {@linkplain TemporalQuery query} that provides + * access to additional information from the parse. The query always returns + * a non-null period, with a zero period returned instead of null. + *
+ * There are two situations where this query may return a non-zero period. + *
+ *
+ * In both cases, if a complete {@code ChronoLocalDateTime} or {@code Instant} + * is parsed, then the excess days are added to the date part. + * As a result, this query will return a zero period. + *
+ * The {@code SMART} behaviour handles the common "end of day" 24:00 value. + * Processing in {@code LENIENT} mode also produces the same result: + *
+ * Text to parse Parsed object Excess days + * "2012-12-03T00:00" LocalDateTime.of(2012, 12, 3, 0, 0) ZERO + * "2012-12-03T24:00" LocalDateTime.of(2012, 12, 4, 0, 0) ZERO + * "00:00" LocalTime.of(0, 0) ZERO + * "24:00" LocalTime.of(0, 0) Period.ofDays(1) + *+ * The query can be used as follows: + *
+ * TemporalAccessor parsed = formatter.parse(str); + * LocalTime time = parsed.query(LocalTime::from); + * Period extraDays = parsed.query(DateTimeFormatter.parsedExcessDays()); + *+ */ + public static final TemporalQuery
+ * This returns a singleton {@linkplain TemporalQuery query} that provides + * access to additional information from the parse. The query always returns + * a non-null boolean, true if parsing saw a leap-second, false if not. + *
+ * Instant parsing handles the special "leap second" time of '23:59:60'. + * Leap seconds occur at '23:59:60' in the UTC time-zone, but at other + * local times in different time-zones. To avoid this potential ambiguity, + * the handling of leap-seconds is limited to + * {@link DateTimeFormatterBuilder#appendInstant()}, as that method + * always parses the instant with the UTC zone offset. + *
+ * If the time '23:59:60' is received, then a simple conversion is applied, + * replacing the second-of-minute of 60 with 59. This query can be used + * on the parse result to determine if the leap-second adjustment was made. + * The query will return one second of excess if it did adjust to remove + * the leap-second, and zero if not. Note that applying a leap-second + * smoothing mechanism, such as UTC-SLS, is the responsibility of the + * application, as follows: + *
+ * TemporalAccessor parsed = formatter.parse(str); + * Instant instant = parsed.query(Instant::from); + * if (parsed.query(DateTimeFormatter.parsedLeapSecond())) { + * // validate leap-second is correct and apply correct smoothing + * } + *+ */ + public static final TemporalQuery
* This instance is immutable and unaffected by this method call. * - * @param symbols the new symbols, not null - * @return a formatter based on this formatter with the requested symbols, not null + * @param decimalStyle the new DecimalStyle, not null + * @return a formatter based on this formatter with the requested DecimalStyle, not null */ - public DateTimeFormatter withSymbols(DateTimeFormatSymbols symbols) { - if (this.symbols.equals(symbols)) { + public DateTimeFormatter withDecimalStyle(DecimalStyle decimalStyle) { + if (this.decimalStyle.equals(decimalStyle)) { return this; } - return new DateTimeFormatter(printerParser, locale, symbols, resolverStyle, resolverFields, chrono, zone); + return new DateTimeFormatter(printerParser, locale, decimalStyle, resolverStyle, resolverFields, chrono, zone); } //----------------------------------------------------------------------- @@ -1332,7 +1488,7 @@ if (Objects.equals(this.chrono, chrono)) { return this; } - return new DateTimeFormatter(printerParser, locale, symbols, resolverStyle, resolverFields, chrono, zone); + return new DateTimeFormatter(printerParser, locale, decimalStyle, resolverStyle, resolverFields, chrono, zone); } //----------------------------------------------------------------------- @@ -1389,7 +1545,7 @@ if (Objects.equals(this.zone, zone)) { return this; } - return new DateTimeFormatter(printerParser, locale, symbols, resolverStyle, resolverFields, chrono, zone); + return new DateTimeFormatter(printerParser, locale, decimalStyle, resolverStyle, resolverFields, chrono, zone); } //----------------------------------------------------------------------- @@ -1431,7 +1587,7 @@ if (Objects.equals(this.resolverStyle, resolverStyle)) { return this; } - return new DateTimeFormatter(printerParser, locale, symbols, resolverStyle, resolverFields, chrono, zone); + return new DateTimeFormatter(printerParser, locale, decimalStyle, resolverStyle, resolverFields, chrono, zone); } //----------------------------------------------------------------------- @@ -1495,7 +1651,7 @@ return this; } fields = Collections.unmodifiableSet(fields); - return new DateTimeFormatter(printerParser, locale, symbols, resolverStyle, fields, chrono, zone); + return new DateTimeFormatter(printerParser, locale, decimalStyle, resolverStyle, fields, chrono, zone); } /** @@ -1543,7 +1699,7 @@ return this; } resolverFields = Collections.unmodifiableSet(new HashSet<>(resolverFields)); - return new DateTimeFormatter(printerParser, locale, symbols, resolverStyle, resolverFields, chrono, zone); + return new DateTimeFormatter(printerParser, locale, decimalStyle, resolverStyle, resolverFields, chrono, zone); } //-----------------------------------------------------------------------