src/share/classes/java/time/format/DateTimeFormatter.java

Print this page




  44  *    and/or other materials provided with the distribution.
  45  *
  46  *  * Neither the name of JSR-310 nor the names of its contributors
  47  *    may be used to endorse or promote products derived from this software
  48  *    without specific prior written permission.
  49  *
  50  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  51  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  52  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  53  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  54  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  55  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  56  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  57  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  58  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  59  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  60  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  61  */
  62 package java.time.format;
  63 










  64 import java.io.IOException;
  65 import java.text.FieldPosition;
  66 import java.text.Format;
  67 import java.text.ParseException;
  68 import java.text.ParsePosition;
  69 import java.time.DateTimeException;
  70 import java.time.ZoneId;

  71 import java.time.format.DateTimeFormatterBuilder.CompositePrinterParser;
  72 import java.time.temporal.Chrono;


  73 import java.time.temporal.TemporalAccessor;
  74 import java.time.temporal.TemporalQuery;

  75 import java.util.Locale;

  76 import java.util.Objects;
  77 
  78 /**
  79  * Formatter for printing and parsing date-time objects.
  80  * <p>
  81  * This class provides the main application entry point for printing and parsing.
  82  * Common instances of {@code DateTimeFormatter} are provided by {@link DateTimeFormatters}.
  83  * For more complex formatters, a {@link DateTimeFormatterBuilder builder} is provided.





  84  * <p>
  85  * In most cases, it is not necessary to use this class directly when formatting.

  86  * The main date-time classes provide two methods - one for printing,
  87  * {@code toString(DateTimeFormatter formatter)}, and one for parsing,
  88  * {@code parse(CharSequence text, DateTimeFormatter formatter)}.
  89  * For example:
  90  * <pre>
  91  *  String text = date.toString(formatter);
  92  *  LocalDate date = LocalDate.parse(text, formatter);
  93  * </pre>
  94  * Some aspects of printing and parsing are dependent on the locale.
  95  * The locale can be changed using the {@link #withLocale(Locale)} method
  96  * which returns a new formatter in the requested locale.
  97  * <p>
  98  * Some applications may need to use the older {@link Format} class for formatting.
  99  * The {@link #toFormat()} method returns an implementation of the old API.
 100  *
 101  * <h3>Specification for implementors</h3>
 102  * This class is immutable and thread-safe.
 103  *
 104  * @since 1.8
 105  */
 106 public final class DateTimeFormatter {
 107 
 108     /**
 109      * The printer and/or parser to use, not null.
 110      */
 111     private final CompositePrinterParser printerParser;
 112     /**
 113      * The locale to use for formatting, not null.
 114      */
 115     private final Locale locale;
 116     /**
 117      * The symbols to use for formatting, not null.
 118      */
 119     private final DateTimeFormatSymbols symbols;
 120     /**
 121      * The chronology to use for formatting, null for no override.
 122      */
 123     private final Chrono<?> chrono;
 124     /**
 125      * The zone to use for formatting, null for no override.
 126      */
 127     private final ZoneId zone;
 128 

































































































































































































































































































































































































































































































































































































































































































































































































 129     /**
 130      * Constructor.
 131      *
 132      * @param printerParser  the printer/parser to use, not null
 133      * @param locale  the locale to use, not null
 134      * @param symbols  the symbols to use, not null
 135      * @param chrono  the chronology to use, null for no override
 136      * @param zone  the zone to use, null for no override
 137      */
 138     DateTimeFormatter(CompositePrinterParser printerParser, Locale locale,
 139                       DateTimeFormatSymbols symbols, Chrono chrono, ZoneId zone) {
 140         this.printerParser = Objects.requireNonNull(printerParser, "printerParser");
 141         this.locale = Objects.requireNonNull(locale, "locale");
 142         this.symbols = Objects.requireNonNull(symbols, "symbols");
 143         this.chrono = chrono;
 144         this.zone = zone;
 145     }
 146 
 147     //-----------------------------------------------------------------------
 148     /**
 149      * Gets the locale to be used during formatting.
 150      * <p>
 151      * This is used to lookup any part of the formatter needing specific
 152      * localization, such as the text or localized pattern.
 153      *
 154      * @return the locale of this formatter, not null
 155      */
 156     public Locale getLocale() {
 157         return locale;
 158     }
 159 


 189      * Returns a copy of this formatter with a new set of symbols.
 190      * <p>
 191      * This instance is immutable and unaffected by this method call.
 192      *
 193      * @param symbols  the new symbols, not null
 194      * @return a formatter based on this formatter with the requested symbols, not null
 195      */
 196     public DateTimeFormatter withSymbols(DateTimeFormatSymbols symbols) {
 197         if (this.symbols.equals(symbols)) {
 198             return this;
 199         }
 200         return new DateTimeFormatter(printerParser, locale, symbols, chrono, zone);
 201     }
 202 
 203     //-----------------------------------------------------------------------
 204     /**
 205      * Gets the overriding chronology to be used during formatting.
 206      * <p>
 207      * This returns the override chronology, used to convert dates.
 208      * By default, a formatter has no override chronology, returning null.
 209      * See {@link #withChrono(Chrono)} for more details on overriding.
 210      *
 211      * @return the chronology of this formatter, null if no override
 212      */
 213     public Chrono<?> getChrono() {
 214         return chrono;
 215     }
 216 
 217     /**
 218      * Returns a copy of this formatter with a new override chronology.
 219      * <p>
 220      * This returns a formatter with similar state to this formatter but
 221      * with the override chronology set.
 222      * By default, a formatter has no override chronology, returning null.
 223      * <p>
 224      * If an override is added, then any date that is printed or parsed will be affected.
 225      * <p>
 226      * When printing, if the {@code Temporal} object contains a date then it will
 227      * be converted to a date in the override chronology.
 228      * Any time or zone will be retained unless overridden.
 229      * The converted result will behave in a manner equivalent to an implementation
 230      * of {@code ChronoLocalDate},{@code ChronoLocalDateTime} or {@code ChronoZonedDateTime}.
 231      * <p>
 232      * When parsing, the override chronology will be used to interpret the
 233      * {@link java.time.temporal.ChronoField fields} into a date unless the
 234      * formatter directly parses a valid chronology.
 235      * <p>
 236      * This instance is immutable and unaffected by this method call.
 237      *
 238      * @param chrono  the new chronology, not null
 239      * @return a formatter based on this formatter with the requested override chronology, not null
 240      */
 241     public DateTimeFormatter withChrono(Chrono chrono) {
 242         if (Objects.equals(this.chrono, chrono)) {
 243             return this;
 244         }
 245         return new DateTimeFormatter(printerParser, locale, symbols, chrono, zone);
 246     }
 247 
 248     //-----------------------------------------------------------------------
 249     /**
 250      * Gets the overriding zone to be used during formatting.
 251      * <p>
 252      * This returns the override zone, used to convert instants.
 253      * By default, a formatter has no override zone, returning null.
 254      * See {@link #withZone(ZoneId)} for more details on overriding.
 255      *
 256      * @return the chronology of this formatter, null if no override
 257      */
 258     public ZoneId getZone() {
 259         return zone;
 260     }
 261 
 262     /**
 263      * Returns a copy of this formatter with a new override zone.
 264      * <p>
 265      * This returns a formatter with similar state to this formatter but
 266      * with the override zone set.
 267      * By default, a formatter has no override zone, returning null.
 268      * <p>
 269      * If an override is added, then any instant that is printed or parsed will be affected.
 270      * <p>
 271      * When printing, if the {@code Temporal} object contains an instant then it will
 272      * be converted to a zoned date-time using the override zone.
 273      * If the input has a chronology then it will be retained unless overridden.
 274      * If the input does not have a chronology, such as {@code Instant}, then
 275      * the ISO chronology will be used.
 276      * The converted result will behave in a manner equivalent to an implementation
 277      * of {@code ChronoZonedDateTime}.
 278      * <p>
 279      * When parsing, the override zone will be used to interpret the
 280      * {@link java.time.temporal.ChronoField fields} into an instant unless the
 281      * formatter directly parses a valid zone.
 282      * <p>
 283      * This instance is immutable and unaffected by this method call.
 284      *
 285      * @param zone  the new override zone, not null
 286      * @return a formatter based on this formatter with the requested override zone, not null
 287      */
 288     public DateTimeFormatter withZone(ZoneId zone) {
 289         if (Objects.equals(this.zone, zone)) {
 290             return this;
 291         }
 292         return new DateTimeFormatter(printerParser, locale, symbols, chrono, zone);
 293     }
 294 
 295     //-----------------------------------------------------------------------
 296     /**
 297      * Prints a date-time object using this formatter.
 298      * <p>
 299      * This prints the date-time to a String using the rules of the formatter.
 300      *
 301      * @param temporal  the temporal object to print, not null
 302      * @return the printed string, not null
 303      * @throws DateTimeException if an error occurs during printing
 304      */
 305     public String print(TemporalAccessor temporal) {
 306         StringBuilder buf = new StringBuilder(32);
 307         printTo(temporal, buf);
 308         return buf.toString();
 309     }
 310 
 311     //-----------------------------------------------------------------------
 312     /**
 313      * Prints a date-time object to an {@code Appendable} using this formatter.
 314      * <p>
 315      * This prints the date-time to the specified destination.
 316      * {@link Appendable} is a general purpose interface that is implemented by all
 317      * key character output classes including {@code StringBuffer}, {@code StringBuilder},
 318      * {@code PrintStream} and {@code Writer}.
 319      * <p>
 320      * Although {@code Appendable} methods throw an {@code IOException}, this method does not.
 321      * Instead, any {@code IOException} is wrapped in a runtime exception.
 322      * See {@link DateTimePrintException#rethrowIOException()} for a means
 323      * to extract the {@code IOException}.
 324      *
 325      * @param temporal  the temporal object to print, not null
 326      * @param appendable  the appendable to print to, not null
 327      * @throws DateTimeException if an error occurs during printing
 328      */
 329     public void printTo(TemporalAccessor temporal, Appendable appendable) {
 330         Objects.requireNonNull(temporal, "temporal");
 331         Objects.requireNonNull(appendable, "appendable");
 332         try {
 333             DateTimePrintContext context = new DateTimePrintContext(temporal, this);
 334             if (appendable instanceof StringBuilder) {
 335                 printerParser.print(context, (StringBuilder) appendable);
 336             } else {
 337                 // buffer output to avoid writing to appendable in case of error
 338                 StringBuilder buf = new StringBuilder(32);
 339                 printerParser.print(context, buf);
 340                 appendable.append(buf);
 341             }
 342         } catch (IOException ex) {
 343             throw new DateTimePrintException(ex.getMessage(), ex);





































































 344         }
 345     }
 346 
 347     //-----------------------------------------------------------------------
 348     /**
 349      * Fully parses the text producing an object of the specified type.
 350      * <p>
 351      * Most applications should use this method for parsing.
 352      * It parses the entire text to produce the required date-time.
 353      * The query is typically a method reference to a {@code from(TemporalAccessor)} method.
 354      * For example:
 355      * <pre>
 356      *  LocalDateTime dt = parser.parse(str, LocalDateTime::from);
 357      * </pre>
 358      * If the parse completes without reading the entire length of the text,
 359      * or a problem occurs during parsing or merging, then an exception is thrown.
 360      *
 361      * @param <T> the type of the parsed date-time
 362      * @param text  the text to parse, not null
 363      * @param query  the query defining the type to parse to, not null
 364      * @return the parsed date-time, not null
 365      * @throws DateTimeParseException if the parse fails
 366      */
 367     public <T> T parse(CharSequence text, TemporalQuery<T> query) {
 368         Objects.requireNonNull(text, "text");
 369         Objects.requireNonNull(query, "query");
 370         String str = text.toString();  // parsing whole String, so this makes sense
 371         try {
 372             DateTimeBuilder builder = parseToBuilder(str).resolve();
 373             return builder.query(query);
 374         } catch (DateTimeParseException ex) {
 375             throw ex;
 376         } catch (RuntimeException ex) {
 377             throw createError(str, ex);
 378         }
 379     }
 380 
 381     /**
 382      * Fully parses the text producing an object of one of the specified types.
 383      * <p>
 384      * This parse method is convenient for use when the parser can handle optional elements.
 385      * For example, a pattern of 'yyyy-MM[-dd[Z]]' can be fully parsed to an {@code OffsetDate},
 386      * or partially parsed to a {@code LocalDate} or a {@code YearMonth}.
 387      * The queries must be specified in order, starting from the best matching full-parse option
 388      * and ending with the worst matching minimal parse option.
 389      * The query is typically a method reference to a {@code from(TemporalAccessor)} method.
 390      * <p>
 391      * The result is associated with the first type that successfully parses.
 392      * Normally, applications will use {@code instanceof} to check the result.
 393      * For example:
 394      * <pre>
 395      *  TemporalAccessor dt = parser.parseBest(str, OffsetDate::from, LocalDate::from);
 396      *  if (dt instanceof OffsetDate) {
 397      *   ...
 398      *  } else {
 399      *   ...
 400      *  }
 401      * </pre>
 402      * If the parse completes without reading the entire length of the text,
 403      * or a problem occurs during parsing or merging, then an exception is thrown.
 404      *
 405      * @param text  the text to parse, not null
 406      * @param queries  the queries defining the types to attempt to parse to,
 407      *  must implement {@code TemporalAccessor}, not null
 408      * @return the parsed date-time, not null
 409      * @throws IllegalArgumentException if less than 2 types are specified
 410      * @throws DateTimeException if none of the queries can be parsed from the input
 411      * @throws DateTimeParseException if the parse fails
 412      */
 413     public TemporalAccessor parseBest(CharSequence text, TemporalQuery<?>... queries) {
 414         Objects.requireNonNull(text, "text");
 415         Objects.requireNonNull(queries, "queries");
 416         if (queries.length < 2) {
 417             throw new IllegalArgumentException("At least two queries must be specified");
 418         }
 419         String str = text.toString();  // parsing whole String, so this makes sense
 420         try {
 421             DateTimeBuilder builder = parseToBuilder(str).resolve();
 422             for (TemporalQuery<?> query : queries) {
 423                 try {
 424                     return (TemporalAccessor) builder.query(query);
 425                 } catch (RuntimeException ex) {
 426                     // continue
 427                 }
 428             }
 429             throw new DateTimeException("Unable to convert parsed text using any of the specified queries");
 430         } catch (DateTimeParseException ex) {
 431             throw ex;
 432         } catch (RuntimeException ex) {
 433             throw createError(str, ex);
 434         }
 435     }
 436 
 437     private DateTimeParseException createError(String str, RuntimeException ex) {
 438         String abbr = str;
 439         if (abbr.length() > 64) {
 440             abbr = abbr.substring(0, 64) + "...";


 441         }
 442         return new DateTimeParseException("Text '" + abbr + "' could not be parsed: " + ex.getMessage(), str, 0, ex);
 443     }
 444 
 445     //-----------------------------------------------------------------------
 446     /**
 447      * Parses the text to a builder.
 448      * <p>
 449      * This parses to a {@code DateTimeBuilder} ensuring that the text is fully parsed.
 450      * This method throws {@link DateTimeParseException} if unable to parse, or
 451      * some other {@code DateTimeException} if another date/time problem occurs.
 452      *
 453      * @param text  the text to parse, not null


 454      * @return the engine representing the result of the parse, not null
 455      * @throws DateTimeParseException if the parse fails
 456      */
 457     public DateTimeBuilder parseToBuilder(CharSequence text) {
 458         Objects.requireNonNull(text, "text");
 459         String str = text.toString();  // parsing whole String, so this makes sense
 460         ParsePosition pos = new ParsePosition(0);
 461         DateTimeBuilder result = parseToBuilder(str, pos);
 462         if (result == null || pos.getErrorIndex() >= 0 || pos.getIndex() < str.length()) {
 463             String abbr = str;
 464             if (abbr.length() > 64) {
 465                 abbr = abbr.substring(0, 64) + "...";
 466             }
 467             if (pos.getErrorIndex() >= 0) {
 468                 throw new DateTimeParseException("Text '" + abbr + "' could not be parsed at index " +
 469                         pos.getErrorIndex(), str, pos.getErrorIndex());
 470             } else {
 471                 throw new DateTimeParseException("Text '" + abbr + "' could not be parsed, unparsed text found at index " +
 472                         pos.getIndex(), str, pos.getIndex());
 473             }
 474         }
 475         return result;
 476     }
 477 
 478     /**
 479      * Parses the text to a builder.













 480      * <p>
 481      * This parses to a {@code DateTimeBuilder} but does not require the input to be fully parsed.


 482      * <p>
 483      * This method does not throw {@link DateTimeParseException}.
 484      * Instead, errors are returned within the state of the specified parse position.

 485      * Callers must check for errors before using the context.
 486      * <p>
 487      * This method may throw some other {@code DateTimeException} if a date/time problem occurs.





 488      *
 489      * @param text  the text to parse, not null
 490      * @param position  the position to parse from, updated with length parsed
 491      *  and the index of any error, not null
 492      * @return the parsed text, null only if the parse results in an error
 493      * @throws DateTimeException if some problem occurs during parsing
 494      * @throws IndexOutOfBoundsException if the position is invalid
 495      */
 496     public DateTimeBuilder parseToBuilder(CharSequence text, ParsePosition position) {




 497         Objects.requireNonNull(text, "text");
 498         Objects.requireNonNull(position, "position");
 499         DateTimeParseContext context = new DateTimeParseContext(this);
 500         int pos = position.getIndex();
 501         pos = printerParser.parse(context, text, pos);
 502         if (pos < 0) {
 503             position.setErrorIndex(~pos);
 504             return null;
 505         }
 506         position.setIndex(pos);
 507         return context.toBuilder();
 508     }
 509 
 510     //-----------------------------------------------------------------------
 511     /**
 512      * Returns the formatter as a composite printer parser.
 513      *
 514      * @param optional  whether the printer/parser should be optional
 515      * @return the printer/parser, not null
 516      */
 517     CompositePrinterParser toPrinterParser(boolean optional) {
 518         return printerParser.withOptional(optional);
 519     }
 520 
 521     /**
 522      * Returns this formatter as a {@code java.text.Format} instance.
 523      * <p>
 524      * The returned {@link Format} instance will print any {@link java.time.temporal.TemporalAccessor}
 525      * and parses to a resolved {@link DateTimeBuilder}.
 526      * <p>
 527      * Exceptions will follow the definitions of {@code Format}, see those methods
 528      * for details about {@code IllegalArgumentException} during formatting and
 529      * {@code ParseException} or null during parsing.
 530      * The format does not support attributing of the returned format string.
 531      *
 532      * @return this formatter as a classic format instance, not null
 533      */
 534     public Format toFormat() {
 535         return new ClassicFormat(this, null);
 536     }
 537 
 538     /**
 539      * Returns this formatter as a {@code java.text.Format} instance that will
 540      * parse using the specified query.
 541      * <p>
 542      * The returned {@link Format} instance will print any {@link java.time.temporal.TemporalAccessor}
 543      * and parses to the type specified.
 544      * The type must be one that is supported by {@link #parse}.
 545      * <p>
 546      * Exceptions will follow the definitions of {@code Format}, see those methods
 547      * for details about {@code IllegalArgumentException} during formatting and
 548      * {@code ParseException} or null during parsing.
 549      * The format does not support attributing of the returned format string.
 550      *
 551      * @param parseQuery  the query defining the type to parse to, not null
 552      * @return this formatter as a classic format instance, not null
 553      */
 554     public Format toFormat(TemporalQuery<?> parseQuery) {
 555         Objects.requireNonNull(parseQuery, "parseQuery");
 556         return new ClassicFormat(this, parseQuery);
 557     }
 558 
 559     //-----------------------------------------------------------------------
 560     /**
 561      * Returns a description of the underlying formatters.
 562      *


 585         private final DateTimeFormatter formatter;
 586         /** The type to be parsed. */
 587         private final TemporalQuery<?> parseType;
 588         /** Constructor. */
 589         public ClassicFormat(DateTimeFormatter formatter, TemporalQuery<?> parseType) {
 590             this.formatter = formatter;
 591             this.parseType = parseType;
 592         }
 593 
 594         @Override
 595         public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
 596             Objects.requireNonNull(obj, "obj");
 597             Objects.requireNonNull(toAppendTo, "toAppendTo");
 598             Objects.requireNonNull(pos, "pos");
 599             if (obj instanceof TemporalAccessor == false) {
 600                 throw new IllegalArgumentException("Format target must implement TemporalAccessor");
 601             }
 602             pos.setBeginIndex(0);
 603             pos.setEndIndex(0);
 604             try {
 605                 formatter.printTo((TemporalAccessor) obj, toAppendTo);
 606             } catch (RuntimeException ex) {
 607                 throw new IllegalArgumentException(ex.getMessage(), ex);
 608             }
 609             return toAppendTo;
 610         }
 611         @Override
 612         public Object parseObject(String text) throws ParseException {
 613             Objects.requireNonNull(text, "text");
 614             try {
 615                 if (parseType != null) {
 616                     return formatter.parse(text, parseType);
 617                 }
 618                 return formatter.parseToBuilder(text);
 619             } catch (DateTimeParseException ex) {
 620                 throw new ParseException(ex.getMessage(), ex.getErrorIndex());
 621             } catch (RuntimeException ex) {
 622                 throw (ParseException) new ParseException(ex.getMessage(), 0).initCause(ex);
 623             }
 624         }
 625         @Override
 626         public Object parseObject(String text, ParsePosition pos) {
 627             Objects.requireNonNull(text, "text");
 628             DateTimeBuilder builder;
 629             try {
 630                 builder = formatter.parseToBuilder(text, pos);
 631             } catch (IndexOutOfBoundsException ex) {
 632                 if (pos.getErrorIndex() < 0) {
 633                     pos.setErrorIndex(0);
 634                 }
 635                 return null;
 636             }
 637             if (builder == null) {
 638                 if (pos.getErrorIndex() < 0) {
 639                     pos.setErrorIndex(0);
 640                 }
 641                 return null;
 642             }


 643             if (parseType == null) {
 644                 return builder;
 645             }
 646             try {
 647                 return builder.resolve().query(parseType);
 648             } catch (RuntimeException ex) {
 649                 pos.setErrorIndex(0);
 650                 return null;
 651             }
 652         }
 653     }
 654 
 655 }


  44  *    and/or other materials provided with the distribution.
  45  *
  46  *  * Neither the name of JSR-310 nor the names of its contributors
  47  *    may be used to endorse or promote products derived from this software
  48  *    without specific prior written permission.
  49  *
  50  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  51  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  52  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  53  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  54  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  55  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  56  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  57  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  58  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  59  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  60  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  61  */
  62 package java.time.format;
  63 
  64 import static java.time.temporal.ChronoField.DAY_OF_MONTH;
  65 import static java.time.temporal.ChronoField.DAY_OF_WEEK;
  66 import static java.time.temporal.ChronoField.DAY_OF_YEAR;
  67 import static java.time.temporal.ChronoField.HOUR_OF_DAY;
  68 import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
  69 import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
  70 import static java.time.temporal.ChronoField.NANO_OF_SECOND;
  71 import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
  72 import static java.time.temporal.ChronoField.YEAR;
  73 
  74 import java.io.IOException;
  75 import java.text.FieldPosition;
  76 import java.text.Format;
  77 import java.text.ParseException;
  78 import java.text.ParsePosition;
  79 import java.time.DateTimeException;
  80 import java.time.ZoneId;
  81 import java.time.ZoneOffset;
  82 import java.time.format.DateTimeFormatterBuilder.CompositePrinterParser;
  83 import java.time.chrono.Chronology;
  84 import java.time.temporal.ChronoField;
  85 import java.time.temporal.IsoFields;
  86 import java.time.temporal.TemporalAccessor;
  87 import java.time.temporal.TemporalQuery;
  88 import java.util.HashMap;
  89 import java.util.Locale;
  90 import java.util.Map;
  91 import java.util.Objects;
  92 
  93 /**
  94  * Formatter for printing and parsing date-time objects.
  95  * <p>
  96  * This class provides the main application entry point for printing and parsing
  97  * and provides common implementations of {@code DateTimeFormatter}:
  98  * <p><ul>
  99  * <li>Using pattern letters, such as {@code yyyy-MMM-dd}
 100  * <li>Using localized styles, such as {@code long} or {@code medium}
 101  * <li>Using predefined constants, such as {@code ISO_LOCAL_DATE}
 102  * </ul></p>
 103  *
 104  * <p>
 105  * In most cases, provided formatters will be sufficient.
 106  * For more complex formatters, a {@link DateTimeFormatterBuilder builder} is provided.
 107  * The main date-time classes provide two methods - one for printing,
 108  * {@code toString(DateTimeFormatter formatter)}, and one for parsing,
 109  * {@code parse(CharSequence text, DateTimeFormatter formatter)}.
 110  * For example:
 111  * <pre>
 112  *  String text = date.toString(formatter);
 113  *  LocalDate date = LocalDate.parse(text, formatter);
 114  * </pre>
 115  * Some aspects of formatting and parsing are dependent on the locale.
 116  * The locale can be changed using the {@link #withLocale(Locale)} method
 117  * which returns a new formatter in the requested locale.
 118  * <p>
 119  * Some applications may need to use the older {@link Format} class for formatting.
 120  * The {@link #toFormat()} method returns an implementation of the old API.
 121  *
 122  * <h3>Specification for implementors</h3>
 123  * This class is immutable and thread-safe.
 124  *
 125  * @since 1.8
 126  */
 127 public final class DateTimeFormatter {
 128 
 129     /**
 130      * The printer and/or parser to use, not null.
 131      */
 132     private final CompositePrinterParser printerParser;
 133     /**
 134      * The locale to use for formatting, not null.
 135      */
 136     private final Locale locale;
 137     /**
 138      * The symbols to use for formatting, not null.
 139      */
 140     private final DateTimeFormatSymbols symbols;
 141     /**
 142      * The chronology to use for formatting, null for no override.
 143      */
 144     private final Chronology chrono;
 145     /**
 146      * The zone to use for formatting, null for no override.
 147      */
 148     private final ZoneId zone;
 149 
 150     //-----------------------------------------------------------------------
 151     /**
 152      * Creates a formatter using the specified pattern.
 153      * <p>
 154      * This method will create a formatter based on a simple pattern of letters and symbols.
 155      * For example, {@code d MMM yyyy} will format 2011-12-03 as '3 Dec 2011'.
 156      * <p>
 157      * The returned formatter will use the default locale, but this can be changed
 158      * using {@link DateTimeFormatter#withLocale(Locale)}.
 159      * <p>
 160      * All letters 'A' to 'Z' and 'a' to 'z' are reserved as pattern letters.
 161      * The following pattern letters are defined:
 162      * <pre>
 163      *  Symbol  Meaning                     Presentation      Examples
 164      *  ------  -------                     ------------      -------
 165      *   G       era                         text              A; AD; Anno Domini
 166      *   y       year                        year              2004; 04
 167      *   D       day-of-year                 number            189
 168      *   M       month-of-year               number/text       7; 07; Jul; July; J
 169      *   d       day-of-month                number            10
 170      *
 171      *   Q       quarter-of-year             number/text       3; 03; Q3
 172      *   Y       week-based-year             year              1996; 96
 173      *   w       week-of-year                number            27
 174      *   W       week-of-month               number            27
 175      *   e       localized day-of-week       number            2; Tue; Tuesday; T
 176      *   E       day-of-week                 number/text       2; Tue; Tuesday; T
 177      *   F       week-of-month               number            3
 178      *
 179      *   a       am-pm-of-day                text              PM
 180      *   h       clock-hour-of-am-pm (1-12)  number            12
 181      *   K       hour-of-am-pm (0-11)        number            0
 182      *   k       clock-hour-of-am-pm (1-24)  number            0
 183      *
 184      *   H       hour-of-day (0-23)          number            0
 185      *   m       minute-of-hour              number            30
 186      *   s       second-of-minute            number            55
 187      *   S       fraction-of-second          fraction          978
 188      *   A       milli-of-day                number            1234
 189      *   n       nano-of-second              number            987654321
 190      *   N       nano-of-day                 number            1234000000
 191      *
 192      *   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
 193      *   z       time-zone name              zone-name         Pacific Standard Time; PST
 194      *   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
 195      *   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
 196      *   Z       zone-offset                 offset-Z          +0000; -0800; -08:00;
 197      *
 198      *   p       pad next                    pad modifier      1
 199      *
 200      *   '       escape for text             delimiter
 201      *   ''      single quote                literal           '
 202      *   [       optional section start
 203      *   ]       optional section end
 204      *   {}      reserved for future use
 205      * </pre>
 206      * <p>
 207      * The count of pattern letters determine the format.
 208      * <p>
 209      * <b>Text</b>: The text style is determined based on the number of pattern letters used.
 210      * Less than 4 pattern letters will use the {@link TextStyle#SHORT short form}.
 211      * Exactly 4 pattern letters will use the {@link TextStyle#FULL full form}.
 212      * Exactly 5 pattern letters will use the {@link TextStyle#NARROW narrow form}.
 213      * <p>
 214      * <b>Number</b>: If the count of letters is one, then the value is output using the minimum number
 215      * of digits and without padding as per {@link DateTimeFormatterBuilder#appendValue(java.time.temporal.TemporalField)}.
 216      * Otherwise, the count of digits is used as the width of the output field as per
 217      * {@link DateTimeFormatterBuilder#appendValue(java.time.temporal.TemporalField, int)}.
 218      * <p>
 219      * <b>Number/Text</b>: If the count of pattern letters is 3 or greater, use the Text rules above.
 220      * Otherwise use the Number rules above.
 221      * <p>
 222      * <b>Fraction</b>: Outputs the nano-of-second field as a fraction-of-second.
 223      * The nano-of-second value has nine digits, thus the count of pattern letters is from 1 to 9.
 224      * If it is less than 9, then the nano-of-second value is truncated, with only the most
 225      * significant digits being output.
 226      * When parsing in strict mode, the number of parsed digits must match the count of pattern letters.
 227      * When parsing in lenient mode, the number of parsed digits must be at least the count of pattern
 228      * letters, up to 9 digits.
 229      * <p>
 230      * <b>Year</b>: The count of letters determines the minimum field width below which padding is used.
 231      * If the count of letters is two, then a {@link DateTimeFormatterBuilder#appendValueReduced reduced}
 232      * two digit form is used.
 233      * For printing, this outputs the rightmost two digits. For parsing, this will parse using the
 234      * base value of 2000, resulting in a year within the range 2000 to 2099 inclusive.
 235      * If the count of letters is less than four (but not two), then the sign is only output for negative
 236      * years as per {@link SignStyle#NORMAL}.
 237      * Otherwise, the sign is output if the pad width is exceeded, as per {@link SignStyle#EXCEEDS_PAD}
 238      * <p>
 239      * <b>ZoneId</b>: This outputs the time-zone ID, such as 'Europe/Paris'.
 240      * If the count of letters is two, then the time-zone ID is output.
 241      * Any other count of letters throws {@code IllegalArgumentException}.
 242      * <p>
 243      * <b>Zone names</b>: This outputs the display name of the time-zone ID.
 244      * If the count of letters is one, two or three, then the short name is output.
 245      * If the count of letters is four, then the full name is output.
 246      * Five or more letters throws {@code IllegalArgumentException}.
 247      * <p>
 248      * <b>Offset X and x</b>: This formats the offset based on the number of pattern letters.
 249      * One letter outputs just the hour', such as '+01', unless the minute is non-zero
 250      * in which case the minute is also output, such as '+0130'.
 251      * Two letters outputs the hour and minute, without a colon, such as '+0130'.
 252      * Three letters outputs the hour and minute, with a colon, such as '+01:30'.
 253      * Four letters outputs the hour and minute and optional second, without a colon, such as '+013015'.
 254      * Five letters outputs the hour and minute and optional second, with a colon, such as '+01:30:15'.
 255      * Six or more letters throws {@code IllegalArgumentException}.
 256      * Pattern letter 'X' (upper case) will output 'Z' when the offset to be output would be zero,
 257      * whereas pattern letter 'x' (lower case) will output '+00', '+0000', or '+00:00'.
 258      * <p>
 259      * <b>Offset Z</b>: This formats the offset based on the number of pattern letters.
 260      * One, two or three letters outputs the hour and minute, without a colon, such as '+0130'.
 261      * Four or more letters throws {@code IllegalArgumentException}.
 262      * The output will be '+0000' when the offset is zero.
 263      * <p>
 264      * <b>Optional section</b>: The optional section markers work exactly like calling
 265      * {@link DateTimeFormatterBuilder#optionalStart()} and {@link DateTimeFormatterBuilder#optionalEnd()}.
 266      * <p>
 267      * <b>Pad modifier</b>: Modifies the pattern that immediately follows to be padded with spaces.
 268      * The pad width is determined by the number of pattern letters.
 269      * This is the same as calling {@link DateTimeFormatterBuilder#padNext(int)}.
 270      * <p>
 271      * For example, 'ppH' outputs the hour-of-day padded on the left with spaces to a width of 2.
 272      * <p>
 273      * Any unrecognized letter is an error.
 274      * Any non-letter character, other than '[', ']', '{', '}' and the single quote will be output directly.
 275      * Despite this, it is recommended to use single quotes around all characters that you want to
 276      * output directly to ensure that future changes do not break your application.
 277      *
 278      * @param pattern  the pattern to use, not null
 279      * @return the formatter based on the pattern, not null
 280      * @throws IllegalArgumentException if the pattern is invalid
 281      * @see DateTimeFormatterBuilder#appendPattern(String)
 282      */
 283     public static DateTimeFormatter ofPattern(String pattern) {
 284         return new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter();
 285     }
 286 
 287     /**
 288      * Creates a formatter using the specified pattern.
 289      * <p>
 290      * This method will create a formatter based on a simple pattern of letters and symbols.
 291      * For example, {@code d MMM yyyy} will format 2011-12-03 as '3 Dec 2011'.
 292      * <p>
 293      * See {@link #ofPattern(String)} for details of the pattern.
 294      * <p>
 295      * The returned formatter will use the specified locale, but this can be changed
 296      * using {@link DateTimeFormatter#withLocale(Locale)}.
 297      *
 298      * @param pattern  the pattern to use, not null
 299      * @param locale  the locale to use, not null
 300      * @return the formatter based on the pattern, not null
 301      * @throws IllegalArgumentException if the pattern is invalid
 302      * @see DateTimeFormatterBuilder#appendPattern(String)
 303      */
 304     public static DateTimeFormatter ofPattern(String pattern, Locale locale) {
 305         return new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter(locale);
 306     }
 307 
 308     //-----------------------------------------------------------------------
 309     /**
 310      * Returns a locale specific date format.
 311      * <p>
 312      * This returns a formatter that will format or parse a date.
 313      * The exact format pattern used varies by locale.
 314      * <p>
 315      * The locale is determined from the formatter. The formatter returned directly by
 316      * this method will use the {@link Locale#getDefault(Locale.Category) default FORMAT locale}.
 317      * The locale can be controlled using {@link DateTimeFormatter#withLocale(Locale) withLocale(Locale)}
 318      * on the result of this method.
 319      * <p>
 320      * Note that the localized pattern is looked up lazily.
 321      * This {@code DateTimeFormatter} holds the style required and the locale,
 322      * looking up the pattern required on demand.
 323      *
 324      * @param dateStyle  the formatter style to obtain, not null
 325      * @return the date formatter, not null
 326      */
 327     public static DateTimeFormatter ofLocalizedDate(FormatStyle dateStyle) {
 328         Objects.requireNonNull(dateStyle, "dateStyle");
 329         return new DateTimeFormatterBuilder().appendLocalized(dateStyle, null).toFormatter();
 330     }
 331 
 332     /**
 333      * Returns a locale specific time format.
 334      * <p>
 335      * This returns a formatter that will format or parse a time.
 336      * The exact format pattern used varies by locale.
 337      * <p>
 338      * The locale is determined from the formatter. The formatter returned directly by
 339      * this method will use the {@link Locale#getDefault(Locale.Category) default FORMAT locale}.
 340      * The locale can be controlled using {@link DateTimeFormatter#withLocale(Locale) withLocale(Locale)}
 341      * on the result of this method.
 342      * <p>
 343      * Note that the localized pattern is looked up lazily.
 344      * This {@code DateTimeFormatter} holds the style required and the locale,
 345      * looking up the pattern required on demand.
 346      *
 347      * @param timeStyle  the formatter style to obtain, not null
 348      * @return the time formatter, not null
 349      */
 350     public static DateTimeFormatter ofLocalizedTime(FormatStyle timeStyle) {
 351         Objects.requireNonNull(timeStyle, "timeStyle");
 352         return new DateTimeFormatterBuilder().appendLocalized(null, timeStyle).toFormatter();
 353     }
 354 
 355     /**
 356      * Returns a locale specific date-time formatter, which is typically of short length.
 357      * <p>
 358      * This returns a formatter that will format or parse a date-time.
 359      * The exact format pattern used varies by locale.
 360      * <p>
 361      * The locale is determined from the formatter. The formatter returned directly by
 362      * this method will use the {@link Locale#getDefault(Locale.Category) default FORMAT locale}.
 363      * The locale can be controlled using {@link DateTimeFormatter#withLocale(Locale) withLocale(Locale)}
 364      * on the result of this method.
 365      * <p>
 366      * Note that the localized pattern is looked up lazily.
 367      * This {@code DateTimeFormatter} holds the style required and the locale,
 368      * looking up the pattern required on demand.
 369      *
 370      * @param dateTimeStyle  the formatter style to obtain, not null
 371      * @return the date-time formatter, not null
 372      */
 373     public static DateTimeFormatter ofLocalizedDateTime(FormatStyle dateTimeStyle) {
 374         Objects.requireNonNull(dateTimeStyle, "dateTimeStyle");
 375         return new DateTimeFormatterBuilder().appendLocalized(dateTimeStyle, dateTimeStyle).toFormatter();
 376     }
 377 
 378     /**
 379      * Returns a locale specific date and time format.
 380      * <p>
 381      * This returns a formatter that will format or parse a date-time.
 382      * The exact format pattern used varies by locale.
 383      * <p>
 384      * The locale is determined from the formatter. The formatter returned directly by
 385      * this method will use the {@link Locale#getDefault() default FORMAT locale}.
 386      * The locale can be controlled using {@link DateTimeFormatter#withLocale(Locale) withLocale(Locale)}
 387      * on the result of this method.
 388      * <p>
 389      * Note that the localized pattern is looked up lazily.
 390      * This {@code DateTimeFormatter} holds the style required and the locale,
 391      * looking up the pattern required on demand.
 392      *
 393      * @param dateStyle  the date formatter style to obtain, not null
 394      * @param timeStyle  the time formatter style to obtain, not null
 395      * @return the date, time or date-time formatter, not null
 396      */
 397     public static DateTimeFormatter ofLocalizedDateTime(FormatStyle dateStyle, FormatStyle timeStyle) {
 398         Objects.requireNonNull(dateStyle, "dateStyle");
 399         Objects.requireNonNull(timeStyle, "timeStyle");
 400         return new DateTimeFormatterBuilder().appendLocalized(dateStyle, timeStyle).toFormatter();
 401     }
 402 
 403     //-----------------------------------------------------------------------
 404     /**
 405      * Returns the ISO date formatter that formats or parses a date without an offset,
 406      * such as '2011-12-03'.
 407      * <p>
 408      * This returns an immutable formatter capable of formatting and parsing
 409      * the ISO-8601 extended local date format.
 410      * The format consists of:
 411      * <p><ul>
 412      * <li>Four digits or more for the {@link ChronoField#YEAR year}.
 413      * Years in the range 0000 to 9999 will be pre-padded by zero to ensure four digits.
 414      * Years outside that range will have a prefixed positive or negative symbol.
 415      * <li>A dash
 416      * <li>Two digits for the {@link ChronoField#MONTH_OF_YEAR month-of-year}.
 417      *  This is pre-padded by zero to ensure two digits.
 418      * <li>A dash
 419      * <li>Two digits for the {@link ChronoField#DAY_OF_MONTH day-of-month}.
 420      *  This is pre-padded by zero to ensure two digits.
 421      * </ul></p>
 422      */
 423     public static final DateTimeFormatter ISO_LOCAL_DATE;
 424     static {
 425         ISO_LOCAL_DATE = new DateTimeFormatterBuilder()
 426             .appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
 427             .appendLiteral('-')
 428             .appendValue(MONTH_OF_YEAR, 2)
 429             .appendLiteral('-')
 430             .appendValue(DAY_OF_MONTH, 2)
 431             .toFormatter();
 432     }
 433 
 434     //-----------------------------------------------------------------------
 435     /**
 436      * Returns the ISO date formatter that formats or parses a date with an offset,
 437      * such as '2011-12-03+01:00'.
 438      * <p>
 439      * This returns an immutable formatter capable of formatting and parsing
 440      * the ISO-8601 extended offset date format.
 441      * The format consists of:
 442      * <p><ul>
 443      * <li>The {@link #ISO_LOCAL_DATE}
 444      * <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
 445      *  they will be handled even though this is not part of the ISO-8601 standard.
 446      *  Parsing is case insensitive.
 447      * </ul></p>
 448      */
 449     public static final DateTimeFormatter ISO_OFFSET_DATE;
 450     static {
 451         ISO_OFFSET_DATE = new DateTimeFormatterBuilder()
 452             .parseCaseInsensitive()
 453             .append(ISO_LOCAL_DATE)
 454             .appendOffsetId()
 455             .toFormatter();
 456     }
 457 
 458     //-----------------------------------------------------------------------
 459     /**
 460      * Returns the ISO date formatter that formats or parses a date with the
 461      * offset if available, such as '2011-12-03' or '2011-12-03+01:00'.
 462      * <p>
 463      * This returns an immutable formatter capable of formatting and parsing
 464      * the ISO-8601 extended date format.
 465      * The format consists of:
 466      * <p><ul>
 467      * <li>The {@link #ISO_LOCAL_DATE}
 468      * <li>If the offset is not available then the format is complete.
 469      * <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
 470      *  they will be handled even though this is not part of the ISO-8601 standard.
 471      *  Parsing is case insensitive.
 472      * </ul></p>
 473      * <p>
 474      * As this formatter has an optional element, it may be necessary to parse using
 475      * {@link DateTimeFormatter#parseBest}.
 476      */
 477     public static final DateTimeFormatter ISO_DATE;
 478     static {
 479         ISO_DATE = new DateTimeFormatterBuilder()
 480             .parseCaseInsensitive()
 481             .append(ISO_LOCAL_DATE)
 482             .optionalStart()
 483             .appendOffsetId()
 484             .toFormatter();
 485     }
 486 
 487     //-----------------------------------------------------------------------
 488     /**
 489      * Returns the ISO time formatter that formats or parses a time without an offset,
 490      * such as '10:15' or '10:15:30'.
 491      * <p>
 492      * This returns an immutable formatter capable of formatting and parsing
 493      * the ISO-8601 extended local time format.
 494      * The format consists of:
 495      * <p><ul>
 496      * <li>Two digits for the {@link ChronoField#HOUR_OF_DAY hour-of-day}.
 497      *  This is pre-padded by zero to ensure two digits.
 498      * <li>A colon
 499      * <li>Two digits for the {@link ChronoField#MINUTE_OF_HOUR minute-of-hour}.
 500      *  This is pre-padded by zero to ensure two digits.
 501      * <li>If the second-of-minute is not available then the format is complete.
 502      * <li>A colon
 503      * <li>Two digits for the {@link ChronoField#SECOND_OF_MINUTE second-of-minute}.
 504      *  This is pre-padded by zero to ensure two digits.
 505      * <li>If the nano-of-second is zero or not available then the format is complete.
 506      * <li>A decimal point
 507      * <li>One to nine digits for the {@link ChronoField#NANO_OF_SECOND nano-of-second}.
 508      *  As many digits will be output as required.
 509      * </ul></p>
 510      */
 511     public static final DateTimeFormatter ISO_LOCAL_TIME;
 512     static {
 513         ISO_LOCAL_TIME = new DateTimeFormatterBuilder()
 514             .appendValue(HOUR_OF_DAY, 2)
 515             .appendLiteral(':')
 516             .appendValue(MINUTE_OF_HOUR, 2)
 517             .optionalStart()
 518             .appendLiteral(':')
 519             .appendValue(SECOND_OF_MINUTE, 2)
 520             .optionalStart()
 521             .appendFraction(NANO_OF_SECOND, 0, 9, true)
 522             .toFormatter();
 523     }
 524 
 525     //-----------------------------------------------------------------------
 526     /**
 527      * Returns the ISO time formatter that formats or parses a time with an offset,
 528      * such as '10:15+01:00' or '10:15:30+01:00'.
 529      * <p>
 530      * This returns an immutable formatter capable of formatting and parsing
 531      * the ISO-8601 extended offset time format.
 532      * The format consists of:
 533      * <p><ul>
 534      * <li>The {@link #ISO_LOCAL_TIME}
 535      * <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
 536      *  they will be handled even though this is not part of the ISO-8601 standard.
 537      *  Parsing is case insensitive.
 538      * </ul></p>
 539      */
 540     public static final DateTimeFormatter ISO_OFFSET_TIME;
 541     static {
 542         ISO_OFFSET_TIME = new DateTimeFormatterBuilder()
 543             .parseCaseInsensitive()
 544             .append(ISO_LOCAL_TIME)
 545             .appendOffsetId()
 546             .toFormatter();
 547     }
 548 
 549     //-----------------------------------------------------------------------
 550     /**
 551      * Returns the ISO time formatter that formats or parses a time, with the
 552      * offset if available, such as '10:15', '10:15:30' or '10:15:30+01:00'.
 553      * <p>
 554      * This returns an immutable formatter capable of formatting and parsing
 555      * the ISO-8601 extended offset time format.
 556      * The format consists of:
 557      * <p><ul>
 558      * <li>The {@link #ISO_LOCAL_TIME}
 559      * <li>If the offset is not available then the format is complete.
 560      * <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
 561      *  they will be handled even though this is not part of the ISO-8601 standard.
 562      *  Parsing is case insensitive.
 563      * </ul></p>
 564      * <p>
 565      * As this formatter has an optional element, it may be necessary to parse using
 566      * {@link DateTimeFormatter#parseBest}.
 567      */
 568     public static final DateTimeFormatter ISO_TIME;
 569     static {
 570         ISO_TIME = new DateTimeFormatterBuilder()
 571             .parseCaseInsensitive()
 572             .append(ISO_LOCAL_TIME)
 573             .optionalStart()
 574             .appendOffsetId()
 575             .toFormatter();
 576     }
 577 
 578     //-----------------------------------------------------------------------
 579     /**
 580      * Returns the ISO date formatter that formats or parses a date-time
 581      * without an offset, such as '2011-12-03T10:15:30'.
 582      * <p>
 583      * This returns an immutable formatter capable of formatting and parsing
 584      * the ISO-8601 extended offset date-time format.
 585      * The format consists of:
 586      * <p><ul>
 587      * <li>The {@link #ISO_LOCAL_DATE}
 588      * <li>The letter 'T'. Parsing is case insensitive.
 589      * <li>The {@link #ISO_LOCAL_TIME}
 590      * </ul></p>
 591      */
 592     public static final DateTimeFormatter ISO_LOCAL_DATE_TIME;
 593     static {
 594         ISO_LOCAL_DATE_TIME = new DateTimeFormatterBuilder()
 595             .parseCaseInsensitive()
 596             .append(ISO_LOCAL_DATE)
 597             .appendLiteral('T')
 598             .append(ISO_LOCAL_TIME)
 599             .toFormatter();
 600     }
 601 
 602     //-----------------------------------------------------------------------
 603     /**
 604      * Returns the ISO date formatter that formats or parses a date-time
 605      * with an offset, such as '2011-12-03T10:15:30+01:00'.
 606      * <p>
 607      * This returns an immutable formatter capable of formatting and parsing
 608      * the ISO-8601 extended offset date-time format.
 609      * The format consists of:
 610      * <p><ul>
 611      * <li>The {@link #ISO_LOCAL_DATE_TIME}
 612      * <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
 613      *  they will be handled even though this is not part of the ISO-8601 standard.
 614      *  Parsing is case insensitive.
 615      * </ul></p>
 616      */
 617     public static final DateTimeFormatter ISO_OFFSET_DATE_TIME;
 618     static {
 619         ISO_OFFSET_DATE_TIME = new DateTimeFormatterBuilder()
 620             .parseCaseInsensitive()
 621             .append(ISO_LOCAL_DATE_TIME)
 622             .appendOffsetId()
 623             .toFormatter();
 624     }
 625 
 626     //-----------------------------------------------------------------------
 627     /**
 628      * Returns the ISO date formatter that formats or parses a date-time with
 629      * offset and zone, such as '2011-12-03T10:15:30+01:00[Europe/Paris]'.
 630      * <p>
 631      * This returns an immutable formatter capable of formatting and parsing
 632      * a format that extends the ISO-8601 extended offset date-time format
 633      * to add the time-zone.
 634      * The format consists of:
 635      * <p><ul>
 636      * <li>The {@link #ISO_OFFSET_DATE_TIME}
 637      * <li>If the zone ID is not available or is a {@code ZoneOffset} then the format is complete.
 638      * <li>An open square bracket '['.
 639      * <li>The {@link ZoneId#getId() zone ID}. This is not part of the ISO-8601 standard.
 640      *  Parsing is case sensitive.
 641      * <li>A close square bracket ']'.
 642      * </ul></p>
 643      */
 644     public static final DateTimeFormatter ISO_ZONED_DATE_TIME;
 645     static {
 646         ISO_ZONED_DATE_TIME = new DateTimeFormatterBuilder()
 647             .append(ISO_OFFSET_DATE_TIME)
 648             .optionalStart()
 649             .appendLiteral('[')
 650             .parseCaseSensitive()
 651             .appendZoneRegionId()
 652             .appendLiteral(']')
 653             .toFormatter();
 654     }
 655 
 656     //-----------------------------------------------------------------------
 657     /**
 658      * Returns the ISO date formatter that formats or parses a date-time
 659      * with the offset and zone if available, such as '2011-12-03T10:15:30',
 660      * '2011-12-03T10:15:30+01:00' or '2011-12-03T10:15:30+01:00[Europe/Paris]'.
 661      * <p>
 662      * This returns an immutable formatter capable of formatting and parsing
 663      * the ISO-8601 extended offset date-time format.
 664      * The format consists of:
 665      * <p><ul>
 666      * <li>The {@link #ISO_LOCAL_DATE_TIME}
 667      * <li>If the offset is not available to format or parse then the format is complete.
 668      * <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
 669      *  they will be handled even though this is not part of the ISO-8601 standard.
 670      * <li>If the zone ID is not available or is a {@code ZoneOffset} then the format is complete.
 671      * <li>An open square bracket '['.
 672      * <li>The {@link ZoneId#getId() zone ID}. This is not part of the ISO-8601 standard.
 673      *  Parsing is case sensitive.
 674      * <li>A close square bracket ']'.
 675      * </ul></p>
 676      * <p>
 677      * As this formatter has an optional element, it may be necessary to parse using
 678      * {@link DateTimeFormatter#parseBest}.
 679      */
 680     public static final DateTimeFormatter ISO_DATE_TIME;
 681     static {
 682         ISO_DATE_TIME = new DateTimeFormatterBuilder()
 683             .append(ISO_LOCAL_DATE_TIME)
 684             .optionalStart()
 685             .appendOffsetId()
 686             .optionalStart()
 687             .appendLiteral('[')
 688             .parseCaseSensitive()
 689             .appendZoneRegionId()
 690             .appendLiteral(']')
 691             .toFormatter();
 692     }
 693 
 694     //-----------------------------------------------------------------------
 695     /**
 696      * Returns the ISO date formatter that formats or parses the ordinal date
 697      * without an offset, such as '2012-337'.
 698      * <p>
 699      * This returns an immutable formatter capable of formatting and parsing
 700      * the ISO-8601 extended ordinal date format.
 701      * The format consists of:
 702      * <p><ul>
 703      * <li>Four digits or more for the {@link ChronoField#YEAR year}.
 704      * Years in the range 0000 to 9999 will be pre-padded by zero to ensure four digits.
 705      * Years outside that range will have a prefixed positive or negative symbol.
 706      * <li>A dash
 707      * <li>Three digits for the {@link ChronoField#DAY_OF_YEAR day-of-year}.
 708      *  This is pre-padded by zero to ensure three digits.
 709      * <li>If the offset is not available to format or parse then the format is complete.
 710      * <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
 711      *  they will be handled even though this is not part of the ISO-8601 standard.
 712      *  Parsing is case insensitive.
 713      * </ul></p>
 714      * <p>
 715      * As this formatter has an optional element, it may be necessary to parse using
 716      * {@link DateTimeFormatter#parseBest}.
 717      */
 718     public static final DateTimeFormatter ISO_ORDINAL_DATE;
 719     static {
 720         ISO_ORDINAL_DATE = new DateTimeFormatterBuilder()
 721             .parseCaseInsensitive()
 722             .appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
 723             .appendLiteral('-')
 724             .appendValue(DAY_OF_YEAR, 3)
 725             .optionalStart()
 726             .appendOffsetId()
 727             .toFormatter();
 728     }
 729 
 730     //-----------------------------------------------------------------------
 731     /**
 732      * Returns the ISO date formatter that formats or parses the week-based date
 733      * without an offset, such as '2012-W48-6'.
 734      * <p>
 735      * This returns an immutable formatter capable of formatting and parsing
 736      * the ISO-8601 extended week-based date format.
 737      * The format consists of:
 738      * <p><ul>
 739      * <li>Four digits or more for the {@link IsoFields#WEEK_BASED_YEAR week-based-year}.
 740      * Years in the range 0000 to 9999 will be pre-padded by zero to ensure four digits.
 741      * Years outside that range will have a prefixed positive or negative symbol.
 742      * <li>A dash
 743      * <li>The letter 'W'. Parsing is case insensitive.
 744      * <li>Two digits for the {@link IsoFields#WEEK_OF_WEEK_BASED_YEAR week-of-week-based-year}.
 745      *  This is pre-padded by zero to ensure three digits.
 746      * <li>A dash
 747      * <li>One digit for the {@link ChronoField#DAY_OF_WEEK day-of-week}.
 748      *  The value run from Monday (1) to Sunday (7).
 749      * <li>If the offset is not available to format or parse then the format is complete.
 750      * <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
 751      *  they will be handled even though this is not part of the ISO-8601 standard.
 752      *  Parsing is case insensitive.
 753      * </ul></p>
 754      * <p>
 755      * As this formatter has an optional element, it may be necessary to parse using
 756      * {@link DateTimeFormatter#parseBest}.
 757      */
 758     public static final DateTimeFormatter ISO_WEEK_DATE;
 759     static {
 760         ISO_WEEK_DATE = new DateTimeFormatterBuilder()
 761             .parseCaseInsensitive()
 762             .appendValue(IsoFields.WEEK_BASED_YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
 763             .appendLiteral("-W")
 764             .appendValue(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 2)
 765             .appendLiteral('-')
 766             .appendValue(DAY_OF_WEEK, 1)
 767             .optionalStart()
 768             .appendOffsetId()
 769             .toFormatter();
 770     }
 771 
 772     //-----------------------------------------------------------------------
 773     /**
 774      * Returns the ISO instant formatter that formats or parses an instant in UTC.
 775      * <p>
 776      * This returns an immutable formatter capable of formatting and parsing
 777      * the ISO-8601 instant format.
 778      * The format consists of:
 779      * <p><ul>
 780      * <li>The {@link #ISO_OFFSET_DATE_TIME} where the instant is converted from
 781      *  {@link ChronoField#INSTANT_SECONDS} and {@link ChronoField#NANO_OF_SECOND}
 782      *  using the {@code UTC} offset. Parsing is case insensitive.
 783      * </ul></p>
 784      */
 785     public static final DateTimeFormatter ISO_INSTANT;
 786     static {
 787         ISO_INSTANT = new DateTimeFormatterBuilder()
 788             .parseCaseInsensitive()
 789             .appendInstant()
 790             .toFormatter();
 791     }
 792 
 793     //-----------------------------------------------------------------------
 794     /**
 795      * Returns the ISO date formatter that formats or parses a date without an offset,
 796      * such as '20111203'.
 797      * <p>
 798      * This returns an immutable formatter capable of formatting and parsing
 799      * the ISO-8601 basic local date format.
 800      * The format consists of:
 801      * <p><ul>
 802      * <li>Four digits for the {@link ChronoField#YEAR year}.
 803      *  Only years in the range 0000 to 9999 are supported.
 804      * <li>Two digits for the {@link ChronoField#MONTH_OF_YEAR month-of-year}.
 805      *  This is pre-padded by zero to ensure two digits.
 806      * <li>Two digits for the {@link ChronoField#DAY_OF_MONTH day-of-month}.
 807      *  This is pre-padded by zero to ensure two digits.
 808      * <li>If the offset is not available to format or parse then the format is complete.
 809      * <li>The {@link ZoneOffset#getId() offset ID} without colons. If the offset has
 810      *  seconds then they will be handled even though this is not part of the ISO-8601 standard.
 811      *  Parsing is case insensitive.
 812      * </ul></p>
 813      * <p>
 814      * As this formatter has an optional element, it may be necessary to parse using
 815      * {@link DateTimeFormatter#parseBest}.
 816      */
 817     public static final DateTimeFormatter BASIC_ISO_DATE;
 818     static {
 819         BASIC_ISO_DATE = new DateTimeFormatterBuilder()
 820             .parseCaseInsensitive()
 821             .appendValue(YEAR, 4)
 822             .appendValue(MONTH_OF_YEAR, 2)
 823             .appendValue(DAY_OF_MONTH, 2)
 824             .optionalStart()
 825             .appendOffset("+HHMMss", "Z")
 826             .toFormatter();
 827     }
 828 
 829     //-----------------------------------------------------------------------
 830     /**
 831      * The RFC-1123 date-time formatter, such as 'Tue, 3 Jun 2008 11:05:30 GMT'.
 832      * <p>
 833      * This returns an immutable formatter capable of formatting and parsing
 834      * most of the RFC-1123 format.
 835      * RFC-1123 updates RFC-822 changing the year from two digits to four.
 836      * This implementation requires a four digit year.
 837      * This implementation also does not handle North American or military zone
 838      * names, only 'GMT' and offset amounts.
 839      * <p>
 840      * The format consists of:
 841      * <p><ul>
 842      * <li>If the day-of-week is not available to format or parse then jump to day-of-month.
 843      * <li>Three letter {@link ChronoField#DAY_OF_WEEK day-of-week} in English.
 844      * <li>A comma
 845      * <li>A space
 846      * <li>One or two digits for the {@link ChronoField#DAY_OF_MONTH day-of-month}.
 847      * <li>A space
 848      * <li>Three letter {@link ChronoField#MONTH_OF_YEAR month-of-year} in English.
 849      * <li>A space
 850      * <li>Four digits for the {@link ChronoField#YEAR year}.
 851      *  Only years in the range 0000 to 9999 are supported.
 852      * <li>A space
 853      * <li>Two digits for the {@link ChronoField#HOUR_OF_DAY hour-of-day}.
 854      *  This is pre-padded by zero to ensure two digits.
 855      * <li>A colon
 856      * <li>Two digits for the {@link ChronoField#MINUTE_OF_HOUR minute-of-hour}.
 857      *  This is pre-padded by zero to ensure two digits.
 858      * <li>If the second-of-minute is not available then jump to the next space.
 859      * <li>A colon
 860      * <li>Two digits for the {@link ChronoField#SECOND_OF_MINUTE second-of-minute}.
 861      *  This is pre-padded by zero to ensure two digits.
 862      * <li>A space
 863      * <li>The {@link ZoneOffset#getId() offset ID} without colons or seconds.
 864      *  An offset of zero uses "GMT". North American zone names and military zone names are not handled.
 865      * </ul></p>
 866      * <p>
 867      * Parsing is case insensitive.
 868      */
 869     public static final DateTimeFormatter RFC_1123_DATE_TIME;
 870     static {
 871         // manually code maps to ensure correct data always used
 872         // (locale data can be changed by application code)
 873         Map<Long, String> dow = new HashMap<>();
 874         dow.put(1L, "Mon");
 875         dow.put(2L, "Tue");
 876         dow.put(3L, "Wed");
 877         dow.put(4L, "Thu");
 878         dow.put(5L, "Fri");
 879         dow.put(6L, "Sat");
 880         dow.put(7L, "Sun");
 881         Map<Long, String> moy = new HashMap<>();
 882         moy.put(1L, "Jan");
 883         moy.put(2L, "Feb");
 884         moy.put(3L, "Mar");
 885         moy.put(4L, "Apr");
 886         moy.put(5L, "May");
 887         moy.put(6L, "Jun");
 888         moy.put(7L, "Jul");
 889         moy.put(8L, "Aug");
 890         moy.put(9L, "Sep");
 891         moy.put(10L, "Oct");
 892         moy.put(11L, "Nov");
 893         moy.put(12L, "Dec");
 894         RFC_1123_DATE_TIME = new DateTimeFormatterBuilder()
 895             .parseCaseInsensitive()
 896             .parseLenient()
 897             .optionalStart()
 898             .appendText(DAY_OF_WEEK, dow)
 899             .appendLiteral(", ")
 900             .optionalEnd()
 901             .appendValue(DAY_OF_MONTH, 1, 2, SignStyle.NOT_NEGATIVE)
 902             .appendLiteral(' ')
 903             .appendText(MONTH_OF_YEAR, moy)
 904             .appendLiteral(' ')
 905             .appendValue(YEAR, 4)  // 2 digit year not handled
 906             .appendLiteral(' ')
 907             .appendValue(HOUR_OF_DAY, 2)
 908             .appendLiteral(':')
 909             .appendValue(MINUTE_OF_HOUR, 2)
 910             .optionalStart()
 911             .appendLiteral(':')
 912             .appendValue(SECOND_OF_MINUTE, 2)
 913             .optionalEnd()
 914             .appendLiteral(' ')
 915             .appendOffset("+HHMM", "GMT")  // should handle UT/Z/EST/EDT/CST/CDT/MST/MDT/PST/MDT
 916             .toFormatter();
 917     }
 918 
 919     /**
 920      * Constructor.
 921      *
 922      * @param printerParser  the printer/parser to use, not null
 923      * @param locale  the locale to use, not null
 924      * @param symbols  the symbols to use, not null
 925      * @param chrono  the chronology to use, null for no override
 926      * @param zone  the zone to use, null for no override
 927      */
 928     DateTimeFormatter(CompositePrinterParser printerParser, Locale locale,
 929                       DateTimeFormatSymbols symbols, Chronology chrono, ZoneId zone) {
 930         this.printerParser = Objects.requireNonNull(printerParser, "printerParser");
 931         this.locale = Objects.requireNonNull(locale, "locale");
 932         this.symbols = Objects.requireNonNull(symbols, "symbols");
 933         this.chrono = chrono;
 934         this.zone = zone;
 935     }
 936 
 937     //-----------------------------------------------------------------------
 938     /**
 939      * Gets the locale to be used during formatting.
 940      * <p>
 941      * This is used to lookup any part of the formatter needing specific
 942      * localization, such as the text or localized pattern.
 943      *
 944      * @return the locale of this formatter, not null
 945      */
 946     public Locale getLocale() {
 947         return locale;
 948     }
 949 


 979      * Returns a copy of this formatter with a new set of symbols.
 980      * <p>
 981      * This instance is immutable and unaffected by this method call.
 982      *
 983      * @param symbols  the new symbols, not null
 984      * @return a formatter based on this formatter with the requested symbols, not null
 985      */
 986     public DateTimeFormatter withSymbols(DateTimeFormatSymbols symbols) {
 987         if (this.symbols.equals(symbols)) {
 988             return this;
 989         }
 990         return new DateTimeFormatter(printerParser, locale, symbols, chrono, zone);
 991     }
 992 
 993     //-----------------------------------------------------------------------
 994     /**
 995      * Gets the overriding chronology to be used during formatting.
 996      * <p>
 997      * This returns the override chronology, used to convert dates.
 998      * By default, a formatter has no override chronology, returning null.
 999      * See {@link #withChronology(Chronology)} for more details on overriding.
1000      *
1001      * @return the chronology of this formatter, null if no override
1002      */
1003     public Chronology getChronology() {
1004         return chrono;
1005     }
1006 
1007     /**
1008      * Returns a copy of this formatter with a new override chronology.
1009      * <p>
1010      * This returns a formatter with similar state to this formatter but
1011      * with the override chronology set.
1012      * By default, a formatter has no override chronology, returning null.
1013      * <p>
1014      * If an override is added, then any date that is formatted or parsed will be affected.
1015      * <p>
1016      * When formatting, if the {@code Temporal} object contains a date then it will
1017      * be converted to a date in the override chronology.
1018      * Any time or zone will be retained unless overridden.
1019      * The converted result will behave in a manner equivalent to an implementation
1020      * of {@code ChronoLocalDate},{@code ChronoLocalDateTime} or {@code ChronoZonedDateTime}.
1021      * <p>
1022      * When parsing, the override chronology will be used to interpret the
1023      * {@link java.time.temporal.ChronoField fields} into a date unless the
1024      * formatter directly parses a valid chronology.
1025      * <p>
1026      * This instance is immutable and unaffected by this method call.
1027      *
1028      * @param chrono  the new chronology, not null
1029      * @return a formatter based on this formatter with the requested override chronology, not null
1030      */
1031     public DateTimeFormatter withChronology(Chronology chrono) {
1032         if (Objects.equals(this.chrono, chrono)) {
1033             return this;
1034         }
1035         return new DateTimeFormatter(printerParser, locale, symbols, chrono, zone);
1036     }
1037 
1038     //-----------------------------------------------------------------------
1039     /**
1040      * Gets the overriding zone to be used during formatting.
1041      * <p>
1042      * This returns the override zone, used to convert instants.
1043      * By default, a formatter has no override zone, returning null.
1044      * See {@link #withZone(ZoneId)} for more details on overriding.
1045      *
1046      * @return the chronology of this formatter, null if no override
1047      */
1048     public ZoneId getZone() {
1049         return zone;
1050     }
1051 
1052     /**
1053      * Returns a copy of this formatter with a new override zone.
1054      * <p>
1055      * This returns a formatter with similar state to this formatter but
1056      * with the override zone set.
1057      * By default, a formatter has no override zone, returning null.
1058      * <p>
1059      * If an override is added, then any instant that is formatted or parsed will be affected.
1060      * <p>
1061      * When formatting, if the {@code Temporal} object contains an instant then it will
1062      * be converted to a zoned date-time using the override zone.
1063      * If the input has a chronology then it will be retained unless overridden.
1064      * If the input does not have a chronology, such as {@code Instant}, then
1065      * the ISO chronology will be used.
1066      * The converted result will behave in a manner equivalent to an implementation
1067      * of {@code ChronoZonedDateTime}.
1068      * <p>
1069      * When parsing, the override zone will be used to interpret the
1070      * {@link java.time.temporal.ChronoField fields} into an instant unless the
1071      * formatter directly parses a valid zone.
1072      * <p>
1073      * This instance is immutable and unaffected by this method call.
1074      *
1075      * @param zone  the new override zone, not null
1076      * @return a formatter based on this formatter with the requested override zone, not null
1077      */
1078     public DateTimeFormatter withZone(ZoneId zone) {
1079         if (Objects.equals(this.zone, zone)) {
1080             return this;
1081         }
1082         return new DateTimeFormatter(printerParser, locale, symbols, chrono, zone);
1083     }
1084 
1085     //-----------------------------------------------------------------------
1086     /**
1087      * Formats a date-time object using this formatter.
1088      * <p>
1089      * This formats the date-time to a String using the rules of the formatter.
1090      *
1091      * @param temporal  the temporal object to format, not null
1092      * @return the formatted string, not null
1093      * @throws DateTimeException if an error occurs during formatting
1094      */
1095     public String format(TemporalAccessor temporal) {
1096         StringBuilder buf = new StringBuilder(32);
1097         formatTo(temporal, buf);
1098         return buf.toString();
1099     }
1100 
1101     //-----------------------------------------------------------------------
1102     /**
1103      * Formats a date-time object to an {@code Appendable} using this formatter.
1104      * <p>
1105      * This outputs the formatted date-time to the specified destination.
1106      * {@link Appendable} is a general purpose interface that is implemented by all
1107      * key character output classes including {@code StringBuffer}, {@code StringBuilder},
1108      * {@code PrintStream} and {@code Writer}.
1109      * <p>
1110      * Although {@code Appendable} methods throw an {@code IOException}, this method does not.
1111      * Instead, any {@code IOException} is wrapped in a runtime exception.


1112      *
1113      * @param temporal  the temporal object to format, not null
1114      * @param appendable  the appendable to format to, not null
1115      * @throws DateTimeException if an error occurs during formatting
1116      */
1117     public void formatTo(TemporalAccessor temporal, Appendable appendable) {
1118         Objects.requireNonNull(temporal, "temporal");
1119         Objects.requireNonNull(appendable, "appendable");
1120         try {
1121             DateTimePrintContext context = new DateTimePrintContext(temporal, this);
1122             if (appendable instanceof StringBuilder) {
1123                 printerParser.format(context, (StringBuilder) appendable);
1124             } else {
1125                 // buffer output to avoid writing to appendable in case of error
1126                 StringBuilder buf = new StringBuilder(32);
1127                 printerParser.format(context, buf);
1128                 appendable.append(buf);
1129             }
1130         } catch (IOException ex) {
1131             throw new DateTimeException(ex.getMessage(), ex);
1132         }
1133     }
1134 
1135     //-----------------------------------------------------------------------
1136     /**
1137      * Fully parses the text producing a temporal object.
1138      * <p>
1139      * This parses the entire text producing a temporal object.
1140      * It is typically more useful to use {@link #parse(CharSequence, TemporalQuery)}.
1141      * The result of this method is {@code TemporalAccessor} which has been resolved,
1142      * applying basic validation checks to help ensure a valid date-time.
1143      * <p>
1144      * If the parse completes without reading the entire length of the text,
1145      * or a problem occurs during parsing or merging, then an exception is thrown.
1146      *
1147      * @param text  the text to parse, not null
1148      * @return the parsed temporal object, not null
1149      * @throws DateTimeParseException if unable to parse the requested result
1150      */
1151     public TemporalAccessor parse(CharSequence text) {
1152         Objects.requireNonNull(text, "text");
1153         try {
1154             return parseToBuilder(text, null).resolve();
1155         } catch (DateTimeParseException ex) {
1156             throw ex;
1157         } catch (RuntimeException ex) {
1158             throw createError(text, ex);
1159         }
1160     }
1161 
1162     /**
1163      * Parses the text using this formatter, providing control over the text position.
1164      * <p>
1165      * This parses the text without requiring the parse to start from the beginning
1166      * of the string or finish at the end.
1167      * The result of this method is {@code TemporalAccessor} which has been resolved,
1168      * applying basic validation checks to help ensure a valid date-time.
1169      * <p>
1170      * The text will be parsed from the specified start {@code ParsePosition}.
1171      * The entire length of the text does not have to be parsed, the {@code ParsePosition}
1172      * will be updated with the index at the end of parsing.
1173      * <p>
1174      * The operation of this method is slightly different to similar methods using
1175      * {@code ParsePosition} on {@code java.text.Format}. That class will return
1176      * errors using the error index on the {@code ParsePosition}. By contrast, this
1177      * method will throw a {@link DateTimeParseException} if an error occurs, with
1178      * the exception containing the error index.
1179      * This change in behavior is necessary due to the increased complexity of
1180      * parsing and resolving dates/times in this API.
1181      * <p>
1182      * If the formatter parses the same field more than once with different values,
1183      * the result will be an error.
1184      *
1185      * @param text  the text to parse, not null
1186      * @param position  the position to parse from, updated with length parsed
1187      *  and the index of any error, not null
1188      * @return the parsed temporal object, not null
1189      * @throws DateTimeParseException if unable to parse the requested result
1190      * @throws IndexOutOfBoundsException if the position is invalid
1191      */
1192     public TemporalAccessor parse(CharSequence text, ParsePosition position) {
1193         Objects.requireNonNull(text, "text");
1194         Objects.requireNonNull(position, "position");
1195         try {
1196             return parseToBuilder(text, position).resolve();
1197         } catch (DateTimeParseException | IndexOutOfBoundsException ex) {
1198             throw ex;
1199         } catch (RuntimeException ex) {
1200             throw createError(text, ex);
1201         }
1202     }
1203 
1204     //-----------------------------------------------------------------------
1205     /**
1206      * Fully parses the text producing an object of the specified type.
1207      * <p>
1208      * Most applications should use this method for parsing.
1209      * It parses the entire text to produce the required date-time.
1210      * The query is typically a method reference to a {@code from(TemporalAccessor)} method.
1211      * For example:
1212      * <pre>
1213      *  LocalDateTime dt = parser.parse(str, LocalDateTime::from);
1214      * </pre>
1215      * If the parse completes without reading the entire length of the text,
1216      * or a problem occurs during parsing or merging, then an exception is thrown.
1217      *
1218      * @param <T> the type of the parsed date-time
1219      * @param text  the text to parse, not null
1220      * @param query  the query defining the type to parse to, not null
1221      * @return the parsed date-time, not null
1222      * @throws DateTimeParseException if unable to parse the requested result
1223      */
1224     public <T> T parse(CharSequence text, TemporalQuery<T> query) {
1225         Objects.requireNonNull(text, "text");
1226         Objects.requireNonNull(query, "query");

1227         try {
1228             DateTimeBuilder builder = parseToBuilder(text, null).resolve();
1229             return builder.query(query);
1230         } catch (DateTimeParseException ex) {
1231             throw ex;
1232         } catch (RuntimeException ex) {
1233             throw createError(text, ex);
1234         }
1235     }
1236 
1237     /**
1238      * Fully parses the text producing an object of one of the specified types.
1239      * <p>
1240      * This parse method is convenient for use when the parser can handle optional elements.
1241      * For example, a pattern of 'yyyy-MM-dd HH.mm[Z]]' can be fully parsed to a {@code ZonedDateTime},
1242      * or partially parsed to a {@code LocalDateTime}.
1243      * The queries must be specified in order, starting from the best matching full-parse option
1244      * and ending with the worst matching minimal parse option.
1245      * The query is typically a method reference to a {@code from(TemporalAccessor)} method.
1246      * <p>
1247      * The result is associated with the first type that successfully parses.
1248      * Normally, applications will use {@code instanceof} to check the result.
1249      * For example:
1250      * <pre>
1251      *  TemporalAccessor dt = parser.parseBest(str, ZonedDateTime::from, LocalDateTime::from);
1252      *  if (dt instanceof ZonedDateTime) {
1253      *   ...
1254      *  } else {
1255      *   ...
1256      *  }
1257      * </pre>
1258      * If the parse completes without reading the entire length of the text,
1259      * or a problem occurs during parsing or merging, then an exception is thrown.
1260      *
1261      * @param text  the text to parse, not null
1262      * @param queries  the queries defining the types to attempt to parse to,
1263      *  must implement {@code TemporalAccessor}, not null
1264      * @return the parsed date-time, not null
1265      * @throws IllegalArgumentException if less than 2 types are specified
1266      * @throws DateTimeParseException if unable to parse the requested result

1267      */
1268     public TemporalAccessor parseBest(CharSequence text, TemporalQuery<?>... queries) {
1269         Objects.requireNonNull(text, "text");
1270         Objects.requireNonNull(queries, "queries");
1271         if (queries.length < 2) {
1272             throw new IllegalArgumentException("At least two queries must be specified");
1273         }

1274         try {
1275             DateTimeBuilder builder = parseToBuilder(text, null).resolve();
1276             for (TemporalQuery<?> query : queries) {
1277                 try {
1278                     return (TemporalAccessor) builder.query(query);
1279                 } catch (RuntimeException ex) {
1280                     // continue
1281                 }
1282             }
1283             throw new DateTimeException("Unable to convert parsed text using any of the specified queries");
1284         } catch (DateTimeParseException ex) {
1285             throw ex;
1286         } catch (RuntimeException ex) {
1287             throw createError(text, ex);
1288         }
1289     }
1290 
1291     private DateTimeParseException createError(CharSequence text, RuntimeException ex) {
1292         String abbr = "";
1293         if (text.length() > 64) {
1294             abbr = text.subSequence(0, 64).toString() + "...";
1295         } else {
1296             abbr = text.toString();
1297         }
1298         return new DateTimeParseException("Text '" + abbr + "' could not be parsed: " + ex.getMessage(), text, 0, ex);
1299     }
1300 
1301     //-----------------------------------------------------------------------
1302     /**
1303      * Parses the text to a builder.
1304      * <p>
1305      * This parses to a {@code DateTimeBuilder} ensuring that the text is fully parsed.
1306      * This method throws {@link DateTimeParseException} if unable to parse, or
1307      * some other {@code DateTimeException} if another date/time problem occurs.
1308      *
1309      * @param text  the text to parse, not null
1310      * @param position  the position to parse from, updated with length parsed
1311      *  and the index of any error, null if parsing whole string
1312      * @return the engine representing the result of the parse, not null
1313      * @throws DateTimeParseException if the parse fails
1314      */
1315     private DateTimeBuilder parseToBuilder(final CharSequence text, final ParsePosition position) {
1316         ParsePosition pos = (position != null ? position : new ParsePosition(0));
1317         DateTimeParseContext result = parseUnresolved0(text, pos);
1318         if (result == null || pos.getErrorIndex() >= 0 || (position == null && pos.getIndex() < text.length())) {
1319             String abbr = "";
1320             if (text.length() > 64) {
1321                 abbr = text.subSequence(0, 64).toString() + "...";
1322             } else {
1323                 abbr = text.toString();
1324             }
1325             if (pos.getErrorIndex() >= 0) {
1326                 throw new DateTimeParseException("Text '" + abbr + "' could not be parsed at index " +
1327                         pos.getErrorIndex(), text, pos.getErrorIndex());
1328             } else {
1329                 throw new DateTimeParseException("Text '" + abbr + "' could not be parsed, unparsed text found at index " +
1330                         pos.getIndex(), text, pos.getIndex());
1331             }
1332         }
1333         return result.resolveFields().toBuilder();
1334     }
1335 
1336     /**
1337      * Parses the text using this formatter, without resolving the result, intended
1338      * for advanced use cases.
1339      * <p>
1340      * Parsing is implemented as a two-phase operation.
1341      * First, the text is parsed using the layout defined by the formatter, producing
1342      * a {@code Map} of field to value, a {@code ZoneId} and a {@code Chronology}.
1343      * Second, the parsed data is <em>resolved</em>, by validating, combining and
1344      * simplifying the various fields into more useful ones.
1345      * This method performs the parsing stage but not the resolving stage.
1346      * <p>
1347      * The result of this method is {@code TemporalAccessor} which represents the
1348      * data as seen in the input. Values are not validated, thus parsing a date string
1349      * of '2012-00-65' would result in a temporal with three fields - year of '2012',
1350      * month of '0' and day-of-month of '65'.
1351      * <p>
1352      * The text will be parsed from the specified start {@code ParsePosition}.
1353      * The entire length of the text does not have to be parsed, the {@code ParsePosition}
1354      * will be updated with the index at the end of parsing.
1355      * <p>
1356      * Errors are returned using the error index field of the {@code ParsePosition}
1357      * instead of {@code DateTimeParseException}.
1358      * The returned error index will be set to an index indicative of the error.
1359      * Callers must check for errors before using the context.
1360      * <p>
1361      * If the formatter parses the same field more than once with different values,
1362      * the result will be an error.
1363      * <p>
1364      * This method is intended for advanced use cases that need access to the
1365      * internal state during parsing. Typical application code should use
1366      * {@link #parse(CharSequence, TemporalQuery)} or the parse method on the target type.
1367      *
1368      * @param text  the text to parse, not null
1369      * @param position  the position to parse from, updated with length parsed
1370      *  and the index of any error, not null
1371      * @return the parsed text, null if the parse results in an error
1372      * @throws DateTimeException if some problem occurs during parsing
1373      * @throws IndexOutOfBoundsException if the position is invalid
1374      */
1375     public TemporalAccessor parseUnresolved(CharSequence text, ParsePosition position) {
1376         return parseUnresolved0(text, position);
1377     }
1378 
1379     private DateTimeParseContext parseUnresolved0(CharSequence text, ParsePosition position) {
1380         Objects.requireNonNull(text, "text");
1381         Objects.requireNonNull(position, "position");
1382         DateTimeParseContext context = new DateTimeParseContext(this);
1383         int pos = position.getIndex();
1384         pos = printerParser.parse(context, text, pos);
1385         if (pos < 0) {
1386             position.setErrorIndex(~pos);  // index not updated from input
1387             return null;
1388         }
1389         position.setIndex(pos);  // errorIndex not updated from input
1390         return context;
1391     }
1392 
1393     //-----------------------------------------------------------------------
1394     /**
1395      * Returns the formatter as a composite printer parser.
1396      *
1397      * @param optional  whether the printer/parser should be optional
1398      * @return the printer/parser, not null
1399      */
1400     CompositePrinterParser toPrinterParser(boolean optional) {
1401         return printerParser.withOptional(optional);
1402     }
1403 
1404     /**
1405      * Returns this formatter as a {@code java.text.Format} instance.
1406      * <p>
1407      * The returned {@link Format} instance will format any {@link TemporalAccessor}
1408      * and parses to a resolved {@link TemporalAccessor}.
1409      * <p>
1410      * Exceptions will follow the definitions of {@code Format}, see those methods
1411      * for details about {@code IllegalArgumentException} during formatting and
1412      * {@code ParseException} or null during parsing.
1413      * The format does not support attributing of the returned format string.
1414      *
1415      * @return this formatter as a classic format instance, not null
1416      */
1417     public Format toFormat() {
1418         return new ClassicFormat(this, null);
1419     }
1420 
1421     /**
1422      * Returns this formatter as a {@code java.text.Format} instance that will
1423      * parse using the specified query.
1424      * <p>
1425      * The returned {@link Format} instance will format any {@link TemporalAccessor}
1426      * and parses to the type specified.
1427      * The type must be one that is supported by {@link #parse}.
1428      * <p>
1429      * Exceptions will follow the definitions of {@code Format}, see those methods
1430      * for details about {@code IllegalArgumentException} during formatting and
1431      * {@code ParseException} or null during parsing.
1432      * The format does not support attributing of the returned format string.
1433      *
1434      * @param parseQuery  the query defining the type to parse to, not null
1435      * @return this formatter as a classic format instance, not null
1436      */
1437     public Format toFormat(TemporalQuery<?> parseQuery) {
1438         Objects.requireNonNull(parseQuery, "parseQuery");
1439         return new ClassicFormat(this, parseQuery);
1440     }
1441 
1442     //-----------------------------------------------------------------------
1443     /**
1444      * Returns a description of the underlying formatters.
1445      *


1468         private final DateTimeFormatter formatter;
1469         /** The type to be parsed. */
1470         private final TemporalQuery<?> parseType;
1471         /** Constructor. */
1472         public ClassicFormat(DateTimeFormatter formatter, TemporalQuery<?> parseType) {
1473             this.formatter = formatter;
1474             this.parseType = parseType;
1475         }
1476 
1477         @Override
1478         public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
1479             Objects.requireNonNull(obj, "obj");
1480             Objects.requireNonNull(toAppendTo, "toAppendTo");
1481             Objects.requireNonNull(pos, "pos");
1482             if (obj instanceof TemporalAccessor == false) {
1483                 throw new IllegalArgumentException("Format target must implement TemporalAccessor");
1484             }
1485             pos.setBeginIndex(0);
1486             pos.setEndIndex(0);
1487             try {
1488                 formatter.formatTo((TemporalAccessor) obj, toAppendTo);
1489             } catch (RuntimeException ex) {
1490                 throw new IllegalArgumentException(ex.getMessage(), ex);
1491             }
1492             return toAppendTo;
1493         }
1494         @Override
1495         public Object parseObject(String text) throws ParseException {
1496             Objects.requireNonNull(text, "text");
1497             try {
1498                 if (parseType == null) {
1499                     return formatter.parseToBuilder(text, null).resolve();
1500                 }
1501                 return formatter.parse(text, parseType);
1502             } catch (DateTimeParseException ex) {
1503                 throw new ParseException(ex.getMessage(), ex.getErrorIndex());
1504             } catch (RuntimeException ex) {
1505                 throw (ParseException) new ParseException(ex.getMessage(), 0).initCause(ex);
1506             }
1507         }
1508         @Override
1509         public Object parseObject(String text, ParsePosition pos) {
1510             Objects.requireNonNull(text, "text");
1511             DateTimeParseContext unresolved;
1512             try {
1513                 unresolved = formatter.parseUnresolved0(text, pos);
1514             } catch (IndexOutOfBoundsException ex) {
1515                 if (pos.getErrorIndex() < 0) {
1516                     pos.setErrorIndex(0);
1517                 }
1518                 return null;
1519             }
1520             if (unresolved == null) {
1521                 if (pos.getErrorIndex() < 0) {
1522                     pos.setErrorIndex(0);
1523                 }
1524                 return null;
1525             }
1526             try {
1527                 DateTimeBuilder builder = unresolved.resolveFields().toBuilder().resolve();
1528                 if (parseType == null) {
1529                     return builder;
1530                 }
1531                 return builder.query(parseType);

1532             } catch (RuntimeException ex) {
1533                 pos.setErrorIndex(0);
1534                 return null;
1535             }
1536         }
1537     }
1538 
1539 }