/*
 
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
 
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
*
 
* This code is free software; you can redistribute it and/or modify it
 
* under the terms of the GNU General Public License version 2 only, as
 
* published by the Free Software Foundation.
  
Oracle designates this
 
* particular file as subject to the "Classpath" exception as provided
 
* by Oracle in the LICENSE file that accompanied this code.
 
*
 
* This code is distributed in the hope that it will be useful, but WITHOUT
 
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
* FITNESS FOR A PARTICULAR PURPOSE.
  
See the GNU General Public License
 
* version 2 for more details (a copy is included in the LICENSE file that
 
* accompanied this code).
 
*
 
* You should have received a copy of the GNU General Public License version
 
* 2 along with this work; if not, write to the Free Software Foundation,
 
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 
*
 
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 
* or visit www.oracle.com if you need additional information or have any
 
* questions.
 
*/

/*
 
* This file is available under and governed by the GNU General Public
 
* License version 2 only, as published by the Free Software Foundation.
 
* However, the following notice accompanied the original version of this
 
* file:
 
*
 
* Copyright (c) 2008-2012, Stephen Colebourne & Michael Nascimento Santos
 
*
 
* All rights reserved.
 
*
 
* Redistribution and use in source and binary forms, with or without
 
* modification, are permitted provided that the following conditions are met:
 
*
 
*
  
* Redistributions of source code must retain the above copyright notice,
 
*
    
this list of conditions and the following disclaimer.
 
*
 
*
  
* Redistributions in binary form must reproduce the above copyright notice,
 
*
    
this list of conditions and the following disclaimer in the documentation
 
*
    
and/or other materials provided with the distribution.
 
*
 
*
  
* Neither the name of JSR-310 nor the names of its contributors
 
*
    
may be used to endorse or promote products derived from this software
 
*
    
without specific prior written permission.
 
*
 
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
*/

package java.time.format;

import static java.time.temporal.ChronoField.DAY_OF_MONTH;
import static java.time.temporal.ChronoField.DAY_OF_WEEK;
import static java.time.temporal.ChronoField.DAY_OF_YEAR;
import static java.time.temporal.ChronoField.HOUR_OF_DAY;
import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
import static java.time.temporal.ChronoField.NANO_OF_SECOND;
import static java.time.temporal.ChronoField.SECOND_OF_MINUTE;
import static java.time.temporal.ChronoField.YEAR;

import java.io.IOException;
import java.text.FieldPosition;
import java.text.Format;
import java.text.ParseException;
import java.text.ParsePosition;
import java.time.DateTimeException;
import java.time.Period;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.chrono.Chronology;
import java.time.chrono.IsoChronology;
import java.time.format.DateTimeFormatterBuilder.CompositePrinterParser;
import java.time.temporal.ChronoField;
import java.time.temporal.IsoFields;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalField;
import java.time.temporal.TemporalQuery;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 
* Formatter for printing and parsing date-time objects.
 
* <p>
 
* This class provides the main application entry point for printing and parsing
 
* and provides common implementations of {@code DateTimeFormatter}:
 
* <ul>
 
* <li>Using predefined constants, such as </li>
 
* <li>Using pattern letters, such as {@code uuuu-MMM-dd}</li>
 
* <li>Using localized styles, such as {@code long} or {@code medium}</li>
 
* </ul>
 
* <p>
 
* More complex formatters are provided by
 
* {@link DateTimeFormatterBuilder DateTimeFormatterBuilder}.
 
*
 
* <p>
 
* The main date-time classes provide two methods - one for formatting,
 
* {@code format(DateTimeFormatter formatter)}, and one for parsing,
 
* {@code parse(CharSequence text, DateTimeFormatter formatter)}.
 
* <p>For example:
 
* <blockquote><pre>
 
*
  
LocalDate date = LocalDate.now();
 
*
  
String text = date.format(formatter);
 
*
  
LocalDate parsedDate = LocalDate.parse(text, formatter);
 
* </pre></blockquote>
 
* <p>
 
* In addition to the format, formatters can be created with desired Locale,
 
* Chronology, ZoneId, and DecimalStyle.
 
* <p>
 
* The {@link #withLocale withLocale} method returns a new formatter that
 
* overrides the locale. The locale affects some aspects of formatting and
 
* parsing. For example, the {@link #ofLocalizedDate ofLocalizedDate} provides a
 
* formatter that uses the locale specific date format.
 
* <p>
 
* The {@link #withChronology withChronology} method returns a new formatter
 
* that overrides the chronology. If overridden, the date-time value is
 
* converted to the chronology before formatting. During parsing the date-time
 
* value is converted to the chronology before it is returned.
 
* <p>
 
* The {@link #withZone withZone} method returns a new formatter that overrides
 
* the zone. If overridden, the date-time value is converted to a ZonedDateTime
 
* with the requested ZoneId before formatting. During parsing the ZoneId is
 
* applied before the value is returned.
 
* <p>
 
* The {@link #withDecimalStyle withDecimalStyle} method returns a new formatter that
 
* overrides the {@link DecimalStyle}. The DecimalStyle symbols are used for
 
* formatting and parsing.
 
* <p>
 
* Some applications may need to use the older {@link Format java.text.Format}
 
* class for formatting. The
 
method returns an
 
* implementation of {@code java.text.Format}.
 
*
 
* <h3 id="predefined">Predefined Formatters</h3>
 
* <table summary="Predefined Formatters" cellpadding="2" cellspacing="3" border="0" >
 
* <thead>
 
* <tr class="tableSubHeadingColor">
 
* <th class="colFirst" align="left">Formatter</th>
 
* <th class="colFirst" align="left">Description</th>
 
* <th class="colLast" align="left">Example</th>
 
* </tr>
 
* </thead>
 
* <tbody>
 
* <tr class="rowColor">
 
* <td>{@link #ofLocalizedDate ofLocalizedDate(dateStyle)} </td>
 
* <td> Formatter with date style from the locale </td>
 
* <td> '2011-12-03'</td>
 
* </tr>
 
* <tr class="altColor">
 
* <td> {@link #ofLocalizedTime ofLocalizedTime(timeStyle)} </td>
 
* <td> Formatter with time style from the locale </td>
 
* <td> '10:15:30'</td>
 
* </tr>
 
* <tr class="rowColor">
 
* <td> {@link #ofLocalizedDateTime ofLocalizedDateTime(dateTimeStyle)} </td>
 
* <td> Formatter with a style for date and time from the locale</td>
 
* <td> '3 Jun 2008 11:05:30'</td>
 
* </tr>
 
* <tr class="altColor">
 
* <td> {@link #ofLocalizedDateTime ofLocalizedDateTime(dateStyle,timeStyle)}
 
* </td>
 
* <td> Formatter with date and time styles from the locale </td>
 
* <td> '3 Jun 2008 11:05'</td>
 
* </tr>
 
* <tr class="rowColor">
 
* <td> </td>
 
* <td>Basic ISO date </td> <td>'20111203'</td>
 
* </tr>
 
* <tr class="altColor">
 
* <td> </td>
 
* <td> ISO Local Date </td>
 
* <td>'2011-12-03'</td>
 
* </tr>
 
* <tr class="rowColor">
 
* <td> </td>
 
* <td> ISO Date with offset </td>
 
* <td>'2011-12-03+01:00'</td>
 
* </tr>
 
* <tr class="altColor">
 
* <td> </td>
 
* <td> ISO Date with or without offset </td>
 
* <td> '2011-12-03+01:00'; '2011-12-03'</td>
 
* </tr>
 
* <tr class="rowColor">
 
* <td> </td>
 
* <td> Time without offset </td>
 
* <td>'10:15:30'</td>
 
* </tr>
 
* <tr class="altColor">
 
* <td> </td>
 
* <td> Time with offset </td>
 
* <td>'10:15:30+01:00'</td>
 
* </tr>
 
* <tr class="rowColor">
 
* <td> </td>
 
* <td> Time with or without offset </td>
 
* <td>'10:15:30+01:00'; '10:15:30'</td>
 
* </tr>
 
* <tr class="altColor">
 
* <td> </td>
 
* <td> ISO Local Date and Time </td>
 
* <td>'2011-12-03T10:15:30'</td>
 
* </tr>
 
* <tr class="rowColor">
 
* <td> </td>
 
* <td> Date Time with Offset
 
* </td><td>2011-12-03T10:15:30+01:00'</td>
 
* </tr>
 
* <tr class="altColor">
 
* <td> </td>
 
* <td> Zoned Date Time </td>
 
* <td>'2011-12-03T10:15:30+01:00[Europe/Paris]'</td>
 
* </tr>
 
* <tr class="rowColor">
 
* <td> </td>
 
* <td> Date and time with ZoneId </td>
 
* <td>'2011-12-03T10:15:30+01:00[Europe/Paris]'</td>
 
* </tr>
 
* <tr class="altColor">
 
* <td> </td>
 
* <td> Year and day of year </td>
 
* <td>'2012-337'</td>
 
* </tr>
 
* <tr class="rowColor">
 
* <td> </td>
 
* <td> Year and Week </td>
 
* <td>2012-W48-6'</td></tr>
 
* <tr class="altColor">
 
* <td> </td>
 
* <td> Date and Time of an Instant </td>
 
* <td>'2011-12-03T10:15:30Z' </td>
 
* </tr>
 
* <tr class="rowColor">
 
* <td> </td>
 
* <td> RFC 1123 / RFC 822 </td>
 
* <td>'Tue, 3 Jun 2008 11:05:30 GMT'</td>
 
* </tr>
 
* </tbody>
 
* </table>
 
*
 
* <h3 id="patterns">Patterns for Formatting and Parsing</h3>
 
* Patterns are based on a simple sequence of letters and symbols.
 
* A pattern is used to create a Formatter using the
 
* {@link #ofPattern(String)} and {@link #ofPattern(String, Locale)} methods.
 
* For example,
 
* {@code "d MMM uuuu"} will format 2011-12-03 as '3&nbsp;Dec&nbsp;2011'.
 
* A formatter created from a pattern can be used as many times as necessary,
 
* it is immutable and is thread-safe.
 
* <p>
 
* For example:
 
* <blockquote><pre>
 
*
  
LocalDate date = LocalDate.now();
 
*
  
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy MM dd");
 
*
  
String text = date.format(formatter);
 
*
  
LocalDate parsedDate = LocalDate.parse(text, formatter);
 
* </pre></blockquote>
 
* <p>
 
* All letters 'A' to 'Z' and 'a' to 'z' are reserved as pattern letters. The
 
* following pattern letters are defined:
 
* <pre>
 
*
  
SymbolMeaning
                     
Presentation
      
Examples
 
*
  
-------------
                     
------------
      

 
*
   
G
       
era
                         
text
              
AD; Anno Domini; A
 
*
   
u
       
year
                        
              
2004; 04
 
*
   
y
       
year-of-era
                 
year
              
2004; 04
 
*
   
D
       
day-of-year
                 
number
            
189
 
*
   
M/L
     
month-of-year
               
number/text
       
7; 07; Jul; July; J
 
*
   
d
       
day-of-month
                
number
            
10
 
*
 
*
   
Q/q
     
quarter-of-year
             
number/text
       
3; 03; Q3; 3rd quarter
 
*
   
Y
       
week-based-year
             
year
              
1996; 96
 
*
   
w
       
week-of-week-based-year
     
number
            
27
 
*
   
W
       
week-of-month
               
number
            
4
 
*
   
E
       
day-of-week
                 
text
              
Tue; Tuesday; T
 
*
   
e/c
     
localized day-of-week
       
number/text2; 02; Tue; Tuesday; T
 
*
   
F
       
week-of-month
               
number
            
3
 
*
 
*
   
a
       
am-pm-of-day
                
text
              
PM
 
*
   
h
       
clock-hour-of-am-pm (1-12)
  
number
            
12
 
*
   
K
       
hour-of-am-pm (0-11)
        
number
            
0
 
*
   
k
       
clock-hour-of-am-pm (1-24)
  
number
            
0
 
*
 
*
   
H
       
hour-of-day (0-23)
          
number
            
0
 
*
   
m
       
minute-of-hour
              
number
            
30
 
*
   
s
       
second-of-minute
            
number55
 
*
   
S
       
fraction-of-second
          
fraction978
 
*
   
A
       
milli-of-day
                
number
            
1234
 
*
   
n
       
nano-of-second
              
number
            
987654321
 
*
   
N
       
nano-of-day
                 
number
            
1234000000
 
*
 
*
   
V
       
time-zone ID
                
zone-id
           
America/Los_Angeles; Z; -08:30
 
*
   
z
       
time-zone name
              
zone-name
         
Pacific Standard Time; PST
 
*
   
O
       
localized zone-offsetoffset-O
          
GMT+8; GMT+08:00; UTC-08:00;
 
*
   
X
       
zone-offset 'Z' for zero
    
offset-X
          
Z; -08; -0830; -08:30; -083015; -08:30:15;
 
*
   
x
       
zone-offset
                 
offset-x
          
+0000; -08; -0830; -08:30; -083015; -08:30:15;
 
*
   
Z
       
zone-offset
                 
offset-Z
          
+0000; -0800; -08:00;
 
*
 
*
   
p
       
pad next
                    
pad modifier
      
1
 
*
 
*
   
'
       
escape for text
             
delimiter
 
*
   
''
      
single quote
                
literal
           
'
 
*
   
[
       
optional section start
 
*
   
]
       
optional section end
 
*
   
#
       
reserved for future use
 
*
   
{
       
reserved for future use
 
*
   
}
       
reserved for future use
 
* </pre>
 
* <p>
 
* The count of pattern letters determines the format.
 
* <p>
 
* <b>Text</b>: The text style is determined based on the number of pattern
 
* letters used. Less than 4 pattern letters will use the
 
* {@link TextStyle#SHORT short form}. Exactly 4 pattern letters will use the
 
* {@link TextStyle#FULL full form}. Exactly 5 pattern letters will use the
 
* {@link TextStyle#NARROW narrow form}.
 
* Pattern letters 'L', 'c', and 'q' specify the stand-alone form of the text styles.
 
* <p>
 
* <b>Number</b>: If the count of letters is one, then the value is output using
 
* the minimum number of digits and without padding. Otherwise, the count of digits
 
* is used as the width of the output field, with the value zero-padded as necessary.
 
* The following pattern letters have constraints on the count of letters.
 
* Only one letter of 'c' and 'F' can be specified.
 
* Up to two letters of 'd', 'H', 'h', 'K', 'k', 'm', and 's' can be specified.
 
* Up to three letters of 'D' can be specified.
 
* <p>
 
* <b>Number/Text</b>: If the count of pattern letters is 3 or greater, use the
 
* Text rules above. Otherwise use the Number rules above.
 
* <p>
 
* <b>Fraction</b>: Outputs the nano-of-second field as a fraction-of-second.
 
* The nano-of-second value has nine digits, thus the count of pattern letters
 
* is from 1 to 9. If it is less than 9, then the nano-of-second value is
 
* truncated, with only the most significant digits being output.
 
* <p>
 
* <b>Year</b>: The count of letters determines the minimum field width below
 
* which padding is used. If the count of letters is two, then a
 
* {@link DateTimeFormatterBuilder#appendValueReduced reduced} two digit form is
 
* used. For printing, this outputs the rightmost two digits. For parsing, this
 
* will parse using the base value of 2000, resulting in a year within the range
 
* 2000 to 2099 inclusive. If the count of letters is less than four (but not
 
* two), then the sign is only output for negative years as per
 
* {@link SignStyle#NORMAL}. Otherwise, the sign is output if the pad width is
 
* exceeded, as per {@link SignStyle#EXCEEDS_PAD}.
 
* <p>
 
* <b>ZoneId</b>: This outputs the time-zone ID, such as 'Europe/Paris'. If the
 
* count of letters is two, then the time-zone ID is output. Any other count of
 
* letters throws {@code IllegalArgumentException}.
 
* <p>
 
* <b>Zone names</b>: This outputs the display name of the time-zone ID. If the
 
* count of letters is one, two or three, then the short name is output. If the
 
* count of letters is four, then the full name is output. Five or more letters
 
* throws {@code IllegalArgumentException}.
 
* <p>
 
* <b>Offset X and x</b>: This formats the offset based on the number of pattern
 
* letters. One letter outputs just the hour, such as '+01', unless the minute
 
* is non-zero in which case the minute is also output, such as '+0130'. Two
 
* letters outputs the hour and minute, without a colon, such as '+0130'. Three
 
* letters outputs the hour and minute, with a colon, such as '+01:30'. Four
 
* letters outputs the hour and minute and optional second, without a colon,
 
* such as '+013015'. Five letters outputs the hour and minute and optional
 
* second, with a colon, such as '+01:30:15'. Six or more letters throws
 
* {@code IllegalArgumentException}. Pattern letter 'X' (upper case) will output
 
* 'Z' when the offset to be output would be zero, whereas pattern letter 'x'
 
* (lower case) will output '+00', '+0000', or '+00:00'.
 
* <p>
 
* <b>Offset O</b>: This formats the localized offset based on the number of
 
* pattern letters. One letter outputs the {@linkplain TextStyle#SHORT short}
 
* form of the localized offset, which is localized offset text, such as 'GMT',
 
* with hour without leading zero, optional 2-digit minute and second if
 
* non-zero, and colon, for example 'GMT+8'. Four letters outputs the
 
* {@linkplain TextStyle#FULL full} form, which is localized offset text,
 
* such as 'GMT, with 2-digit hour and minute field, optional second field
 
* if non-zero, and colon, for example 'GMT+08:00'. Any other count of letters
 
* throws {@code IllegalArgumentException}.
 
* <p>
 
* <b>Offset Z</b>: This formats the offset based on the number of pattern
 
* letters. One, two or three letters outputs the hour and minute, without a
 
* colon, such as '+0130'. The output will be '+0000' when the offset is zero.
 
* Four letters outputs the {@linkplain TextStyle#FULL full} form of localized
 
* offset, equivalent to four letters of Offset-O. The output will be the
 
* corresponding localized offset text if the offset is zero. Five
 
* letters outputs the hour, minute, with optional second if non-zero, with
 
* colon. It outputs 'Z' if the offset is zero.
 
* Six or more letters throws {@code IllegalArgumentException}.
 
* <p>
 
* <b>Optional section</b>: The optional section markers work exactly like
 
* calling {@link DateTimeFormatterBuilder#optionalStart()} and
 
* {@link DateTimeFormatterBuilder#optionalEnd()}.
 
* <p>
 
* <b>Pad modifier</b>: Modifies the pattern that immediately follows to be
 
* padded with spaces. The pad width is determined by the number of pattern
 
* letters. This is the same as calling
 
* {@link DateTimeFormatterBuilder#padNext(int)}.
 
* <p>
 
* For example, 'ppH' outputs the hour-of-day padded on the left with spaces to
 
* a width of 2.
 
* <p>
 
* Any unrecognized letter is an error. Any non-letter character, other than
 
* '[', ']', '{', '}', '#' and the single quote will be output directly.
 
* Despite this, it is recommended to use single quotes around all characters
 
* that you want to output directly to ensure that future changes do not break
 
* your application.
 
*
 
* <h3 id="resolving">Resolving</h3>
 
* Parsing is implemented as a two-phase operation.
 
* First, the text is parsed using the layout defined by the formatter, producing
 
* a {@code Map} of field to value, a {@code ZoneId} and a {@code Chronology}.
 
* Second, the parsed data is <em>resolved</em>, by validating, combining and
 
* simplifying the various fields into more useful ones.
 
* <p>
 
* Five parsing methods are supplied by this class.
 
* Four of these perform both the parse and resolve phases.
 
* The fifth method, {@link #parseUnresolved(CharSequence, ParsePosition)},
 
* only performs the first phase, leaving the result unresolved.
 
* As such, it is essentially a low-level operation.
 
* <p>
 
* The resolve phase is controlled by two parameters, set on this class.
 
* <p>
 
* The {@link ResolverStyle} is an enum that offers three different approaches,
 
* strict, smart and lenient. The smart option is the default.
 
* It can be set using {@link #withResolverStyle(ResolverStyle)}.
 
* <p>
 
* The {@link #withResolverFields(TemporalField...)} parameter allows the
 
* set of fields that will be resolved to be filtered before resolving starts.
 
* For example, if the formatter has parsed a year, month, day-of-month
 
* and day-of-year, then there are two approaches to resolve a date:
 
* (year + month + day-of-month) and (year + day-of-year).
 
* The resolver fields allows one of the two approaches to be selected.
 
* If no resolver fields are set then both approaches must result in the same date.
 
* <p>
 
* Resolving separate fields to form a complete date and time is a complex
 
* process with behaviour distributed across a number of classes.
 
* It follows these steps:
 
* <ol>
 
* <li>The chronology is determined.
 
* The chronology of the result is either the chronology that was parsed,
 
* or if no chronology was parsed, it is the chronology set on this class,
 
* or if that is null, it is {@code IsoChronology}.
 
* <li>The {@code ChronoField} date fields are resolved.
 
* This is achieved using {@link Chronology#resolveDate(Map, ResolverStyle)}.
 
* Documentation about field resolution is located in the implementation
 
* of {@code Chronology}.
 
* <li>The {@code ChronoField} time fields are resolved.
 
* This is documented on {@link ChronoField} and is the same for all chronologies.
 
* <li>Any fields that are not {@code ChronoField} are processed.
 
* This is achieved using {@link TemporalField#resolve(Map, TemporalAccessor, ResolverStyle)}.
 
* Documentation about field resolution is located in the implementation
 
* of {@code TemporalField}.
 
* <li>The {@code ChronoField} date and time fields are re-resolved.
 
* This allows fields in step four to produce {@code ChronoField} values
 
* and have them be processed into dates and times.
 
* <li>A {@code LocalTime} is formed if there is at least an hour-of-day available.
 
* This involves providing default values for minute, second and fraction of second.
 
* <li>Any remaining unresolved fields are cross-checked against any
 
* date and/or time that was resolved. Thus, an earlier stage would resolve
 
* (year + month + day-of-month) to a date, and this stage would check that
 
* day-of-week was valid for the date.
 
* <li>If an {@linkplain #parsedExcessDays() excess number of days}
 
* was parsed then it is added to the date if a date is available.
 
* </ol>
 
*
 
* @implSpec
 
* This class is immutable and thread-safe.
 
*
 
* @since 1.8
 
*/

public final class DateTimeFormatter {

    
/**
     
* The printer and/or parser to use, not null.
     
*/
    
private final CompositePrinterParser printerParser;
    
/**
     
* The locale to use for formatting, not null.
     
*/
    
private final Locale locale;
    
/**
     
* The symbols to use for formatting, not null.
     
*/
    
private final DecimalStyle decimalStyle;
    
/**
     
* The resolver style to use, not null.
     
*/
    
private final ResolverStyle resolverStyle;
    
/**
     
* The fields to use in resolving, null for all fields.
     
*/
    
private final Set<TemporalField> resolverFields;
    
/**
     
* The chronology to use for formatting, null for no override.
     
*/
    
private final Chronology chrono;
    
/**
     
* The zone to use for formatting, null for no override.
     
*/
    
private final ZoneId zone;

    
//-----------------------------------------------------------------------
    
/**
     
* Creates a formatter using the specified pattern.
     
* <p>
     
* This method will create a formatter based on a simple
     
*
 
<a href="#patterns">pattern of letters and symbols</a>
     
* as described in the class documentation.
     
* For example, {@code d MMM uuuu} will format 2011-12-03 as '3 Dec 2011'.
     
* <p>
     
* The formatter will use the {@link Locale#getDefault(Locale.Category) default FORMAT locale}.
     
* This can be changed using {@link DateTimeFormatter#withLocale(Locale)} on the returned formatter
     
* Alternatively use the {@link #ofPattern(String, Locale)} variant of this method.
     
* <p>
     
* The returned formatter has no override chronology or zone.
     
* It uses {@link ResolverStyle#SMART SMART} resolver style.
     
*
     
* @param pattern
  
the pattern to use, not null
     
* @return the formatter based on the pattern, not null
     
* @throws IllegalArgumentException if the pattern is invalid
     
* @see DateTimeFormatterBuilder#appendPattern(String)
     
*/

    
public static DateTimeFormatter ofPattern(String pattern) {
        
return new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter();
    
}

    
/**
     
* Creates a formatter using the specified pattern and locale.
     
* <p>
     
* This method will create a formatter based on a simple
     
*
 
<a href="#patterns">pattern of letters and symbols</a>
     
* as described in the class documentation.
     
* For example, {@code d MMM uuuu} will format 2011-12-03 as '3 Dec 2011'.
     
* <p>
     
* The formatter will use the specified locale.
     
* This can be changed using {@link DateTimeFormatter#withLocale(Locale)} on the returned formatter
     
* <p>
     
* The returned formatter has no override chronology or zone.
     
* It uses {@link ResolverStyle#SMART SMART} resolver style.
     
*
     
* @param pattern
  
the pattern to use, not null
     
* @param locale
  
the locale to use, not null
     
* @return the formatter based on the pattern, not null
     
* @throws IllegalArgumentException if the pattern is invalid
     
* @see DateTimeFormatterBuilder#appendPattern(String)
     
*/

    
public static DateTimeFormatter ofPattern(String pattern, Locale locale) {
        
return new DateTimeFormatterBuilder().appendPattern(pattern).toFormatter(locale);
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* Returns a locale specific date format for the ISO chronology.
     
* <p>
     
* This returns a formatter that will format or parse a date.
     
* The exact format pattern used varies by locale.
     
* <p>
     
* The locale is determined from the formatter. The formatter returned directly by
     
* this method will use the {@link Locale#getDefault(Locale.Category) default FORMAT locale}.
     
* The locale can be controlled using {@link DateTimeFormatter#withLocale(Locale) withLocale(Locale)}
     
* on the result of this method.
     
* <p>
     
* Note that the localized pattern is looked up lazily.
     
* This {@code DateTimeFormatter} holds the style required and the locale,
     
* looking up the pattern required on demand.
     
* <p>
     
* The returned formatter has a chronology of ISO set to ensure dates in
     
* other calendar systems are correctly converted.
     
* It has no override zone and uses the {@link ResolverStyle#SMART SMART} resolver style.
     
*
     
* @param dateStyle
  
the formatter style to obtain, not null
     
* @return the date formatter, not null
     
*/

    
public static DateTimeFormatter ofLocalizedDate(FormatStyle dateStyle) {
        
Objects.requireNonNull(dateStyle, "dateStyle");
        
return new DateTimeFormatterBuilder().appendLocalized(dateStyle, null)
                
.toFormatter(ResolverStyle.SMART, IsoChronology.INSTANCE);
    
}

    
/**
     
* Returns a locale specific time format for the ISO chronology.
     
* <p>
     
* This returns a formatter that will format or parse a time.
     
* The exact format pattern used varies by locale.
     
* <p>
     
* The locale is determined from the formatter. The formatter returned directly by
     
* this method will use the {@link Locale#getDefault(Locale.Category) default FORMAT locale}.
     
* The locale can be controlled using {@link DateTimeFormatter#withLocale(Locale) withLocale(Locale)}
     
* on the result of this method.
     
* <p>
     
* Note that the localized pattern is looked up lazily.
     
* This {@code DateTimeFormatter} holds the style required and the locale,
     
* looking up the pattern required on demand.
     
* <p>
     
* The returned formatter has a chronology of ISO set to ensure dates in
     
* other calendar systems are correctly converted.
     
* It has no override zone and uses the {@link ResolverStyle#SMART SMART} resolver style.
     
*
     
* @param timeStyle
  
the formatter style to obtain, not null
     
* @return the time formatter, not null
     
*/

    
public static DateTimeFormatter ofLocalizedTime(FormatStyle timeStyle) {
        
Objects.requireNonNull(timeStyle, "timeStyle");
        
return new DateTimeFormatterBuilder().appendLocalized(null, timeStyle)
                
.toFormatter(ResolverStyle.SMART, IsoChronology.INSTANCE);
    
}

    
/**
     
* Returns a locale specific date-time formatter for the ISO chronology.
     
* <p>
     
* This returns a formatter that will format or parse a date-time.
     
* The exact format pattern used varies by locale.
     
* <p>
     
* The locale is determined from the formatter. The formatter returned directly by
     
* this method will use the {@link Locale#getDefault(Locale.Category) default FORMAT locale}.
     
* The locale can be controlled using {@link DateTimeFormatter#withLocale(Locale) withLocale(Locale)}
     
* on the result of this method.
     
* <p>
     
* Note that the localized pattern is looked up lazily.
     
* This {@code DateTimeFormatter} holds the style required and the locale,
     
* looking up the pattern required on demand.
     
* <p>
     
* The returned formatter has a chronology of ISO set to ensure dates in
     
* other calendar systems are correctly converted.
     
* It has no override zone and uses the {@link ResolverStyle#SMART SMART} resolver style.
     
*
     
* @param dateTimeStyle
  
the formatter style to obtain, not null
     
* @return the date-time formatter, not null
     
*/

    
public static DateTimeFormatter ofLocalizedDateTime(FormatStyle dateTimeStyle) {
        
Objects.requireNonNull(dateTimeStyle, "dateTimeStyle");
        
return new DateTimeFormatterBuilder().appendLocalized(dateTimeStyle, dateTimeStyle)
                
.toFormatter(ResolverStyle.SMART, IsoChronology.INSTANCE);
    
}

    
/**
     
* Returns a locale specific date and time format for the ISO chronology.
     
* <p>
     
* This returns a formatter that will format or parse a date-time.
     
* The exact format pattern used varies by locale.
     
* <p>
     
* The locale is determined from the formatter. The formatter returned directly by
     
* this method will use the {@link Locale#getDefault() default FORMAT locale}.
     
* The locale can be controlled using {@link DateTimeFormatter#withLocale(Locale) withLocale(Locale)}
     
* on the result of this method.
     
* <p>
     
* Note that the localized pattern is looked up lazily.
     
* This {@code DateTimeFormatter} holds the style required and the locale,
     
* looking up the pattern required on demand.
     
* <p>
     
* The returned formatter has a chronology of ISO set to ensure dates in
     
* other calendar systems are correctly converted.
     
* It has no override zone and uses the {@link ResolverStyle#SMART SMART} resolver style.
     
*
     
* @param dateStyle
  
the date formatter style to obtain, not null
     
* @param timeStyle
  
the time formatter style to obtain, not null
     
* @return the date, time or date-time formatter, not null
     
*/

    
public static DateTimeFormatter ofLocalizedDateTime(FormatStyle dateStyle, FormatStyle timeStyle) {
        
Objects.requireNonNull(dateStyle, "dateStyle");
        
Objects.requireNonNull(timeStyle, "timeStyle");
        
return new DateTimeFormatterBuilder().appendLocalized(dateStyle, timeStyle)
                
.toFormatter(ResolverStyle.SMART, IsoChronology.INSTANCE);
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* The ISO date formatter that formats or parses a date without an
     
* offset, such as '2011-12-03'.
     
* <p>
     
* This returns an immutable formatter capable of formatting and parsing
     
* the ISO-8601 extended local date format.
     
* The format consists of:
     
* <ul>
     
* <li>Four digits or more for the {@link ChronoField#YEAR year}.
     
* Years in the range 0000 to 9999 will be pre-padded by zero to ensure four digits.
     
* Years outside that range will have a prefixed positive or negative symbol.
     
* <li>A dash
     
* <li>Two digits for the {@link ChronoField#MONTH_OF_YEAR month-of-year}.
     
*
  
This is pre-padded by zero to ensure two digits.
     
* <li>A dash
     
* <li>Two digits for the {@link ChronoField#DAY_OF_MONTH day-of-month}.
     
*
  
This is pre-padded by zero to ensure two digits.
     
* </ul>
     
* <p>
     
* The returned formatter has a chronology of ISO set to ensure dates in
     
* other calendar systems are correctly converted.
     
* It has no override zone and uses the {@link ResolverStyle#STRICT STRICT} resolver style.
     
*/

    
public static final DateTimeFormatter ISO_LOCAL_DATE;
    
static {
        
ISO_LOCAL_DATE = new DateTimeFormatterBuilder()
                
.appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
                
.appendLiteral('-')
                
.appendValue(MONTH_OF_YEAR, 2)
                
.appendLiteral('-')
                
.appendValue(DAY_OF_MONTH, 2)
                
.toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* The ISO date formatter that formats or parses a date with an
     
* offset, such as '2011-12-03+01:00'.
     
* <p>
     
* This returns an immutable formatter capable of formatting and parsing
     
* the ISO-8601 extended offset date format.
     
* The format consists of:
     
* <ul>
     
* <li>The
 

     
* <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
     
*
  
they will be handled even though this is not part of the ISO-8601 standard.
     
*
  
Parsing is case insensitive.
     
* </ul>
     
* <p>
     
* The returned formatter has a chronology of ISO set to ensure dates in
     
* other calendar systems are correctly converted.
     
* It has no override zone and uses the {@link ResolverStyle#STRICT STRICT} resolver style.
     
*/

    
public static final DateTimeFormatter ISO_OFFSET_DATE;
    
static {
        
ISO_OFFSET_DATE = new DateTimeFormatterBuilder()
                
.parseCaseInsensitive()
                
.append(ISO_LOCAL_DATE)
                
.appendOffsetId()
                
.toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* The ISO date formatter that formats or parses a date with the
     
* offset if available, such as '2011-12-03' or '2011-12-03+01:00'.
     
* <p>
     
* This returns an immutable formatter capable of formatting and parsing
     
* the ISO-8601 extended date format.
     
* The format consists of:
     
* <ul>
     
* <li>The
 

     
* <li>If the offset is not available then the format is complete.
     
* <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
     
*
  
they will be handled even though this is not part of the ISO-8601 standard.
     
*
  
Parsing is case insensitive.
     
* </ul>
     
* <p>
     
* As this formatter has an optional element, it may be necessary to parse using
     
* {@link DateTimeFormatter#parseBest}.
     
* <p>
     
* The returned formatter has a chronology of ISO set to ensure dates in
     
* other calendar systems are correctly converted.
     
* It has no override zone and uses the {@link ResolverStyle#STRICT STRICT} resolver style.
     
*/

    
public static final DateTimeFormatter ISO_DATE;
    
static {
        
ISO_DATE = new DateTimeFormatterBuilder()
                
.parseCaseInsensitive()
                
.append(ISO_LOCAL_DATE)
                
.optionalStart()
                
.appendOffsetId()
                
.toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* The ISO time formatter that formats or parses a time without an
     
* offset, such as '10:15' or '10:15:30'.
     
* <p>
     
* This returns an immutable formatter capable of formatting and parsing
     
* the ISO-8601 extended local time format.
     
* The format consists of:
     
* <ul>
     
* <li>Two digits for the {@link ChronoField#HOUR_OF_DAY hour-of-day}.
     
*
  
This is pre-padded by zero to ensure two digits.
     
* <li>A colon
     
* <li>Two digits for the {@link ChronoField#MINUTE_OF_HOUR minute-of-hour}.
     
*
  
This is pre-padded by zero to ensure two digits.
     
* <li>If the second-of-minute is not available then the format is complete.
     
* <li>A colon
     
* <li>Two digits for the {@link ChronoField#SECOND_OF_MINUTE second-of-minute}.
     
*
  
This is pre-padded by zero to ensure two digits.
     
* <li>If the nano-of-second is zero or not available then the format is complete.
     
* <li>A decimal point
     
* <li>One to nine digits for the {@link ChronoField#NANO_OF_SECOND nano-of-second}.
     
*
  
As many digits will be output as required.
     
* </ul>
     
* <p>
     
* The returned formatter has no override chronology or zone.
     
* It uses the {@link ResolverStyle#STRICT STRICT} resolver style.
     
*/

    
public static final DateTimeFormatter ISO_LOCAL_TIME;
    
static {
        
ISO_LOCAL_TIME = new DateTimeFormatterBuilder()
                
.appendValue(HOUR_OF_DAY, 2)
                
.appendLiteral(':')
                
.appendValue(MINUTE_OF_HOUR, 2)
                
.optionalStart()
                
.appendLiteral(':')
                
.appendValue(SECOND_OF_MINUTE, 2)
                
.optionalStart()
                
.appendFraction(NANO_OF_SECOND, 0, 9, true)
                
.toFormatter(ResolverStyle.STRICT, null);
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* The ISO time formatter that formats or parses a time with an
     
* offset, such as '10:15+01:00' or '10:15:30+01:00'.
     
* <p>
     
* This returns an immutable formatter capable of formatting and parsing
     
* the ISO-8601 extended offset time format.
     
* The format consists of:
     
* <ul>
     
* <li>The
 

     
* <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
     
*
  
they will be handled even though this is not part of the ISO-8601 standard.
     
*
  
Parsing is case insensitive.
     
* </ul>
     
* <p>
     
* The returned formatter has no override chronology or zone.
     
* It uses the {@link ResolverStyle#STRICT STRICT} resolver style.
     
*/

    
public static final DateTimeFormatter ISO_OFFSET_TIME;
    
static {
        
ISO_OFFSET_TIME = new DateTimeFormatterBuilder()
                
.parseCaseInsensitive()
                
.append(ISO_LOCAL_TIME)
                
.appendOffsetId()
                
.toFormatter(ResolverStyle.STRICT, null);
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* The ISO time formatter that formats or parses a time, with the
     
* offset if available, such as '10:15', '10:15:30' or '10:15:30+01:00'.
     
* <p>
     
* This returns an immutable formatter capable of formatting and parsing
     
* the ISO-8601 extended offset time format.
     
* The format consists of:
     
* <ul>
     
* <li>The
 

     
* <li>If the offset is not available then the format is complete.
     
* <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
     
*
  
they will be handled even though this is not part of the ISO-8601 standard.
     
*
  
Parsing is case insensitive.
     
* </ul>
     
* <p>
     
* As this formatter has an optional element, it may be necessary to parse using
     
* {@link DateTimeFormatter#parseBest}.
     
* <p>
     
* The returned formatter has no override chronology or zone.
     
* It uses the {@link ResolverStyle#STRICT STRICT} resolver style.
     
*/

    
public static final DateTimeFormatter ISO_TIME;
    
static {
        
ISO_TIME = new DateTimeFormatterBuilder()
                
.parseCaseInsensitive()
                
.append(ISO_LOCAL_TIME)
                
.optionalStart()
                
.appendOffsetId()
                
.toFormatter(ResolverStyle.STRICT, null);
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* The ISO date-time formatter that formats or parses a date-time without
     
* an offset, such as '2011-12-03T10:15:30'.
     
* <p>
     
* This returns an immutable formatter capable of formatting and parsing
     
* the ISO-8601 extended offset date-time format.
     
* The format consists of:
     
* <ul>
     
* <li>The
 

     
* <li>The letter 'T'. Parsing is case insensitive.
     
* <li>The
 

     
* </ul>
     
* <p>
     
* The returned formatter has a chronology of ISO set to ensure dates in
     
* other calendar systems are correctly converted.
     
* It has no override zone and uses the {@link ResolverStyle#STRICT STRICT} resolver style.
     
*/

    
public static final DateTimeFormatter ISO_LOCAL_DATE_TIME;
    
static {
        
ISO_LOCAL_DATE_TIME = new DateTimeFormatterBuilder()
                
.parseCaseInsensitive()
                
.append(ISO_LOCAL_DATE)
                
.appendLiteral('T')
                
.append(ISO_LOCAL_TIME)
                
.toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* The ISO date-time formatter that formats or parses a date-time with an
     
* offset, such as '2011-12-03T10:15:30+01:00'.
     
* <p>
     
* This returns an immutable formatter capable of formatting and parsing
     
* the ISO-8601 extended offset date-time format.
     
* The format consists of:
     
* <ul>
     
* <li>The
 

     
* <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
     
*
  
they will be handled even though this is not part of the ISO-8601 standard.
     
*
  
Parsing is case insensitive.
     
* </ul>
     
* <p>
     
* The returned formatter has a chronology of ISO set to ensure dates in
     
* other calendar systems are correctly converted.
     
* It has no override zone and uses the {@link ResolverStyle#STRICT STRICT} resolver style.
     
*/

    
public static final DateTimeFormatter ISO_OFFSET_DATE_TIME;
    
static {
        
ISO_OFFSET_DATE_TIME = new DateTimeFormatterBuilder()
                
.parseCaseInsensitive()
                
.append(ISO_LOCAL_DATE_TIME)
                
.appendOffsetId()
                
.toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* The ISO-like date-time formatter that formats or parses a date-time with
     
* offset and zone, such as '2011-12-03T10:15:30+01:00[Europe/Paris]'.
     
* <p>
     
* This returns an immutable formatter capable of formatting and parsing
     
* a format that extends the ISO-8601 extended offset date-time format
     
* to add the time-zone.
     
* The section in square brackets is not part of the ISO-8601 standard.
     
* The format consists of:
     
* <ul>
     
* <li>The
 

     
* <li>If the zone ID is not available or is a {@code ZoneOffset} then the format is complete.
     
* <li>An open square bracket '['.
     
* <li>The {@link ZoneId#getId() zone ID}. This is not part of the ISO-8601 standard.
     
*
  
Parsing is case sensitive.
     
* <li>A close square bracket ']'.
     
* </ul>
     
* <p>
     
* The returned formatter has a chronology of ISO set to ensure dates in
     
* other calendar systems are correctly converted.
     
* It has no override zone and uses the {@link ResolverStyle#STRICT STRICT} resolver style.
     
*/

    
public static final DateTimeFormatter ISO_ZONED_DATE_TIME;
    
static {
        
ISO_ZONED_DATE_TIME = new DateTimeFormatterBuilder()
                
.append(ISO_OFFSET_DATE_TIME)
                
.optionalStart()
                
.appendLiteral('[')
                
.parseCaseSensitive()
                
.appendZoneRegionId()
                
.appendLiteral(']')
                
.toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* The ISO-like date-time formatter that formats or parses a date-time with
     
* the offset and zone if available, such as '2011-12-03T10:15:30',
     
* '2011-12-03T10:15:30+01:00' or '2011-12-03T10:15:30+01:00[Europe/Paris]'.
     
* <p>
     
* This returns an immutable formatter capable of formatting and parsing
     
* the ISO-8601 extended local or offset date-time format, as well as the
     
* extended non-ISO form specifying the time-zone.
     
* The format consists of:
     
* <ul>
     
* <li>The
 

     
* <li>If the offset is not available to format or parse then the format is complete.
     
* <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
     
*
  
they will be handled even though this is not part of the ISO-8601 standard.
     
* <li>If the zone ID is not available or is a {@code ZoneOffset} then the format is complete.
     
* <li>An open square bracket '['.
     
* <li>The {@link ZoneId#getId() zone ID}. This is not part of the ISO-8601 standard.
     
*
  
Parsing is case sensitive.
     
* <li>A close square bracket ']'.
     
* </ul>
     
* <p>
     
* As this formatter has an optional element, it may be necessary to parse using
     
* {@link DateTimeFormatter#parseBest}.
     
* <p>
     
* The returned formatter has a chronology of ISO set to ensure dates in
     
* other calendar systems are correctly converted.
     
* It has no override zone and uses the {@link ResolverStyle#STRICT STRICT} resolver style.
     
*/

    
public static final DateTimeFormatter ISO_DATE_TIME;
    
static {
        
ISO_DATE_TIME = new DateTimeFormatterBuilder()
                
.append(ISO_LOCAL_DATE_TIME)
                
.optionalStart()
                
.appendOffsetId()
                
.optionalStart()
                
.appendLiteral('[')
                
.parseCaseSensitive()
                
.appendZoneRegionId()
                
.appendLiteral(']')
                
.toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* The ISO date formatter that formats or parses the ordinal date
     
* without an offset, such as '2012-337'.
     
* <p>
     
* This returns an immutable formatter capable of formatting and parsing
     
* the ISO-8601 extended ordinal date format.
     
* The format consists of:
     
* <ul>
     
* <li>Four digits or more for the {@link ChronoField#YEAR year}.
     
* Years in the range 0000 to 9999 will be pre-padded by zero to ensure four digits.
     
* Years outside that range will have a prefixed positive or negative symbol.
     
* <li>A dash
     
* <li>Three digits for the {@link ChronoField#DAY_OF_YEAR day-of-year}.
     
*
  
This is pre-padded by zero to ensure three digits.
     
* <li>If the offset is not available to format or parse then the format is complete.
     
* <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
     
*
  
they will be handled even though this is not part of the ISO-8601 standard.
     
*
  
Parsing is case insensitive.
     
* </ul>
     
* <p>
     
* As this formatter has an optional element, it may be necessary to parse using
     
* {@link DateTimeFormatter#parseBest}.
     
* <p>
     
* The returned formatter has a chronology of ISO set to ensure dates in
     
* other calendar systems are correctly converted.
     
* It has no override zone and uses the {@link ResolverStyle#STRICT STRICT} resolver style.
     
*/

    
public static final DateTimeFormatter ISO_ORDINAL_DATE;
    
static {
        
ISO_ORDINAL_DATE = new DateTimeFormatterBuilder()
                
.parseCaseInsensitive()
                
.appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
                
.appendLiteral('-')
                
.appendValue(DAY_OF_YEAR, 3)
                
.optionalStart()
                
.appendOffsetId()
                
.toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* The ISO date formatter that formats or parses the week-based date
     
* without an offset, such as '2012-W48-6'.
     
* <p>
     
* This returns an immutable formatter capable of formatting and parsing
     
* the ISO-8601 extended week-based date format.
     
* The format consists of:
     
* <ul>
     
* <li>Four digits or more for the {@link IsoFields#WEEK_BASED_YEAR week-based-year}.
     
* Years in the range 0000 to 9999 will be pre-padded by zero to ensure four digits.
     
* Years outside that range will have a prefixed positive or negative symbol.
     
* <li>A dash
     
* <li>The letter 'W'. Parsing is case insensitive.
     
* <li>Two digits for the {@link IsoFields#WEEK_OF_WEEK_BASED_YEAR week-of-week-based-year}.
     
*
  
This is pre-padded by zero to ensure three digits.
     
* <li>A dash
     
* <li>One digit for the {@link ChronoField#DAY_OF_WEEK day-of-week}.
     
*
  
The value run from Monday (1) to Sunday (7).
     
* <li>If the offset is not available to format or parse then the format is complete.
     
* <li>The {@link ZoneOffset#getId() offset ID}. If the offset has seconds then
     
*
  
they will be handled even though this is not part of the ISO-8601 standard.
     
*
  
Parsing is case insensitive.
     
* </ul>
     
* <p>
     
* As this formatter has an optional element, it may be necessary to parse using
     
* {@link DateTimeFormatter#parseBest}.
     
* <p>
     
* The returned formatter has a chronology of ISO set to ensure dates in
     
* other calendar systems are correctly converted.
     
* It has no override zone and uses the {@link ResolverStyle#STRICT STRICT} resolver style.
     
*/

    
public static final DateTimeFormatter ISO_WEEK_DATE;
    
static {
        
ISO_WEEK_DATE = new DateTimeFormatterBuilder()
                
.parseCaseInsensitive()
                
.appendValue(IsoFields.WEEK_BASED_YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
                
.appendLiteral("-W")
                
.appendValue(IsoFields.WEEK_OF_WEEK_BASED_YEAR, 2)
                
.appendLiteral('-')
                
.appendValue(DAY_OF_WEEK, 1)
                
.optionalStart()
                
.appendOffsetId()
                
.toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* The ISO instant formatter that formats or parses an instant in UTC,
     
* such as '2011-12-03T10:15:30Z'.
     
* <p>
     
* This returns an immutable formatter capable of formatting and parsing
     
* the ISO-8601 instant format.
     
* When formatting, the second-of-minute is always output.
     
* The nano-of-second outputs zero, three, six or nine digits digits as necessary.
     
* When parsing, time to at least the seconds field is required.
     
* Fractional seconds from zero to nine are parsed.
     
* The localized decimal style is not used.
     
* <p>
     
* This is a special case formatter intended to allow a human readable form
     
* of an
 
. The {@code Instant} class is designed to
     
* only represent a point in time and internally stores a value in nanoseconds
     
* from a fixed epoch of 1970-01-01Z. As such, an {@code Instant} cannot be
     
* formatted as a date or time without providing some form of time-zone.
     
* This formatter allows the {@code Instant} to be formatted, by providing
     
* a suitable conversion using {@code ZoneOffset.UTC}.
     
* <p>
     
* The format consists of:
     
* <ul>
     
* <li>The
 
 
where the instant is converted from
     
*
  
{@link ChronoField#INSTANT_SECONDS} and {@link ChronoField#NANO_OF_SECOND}
     
*
  
using the {@code UTC} offset. Parsing is case insensitive.
     
* </ul>
     
* <p>
     
* The returned formatter has no override chronology or zone.
     
* It uses the {@link ResolverStyle#STRICT STRICT} resolver style.
     
*/

    
public static final DateTimeFormatter ISO_INSTANT;
    
static {
        
ISO_INSTANT = new DateTimeFormatterBuilder()
                
.parseCaseInsensitive()
                
.appendInstant()
                
.toFormatter(ResolverStyle.STRICT, null);
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* The ISO date formatter that formats or parses a date without an
     
* offset, such as '20111203'.
     
* <p>
     
* This returns an immutable formatter capable of formatting and parsing
     
* the ISO-8601 basic local date format.
     
* The format consists of:
     
* <ul>
     
* <li>Four digits for the {@link ChronoField#YEAR year}.
     
*
  
Only years in the range 0000 to 9999 are supported.
     
* <li>Two digits for the {@link ChronoField#MONTH_OF_YEAR month-of-year}.
     
*
  
This is pre-padded by zero to ensure two digits.
     
* <li>Two digits for the {@link ChronoField#DAY_OF_MONTH day-of-month}.
     
*
  
This is pre-padded by zero to ensure two digits.
     
* <li>If the offset is not available to format or parse then the format is complete.
     
* <li>The {@link ZoneOffset#getId() offset ID} without colons. If the offset has
     
*
  
seconds then they will be handled even though this is not part of the ISO-8601 standard.
     
*
  
Parsing is case insensitive.
     
* </ul>
     
* <p>
     
* As this formatter has an optional element, it may be necessary to parse using
     
* {@link DateTimeFormatter#parseBest}.
     
* <p>
     
* The returned formatter has a chronology of ISO set to ensure dates in
     
* other calendar systems are correctly converted.
     
* It has no override zone and uses the {@link ResolverStyle#STRICT STRICT} resolver style.
     
*/

    
public static final DateTimeFormatter BASIC_ISO_DATE;
    
static {
        
BASIC_ISO_DATE = new DateTimeFormatterBuilder()
                
.parseCaseInsensitive()
                
.appendValue(YEAR, 4)
                
.appendValue(MONTH_OF_YEAR, 2)
                
.appendValue(DAY_OF_MONTH, 2)
                
.optionalStart()
                
.appendOffset("+HHMMss", "Z")
                
.toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* The RFC-1123 date-time formatter, such as 'Tue, 3 Jun 2008 11:05:30 GMT'.
     
* <p>
     
* This returns an immutable formatter capable of formatting and parsing
     
* most of the RFC-1123 format.
     
* RFC-1123 updates RFC-822 changing the year from two digits to four.
     
* This implementation requires a four digit year.
     
* This implementation also does not handle North American or military zone
     
* names, only 'GMT' and offset amounts.
     
* <p>
     
* The format consists of:
     
* <ul>
     
* <li>If the day-of-week is not available to format or parse then jump to day-of-month.
     
* <li>Three letter {@link ChronoField#DAY_OF_WEEK day-of-week} in English.
     
* <li>A comma
     
* <li>A space
     
* <li>One or two digits for the {@link ChronoField#DAY_OF_MONTH day-of-month}.
     
* <li>A space
     
* <li>Three letter {@link ChronoField#MONTH_OF_YEAR month-of-year} in English.
     
* <li>A space
     
* <li>Four digits for the {@link ChronoField#YEAR year}.
     
*
  
Only years in the range 0000 to 9999 are supported.
     
* <li>A space
     
* <li>Two digits for the {@link ChronoField#HOUR_OF_DAY hour-of-day}.
     
*
  
This is pre-padded by zero to ensure two digits.
     
* <li>A colon
     
* <li>Two digits for the {@link ChronoField#MINUTE_OF_HOUR minute-of-hour}.
     
*
  
This is pre-padded by zero to ensure two digits.
     
* <li>If the second-of-minute is not available then jump to the next space.
     
* <li>A colon
     
* <li>Two digits for the {@link ChronoField#SECOND_OF_MINUTE second-of-minute}.
     
*
  
This is pre-padded by zero to ensure two digits.
     
* <li>A space
     
* <li>The {@link ZoneOffset#getId() offset ID} without colons or seconds.
     
*
  
An offset of zero uses "GMT". North American zone names and military zone names are not handled.
     
* </ul>
     
* <p>
     
* Parsing is case insensitive.
     
* <p>
     
* The returned formatter has a chronology of ISO set to ensure dates in
     
* other calendar systems are correctly converted.
     
* It has no override zone and uses the {@link ResolverStyle#SMART SMART} resolver style.
     
*/

    
public static final DateTimeFormatter RFC_1123_DATE_TIME;
    
static {
        
// manually code maps to ensure correct data always used
        
// (locale data can be changed by application code)
        
Map<Long, String> dow = new HashMap<>();
        
dow.put(1L, "Mon");
        
dow.put(2L, "Tue");
        
dow.put(3L, "Wed");
        
dow.put(4L, "Thu");
        
dow.put(5L, "Fri");
        
dow.put(6L, "Sat");
        
dow.put(7L, "Sun");
        
Map<Long, String> moy = new HashMap<>();
        
moy.put(1L, "Jan");
        
moy.put(2L, "Feb");
        
moy.put(3L, "Mar");
        
moy.put(4L, "Apr");
        
moy.put(5L, "May");
        
moy.put(6L, "Jun");
        
moy.put(7L, "Jul");
        
moy.put(8L, "Aug");
        
moy.put(9L, "Sep");
        
moy.put(10L, "Oct");
        
moy.put(11L, "Nov");
        
moy.put(12L, "Dec");
        
RFC_1123_DATE_TIME = new DateTimeFormatterBuilder()
                
.parseCaseInsensitive()
                
.parseLenient()
                
.optionalStart()
                
.appendText(DAY_OF_WEEK, dow)
                
.appendLiteral(", ")
                
.optionalEnd()
                
.appendValue(DAY_OF_MONTH, 1, 2, SignStyle.NOT_NEGATIVE)
                
.appendLiteral(' ')
                
.appendText(MONTH_OF_YEAR, moy)
                
.appendLiteral(' ')
                
.appendValue(YEAR, 4)
  
// 2 digit year not handled
                
.appendLiteral(' ')
                
.appendValue(HOUR_OF_DAY, 2)
                
.appendLiteral(':')
                
.appendValue(MINUTE_OF_HOUR, 2)
                
.optionalStart()
                
.appendLiteral(':')
                
.appendValue(SECOND_OF_MINUTE, 2)
                
.optionalEnd()
                
.appendLiteral(' ')
                
.appendOffset("+HHMM", "GMT")
  
// should handle UT/Z/EST/EDT/CST/CDT/MST/MDT/PST/MDT
                
.toFormatter(ResolverStyle.SMART, IsoChronology.INSTANCE);
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* A query that provides access to the excess days that were parsed.
     
* <p>
     
* This returns a singleton {@linkplain TemporalQuery query} that provides
     
* access to additional information from the parse. The query always returns
     
* a non-null period, with a zero period returned instead of null.
     
* <p>
     
* There are two situations where this query may return a non-zero period.
     
* <ul>
     
* <li>If the {@code ResolverStyle} is {@code LENIENT} and a time is parsed
     
*
  
without a date, then the complete result of the parse consists of a
     
*
  
{@code LocalTime} and an excess {@code Period} in days.
     
*
     
* <li>If the {@code ResolverStyle} is {@code SMART} and a time is parsed
     
*
  
without a date where the time is 24:00:00, then the complete result of
     
*
  
the parse consists of a {@code LocalTime} of 00:00:00 and an excess
     
*
  
{@code Period} of one day.
     
* </ul>
     
* <p>
     
* In both cases, if a complete {@code ChronoLocalDateTime} or {@code Instant}
     
* is parsed, then the excess days are added to the date part.
     
* As a result, this query will return a zero period.
     
* <p>
     
* The {@code SMART} behaviour handles the common "end of day" 24:00 value.
     
* Processing in {@code LENIENT} mode also produces the same result:
     
* <pre>
     
*
  
Text to parse
        
Parsed object
                         
Excess days
     
*
  
"2012-12-03T00:00"
   
LocalDateTime.of(2012, 12, 3, 0, 0)ZERO
     
*
  
"2012-12-03T24:00"
   
LocalDateTime.of(2012, 12, 4, 0, 0)ZERO
     
*
  
"00:00"
              
LocalTime.of(0, 0)
                    
ZERO
     
*
  
"24:00"
              
LocalTime.of(0, 0)
                    
Period.ofDays(1)
     
* </pre>
     
* The query can be used as follows:
     
* <pre>
     
*
  
TemporalAccessor parsed = formatter.parse(str);
     
*
  
LocalTime time = parsed.query(LocalTime::from);
     
*
  
Period extraDays = parsed.query(DateTimeFormatter.parsedExcessDays());
     
* </pre>
     
* @return a query that provides access to the excess days that were parsed
     
*/

    
public static final TemporalQuery<Period> parsedExcessDays() {
        
return PARSED_EXCESS_DAYS;
    
}
    
private static final TemporalQuery<Period> PARSED_EXCESS_DAYS = t -> {
        
if (t instanceof Parsed) {
            
return ((Parsed) t).excessDays;
        
} else {
            
return Period.ZERO;
        
}
    
};

    
/**
     
* A query that provides access to whether a leap-second was parsed.
     
* <p>
     
* This returns a singleton {@linkplain TemporalQuery query} that provides
     
* access to additional information from the parse. The query always returns
     
* a non-null boolean, true if parsing saw a leap-second, false if not.
     
* <p>
     
* Instant parsing handles the special "leap second" time of '23:59:60'.
     
* Leap seconds occur at '23:59:60' in the UTC time-zone, but at other
     
* local times in different time-zones. To avoid this potential ambiguity,
     
* the handling of leap-seconds is limited to
     
* {@link DateTimeFormatterBuilder#appendInstant()}, as that method
     
* always parses the instant with the UTC zone offset.
     
* <p>
     
* If the time '23:59:60' is received, then a simple conversion is applied,
     
* replacing the second-of-minute of 60 with 59. This query can be used
     
* on the parse result to determine if the leap-second adjustment was made.
     
* The query will return {@code true} if it did adjust to remove the
     
* leap-second, and {@code false} if not. Note that applying a leap-second
     
* smoothing mechanism, such as UTC-SLS, is the responsibility of the
     
* application, as follows:
     
* <pre>
     
*
  
TemporalAccessor parsed = formatter.parse(str);
     
*
  
Instant instant = parsed.query(Instant::from);
     
*
  
if (parsed.query(DateTimeFormatter.parsedLeapSecond())) {
     
*
    
// validate leap-second is correct and apply correct smoothing
     
*
  
}
     
* </pre>
     
* @return a query that provides access to whether a leap-second was parsed
     
*/

    
public static final TemporalQuery<Boolean> parsedLeapSecond() {
        
return PARSED_LEAP_SECOND;
    
}
    
private static final TemporalQuery<Boolean> PARSED_LEAP_SECOND = t -> {
        
if (t instanceof Parsed) {
            
return ((Parsed) t).leapSecond;
        
} else {
            
return Boolean.FALSE;
        
}
    
};

    
//-----------------------------------------------------------------------
    
/**
     
* Constructor.
     
*
     
* @param printerParser
  
the printer/parser to use, not null
     
* @param locale
  
the locale to use, not null
     
* @param decimalStyle
  
the DecimalStyle to use, not null
     
* @param resolverStyle
  
the resolver style to use, not null
     
* @param resolverFields
  
the fields to use during resolving, null for all fields
     
* @param chrono
  
the chronology to use, null for no override
     
* @param zone
  
the zone to use, null for no override
     
*/

    
DateTimeFormatter(CompositePrinterParser printerParser,
            
Locale locale, DecimalStyle decimalStyle,
            
ResolverStyle resolverStyle, Set<TemporalField> resolverFields,
            
Chronology chrono, ZoneId zone) {
        
this.printerParser = Objects.requireNonNull(printerParser, "printerParser");
        
this.resolverFields = resolverFields;
        
this.locale = Objects.requireNonNull(locale, "locale");
        
this.decimalStyle = Objects.requireNonNull(decimalStyle, "decimalStyle");
        
this.resolverStyle = Objects.requireNonNull(resolverStyle, "resolverStyle");
        
this.chrono = chrono;
        
this.zone = zone;
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* Gets the locale to be used during formatting.
     
* <p>
     
* This is used to lookup any part of the formatter needing specific
     
* localization, such as the text or localized pattern.
     
*
     
* @return the locale of this formatter, not null
     
*/

    
public Locale getLocale() {
        
return locale;
    
}

    
/**
     
* Returns a copy of this formatter with a new locale.
     
* <p>
     
* This is used to lookup any part of the formatter needing specific
     
* localization, such as the text or localized pattern.
     
* <p>
     
* This instance is immutable and unaffected by this method call.
     
*
     
* @param locale
  
the new locale, not null
     
* @return a formatter based on this formatter with the requested locale, not null
     
*/

    
public DateTimeFormatter withLocale(Locale locale) {
        
if (this.locale.equals(locale)) {
            
return this;
        
}
        
return new DateTimeFormatter(printerParser, locale, decimalStyle, resolverStyle, resolverFields, chrono, zone);
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* Gets the DecimalStyle to be used during formatting.
     
*
     
* @return the locale of this formatter, not null
     
*/

    
public DecimalStyle getDecimalStyle() {
        
return decimalStyle;
    
}

    
/**
     
* Returns a copy of this formatter with a new DecimalStyle.
     
* <p>
     
* This instance is immutable and unaffected by this method call.
     
*
     
* @param decimalStyle
  
the new DecimalStyle, not null
     
* @return a formatter based on this formatter with the requested DecimalStyle, not null
     
*/

    
public DateTimeFormatter withDecimalStyle(DecimalStyle decimalStyle) {
        
if (this.decimalStyle.equals(decimalStyle)) {
            
return this;
        
}
        
return new DateTimeFormatter(printerParser, locale, decimalStyle, resolverStyle, resolverFields, chrono, zone);
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* Gets the overriding chronology to be used during formatting.
     
* <p>
     
* This returns the override chronology, used to convert dates.
     
* By default, a formatter has no override chronology, returning null.
     
* See {@link #withChronology(Chronology)} for more details on overriding.
     
*
     
* @return the override chronology of this formatter, null if no override
     
*/

    
public Chronology getChronology() {
        
return chrono;
    
}

    
/**
     
* Returns a copy of this formatter with a new override chronology.
     
* <p>
     
* This returns a formatter with similar state to this formatter but
     
* with the override chronology set.
     
* By default, a formatter has no override chronology, returning null.
     
* <p>
     
* If an override is added, then any date that is formatted or parsed will be affected.
     
* <p>
     
* When formatting, if the temporal object contains a date, then it will
     
* be converted to a date in the override chronology.
     
* Whether the temporal contains a date is determined by querying the
     
* {@link ChronoField#EPOCH_DAY EPOCH_DAY} field.
     
* Any time or zone will be retained unaltered unless overridden.
     
* <p>
     
* If the temporal object does not contain a date, but does contain one
     
* or more {@code ChronoField} date fields, then a {@code DateTimeException}
     
* is thrown. In all other cases, the override chronology is added to the temporal,
     
* replacing any previous chronology, but without changing the date/time.
     
* <p>
     
* When parsing, there are two distinct cases to consider.
     
* If a chronology has been parsed directly from the text, perhaps because
     
* {@link DateTimeFormatterBuilder#appendChronologyId()} was used, then
     
* this override chronology has no effect.
     
* If no zone has been parsed, then this override chronology will be used
     
* to interpret the {@code ChronoField} values into a date according to the
     
* date resolving rules of the chronology.
     
* <p>
     
* This instance is immutable and unaffected by this method call.
     
*
     
* @param chrono
  
the new chronology, null if no override
     
* @return a formatter based on this formatter with the requested override chronology, not null
     
*/

    
public DateTimeFormatter withChronology(Chronology chrono) {
        
if (Objects.equals(this.chrono, chrono)) {
            
return this;
        
}
        
return new DateTimeFormatter(printerParser, locale, decimalStyle, resolverStyle, resolverFields, chrono, zone);
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* Gets the overriding zone to be used during formatting.
     
* <p>
     
* This returns the override zone, used to convert instants.
     
* By default, a formatter has no override zone, returning null.
     
* See {@link #withZone(ZoneId)} for more details on overriding.
     
*
     
* @return the override zone of this formatter, null if no override
     
*/

    
public ZoneId getZone() {
        
return zone;
    
}

    
/**
     
* Returns a copy of this formatter with a new override zone.
     
* <p>
     
* This returns a formatter with similar state to this formatter but
     
* with the override zone set.
     
* By default, a formatter has no override zone, returning null.
     
* <p>
     
* If an override is added, then any instant that is formatted or parsed will be affected.
     
* <p>
     
* When formatting, if the temporal object contains an instant, then it will
     
* be converted to a zoned date-time using the override zone.
     
* Whether the temporal is an instant is determined by querying the
     
* {@link ChronoField#INSTANT_SECONDS INSTANT_SECONDS} field.
     
* If the input has a chronology then it will be retained unless overridden.
     
* If the input does not have a chronology, such as {@code Instant}, then
     
* the ISO chronology will be used.
     
* <p>
     
* If the temporal object does not contain an instant, but does contain
     
* an offset then an additional check is made. If the normalized override
     
* zone is an offset that differs from the offset of the temporal, then
     
* a {@code DateTimeException} is thrown. In all other cases, the override
     
* zone is added to the temporal, replacing any previous zone, but without
     
* changing the date/time.
     
* <p>
     
* When parsing, there are two distinct cases to consider.
     
* If a zone has been parsed directly from the text, perhaps because
     
* {@link DateTimeFormatterBuilder#appendZoneId()} was used, then
     
* this override zone has no effect.
     
* If no zone has been parsed, then this override zone will be included in
     
* the result of the parse where it can be used to build instants and date-times.
     
* <p>
     
* This instance is immutable and unaffected by this method call.
     
*
     
* @param zone
  
the new override zone, null if no override
     
* @return a formatter based on this formatter with the requested override zone, not null
     
*/

    
public DateTimeFormatter withZone(ZoneId zone) {
        
if (Objects.equals(this.zone, zone)) {
            
return this;
        
}
        
return new DateTimeFormatter(printerParser, locale, decimalStyle, resolverStyle, resolverFields, chrono, zone);
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* Gets the resolver style to use during parsing.
     
* <p>
     
* This returns the resolver style, used during the second phase of parsing
     
* when fields are resolved into dates and times.
     
* By default, a formatter has the {@link ResolverStyle#SMART SMART} resolver style.
     
* See {@link #withResolverStyle(ResolverStyle)} for more details.
     
*
     
* @return the resolver style of this formatter, not null
     
*/

    
public ResolverStyle getResolverStyle() {
        
return resolverStyle;
    
}

    
/**
     
* Returns a copy of this formatter with a new resolver style.
     
* <p>
     
* This returns a formatter with similar state to this formatter but
     
* with the resolver style set. By default, a formatter has the
     
* {@link ResolverStyle#SMART SMART} resolver style.
     
* <p>
     
* Changing the resolver style only has an effect during parsing.
     
* Parsing a text string occurs in two phases.
     
* Phase 1 is a basic text parse according to the fields added to the builder.
     
* Phase 2 resolves the parsed field-value pairs into date and/or time objects.
     
* The resolver style is used to control how phase 2, resolving, happens.
     
* See {@code ResolverStyle} for more information on the options available.
     
* <p>
     
* This instance is immutable and unaffected by this method call.
     
*
     
* @param resolverStyle
  
the new resolver style, not null
     
* @return a formatter based on this formatter with the requested resolver style, not null
     
*/

    
public DateTimeFormatter withResolverStyle(ResolverStyle resolverStyle) {
        
Objects.requireNonNull(resolverStyle, "resolverStyle");
        
if (Objects.equals(this.resolverStyle, resolverStyle)) {
            
return this;
        
}
        
return new DateTimeFormatter(printerParser, locale, decimalStyle, resolverStyle, resolverFields, chrono, zone);
    
}

    
//-----------------------------------------------------------------------
    
/**
     
* Gets the resolver fields to use during parsing.
     
* <p>
     
* This returns the resolver fields, used during the second phase of parsing
     
* when fields are resolved into dates and times.
     
* By default, a formatter has no resolver fields, and thus returns null.
     
* See {@link #withResolverFields(Set)} for more details.
     
*
     
* @return the immutable set of resolver fields of this formatter, null if no fields
     
*/

    
public Set<TemporalField> getResolverFields() {
        
return resolverFields;
    
}

    
/**
     
* Returns a copy of this formatter with a new set of resolver fields.
     
* <p>
     
* This returns a formatter with similar state to this formatter but with
     
* the resolver fields set. By default, a formatter has no resolver fields.
     
* <p>
     
* Changing the resolver fields only has an effect during parsing.
     
* Parsing a text string occurs in two phases.
     
* Phase 1 is a basic text parse according to the fields added to the builder.
     
* Phase 2 resolves the parsed field-value pairs into date and/or time objects.
     
* The resolver fields are used to filter the field-value pairs between phase 1 and 2.
     
* <p>
     
* This can be used to select between two or more ways that a date or time might
     
* be resolved. For example, if the formatter consists of year, month, day-of-month
     
* and day-of-year, then there are two ways to resolve a date.
     
* Calling this method with the arguments {@link ChronoField#YEAR YEAR} and
     
* {@link ChronoField#DAY_OF_YEAR DAY_OF_YEAR} will ensure that the date is
     
* resolved using the year and day-of-year, effectively meaning that the month
     
* and day-of-month are ignored during the resolving phase.
     
* <p>
     
* In a similar manner, this method can be used to ignore secondary fields that
     
* would otherwise be cross-checked. For example, if the formatter consists of year,
     
* month, day-of-month and day-of-week, then there is only one way to resolve a
     
* date, but the parsed value for day-of-week will be cross-checked against the
     
* resolved date. Calling this method with the arguments {@link ChronoField#YEAR YEAR},
     
* {@link ChronoField#MONTH_OF_YEAR MONTH_OF_YEAR} and
     
* {@link ChronoField#DAY_OF_MONTH DAY_OF_MONTH} will ensure that the date is
     
* resolved correctly, but without any cross-check for the day-of-week.
     
* <p>
     
* In implementation terms, this method behaves as follows. The result of the
     
* parsing phase can be considered to be a map of field to value. The behavior
     
* of this method is to cause that map to be filtered between phase 1 and 2,
     
* removing all fields other than those specified as arguments to this method.
     
* <p>
     
* This instance is immutable and unaffected by this method call.
     
*
     
* @param resolverFields
  
the new set of resolver fields, null if no fields
     
* @return a formatter based on this formatter with the requested resolver style, not null
     
*/

    
public DateTimeFormatter withResolverFields(TemporalField... resolverFields) {
        
Set<TemporalField> fields = null;
        
if (resolverFields != null) {
            
fields = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(resolverFields)));
        
}
        
if (Objects.equals(this.resolverFields, fields)) {
            
return this;
        
}
        
return new