Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    *  Copyright 2001-2011 Stephen Colebourne
    *
    *  Licensed under the Apache License, Version 2.0 (the "License");
    *  you may not use this file except in compliance with the License.
    *  You may obtain a copy of the License at
    *
    *      http://www.apache.org/licenses/LICENSE-2.0
    *
   *  Unless required by applicable law or agreed to in writing, software
   *  distributed under the License is distributed on an "AS IS" BASIS,
   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *  See the License for the specific language governing permissions and
   *  limitations under the License.
   */
  package org.joda.time.format;
  
  import java.io.Writer;
  import java.util.HashMap;
  import java.util.HashSet;
  import java.util.List;
  import java.util.Locale;
  import java.util.Map;
  import java.util.Set;
  
Factory that creates complex instances of DateTimeFormatter via method calls.

Datetime formatting is performed by the DateTimeFormatter class. Three classes provide factory methods to create formatters, and this is one. The others are DateTimeFormat and ISODateTimeFormat.

DateTimeFormatterBuilder is used for constructing formatters which are then used to print or parse. The formatters are built by appending specific fields or other formatters to an instance of this builder.

For example, a formatter that prints month and year, like "January 1970", can be constructed as follows:

 DateTimeFormatter monthAndYear = new DateTimeFormatterBuilder()
     .appendMonthOfYearText()
     .appendLiteral(' ')
     .appendYear(4, 4)
     .toFormatter();
 

DateTimeFormatterBuilder itself is mutable and not thread-safe, but the formatters that it builds are thread-safe and immutable.

Author(s):
Brian S O'Neill
Stephen Colebourne
Fredrik Borgh
Since:
1.0
See also:
DateTimeFormat
ISODateTimeFormat
  
  public class DateTimeFormatterBuilder {

    
Array of printers and parsers (alternating).
  
      private ArrayList<ObjectiElementPairs;
    
Cache of the last returned formatter.
  
      private Object iFormatter;
  
      //-----------------------------------------------------------------------
      
Creates a DateTimeFormatterBuilder.
  
      public DateTimeFormatterBuilder() {
          super();
           = new ArrayList<Object>();
      }
  
      //-----------------------------------------------------------------------
      
Constructs a DateTimeFormatter using all the appended elements.

This is the main method used by applications at the end of the build process to create a usable formatter.

Subsequent changes to this builder do not affect the returned formatter.

The returned formatter may not support both printing and parsing. The methods DateTimeFormatter.isPrinter() and DateTimeFormatter.isParser() will help you determine the state of the formatter.

Throws:
java.lang.UnsupportedOperationException if neither printing nor parsing is supported
 
     public DateTimeFormatter toFormatter() {
         Object f = getFormatter();
         DateTimePrinter printer = null;
         if (isPrinter(f)) {
             printer = (DateTimePrinterf;
         }
         DateTimeParser parser = null;
         if (isParser(f)) {
             parser = (DateTimeParserf;
         }
         if (printer != null || parser != null) {
             return new DateTimeFormatter(printerparser);
         }
         throw new UnsupportedOperationException("Both printing and parsing not supported");
     }

    
Internal method to create a DateTimePrinter instance using all the appended elements.

Most applications will not use this method. If you want a printer in an application, call toFormatter() and just use the printing API.

Subsequent changes to this builder do not affect the returned printer.

Throws:
java.lang.UnsupportedOperationException if printing is not supported
 
     public DateTimePrinter toPrinter() {
         Object f = getFormatter();
         if (isPrinter(f)) {
             return (DateTimePrinterf;
         }
         throw new UnsupportedOperationException("Printing is not supported");
     }

    
Internal method to create a DateTimeParser instance using all the appended elements.

Most applications will not use this method. If you want a parser in an application, call toFormatter() and just use the parsing API.

Subsequent changes to this builder do not affect the returned parser.

Throws:
java.lang.UnsupportedOperationException if parsing is not supported
 
     public DateTimeParser toParser() {
         Object f = getFormatter();
         if (isParser(f)) {
             return (DateTimeParserf;
         }
         throw new UnsupportedOperationException("Parsing is not supported");
     }
 
     //-----------------------------------------------------------------------
     
Returns true if toFormatter can be called without throwing an UnsupportedOperationException.

Returns:
true if a formatter can be built
 
     public boolean canBuildFormatter() {
         return isFormatter(getFormatter());
     }

    
Returns true if toPrinter can be called without throwing an UnsupportedOperationException.

Returns:
true if a printer can be built
 
     public boolean canBuildPrinter() {
         return isPrinter(getFormatter());
     }

    
Returns true if toParser can be called without throwing an UnsupportedOperationException.

Returns:
true if a parser can be built
 
     public boolean canBuildParser() {
         return isParser(getFormatter());
     }
 
     //-----------------------------------------------------------------------
     
Clears out all the appended elements, allowing this builder to be reused.
 
     public void clear() {
          = null;
         .clear();
     }
 
     //-----------------------------------------------------------------------
     
Appends another formatter.

This extracts the underlying printer and parser and appends them The printer and parser interfaces are the low-level part of the formatting API. Normally, instances are extracted from another formatter. Note however that any formatter specific information, such as the locale, time-zone, chronology, offset parsing or pivot/default year, will not be extracted by this method.

Parameters:
formatter the formatter to add
Returns:
this DateTimeFormatterBuilder, for chaining
Throws:
java.lang.IllegalArgumentException if formatter is null or of an invalid type
 
     public DateTimeFormatterBuilder append(DateTimeFormatter formatter) {
         if (formatter == null) {
             throw new IllegalArgumentException("No formatter supplied");
         }
         return append0(formatter.getPrinter(), formatter.getParser());
     }

    
Appends just a printer. With no matching parser, a parser cannot be built from this DateTimeFormatterBuilder.

The printer interface is part of the low-level part of the formatting API. Normally, instances are extracted from another formatter. Note however that any formatter specific information, such as the locale, time-zone, chronology, offset parsing or pivot/default year, will not be extracted by this method.

Parameters:
printer the printer to add, not null
Returns:
this DateTimeFormatterBuilder, for chaining
Throws:
java.lang.IllegalArgumentException if printer is null or of an invalid type
 
     public DateTimeFormatterBuilder append(DateTimePrinter printer) {
         checkPrinter(printer);
         return append0(printernull);
     }

    
Appends just a parser. With no matching printer, a printer cannot be built from this builder.

The parser interface is part of the low-level part of the formatting API. Normally, instances are extracted from another formatter. Note however that any formatter specific information, such as the locale, time-zone, chronology, offset parsing or pivot/default year, will not be extracted by this method.

Parameters:
parser the parser to add, not null
Returns:
this DateTimeFormatterBuilder, for chaining
Throws:
java.lang.IllegalArgumentException if parser is null or of an invalid type
 
     public DateTimeFormatterBuilder append(DateTimeParser parser) {
         checkParser(parser);
         return append0(nullparser);
     }

    
Appends a printer/parser pair.

The printer and parser interfaces are the low-level part of the formatting API. Normally, instances are extracted from another formatter. Note however that any formatter specific information, such as the locale, time-zone, chronology, offset parsing or pivot/default year, will not be extracted by this method.

Parameters:
printer the printer to add, not null
parser the parser to add, not null
Returns:
this DateTimeFormatterBuilder, for chaining
Throws:
java.lang.IllegalArgumentException if printer or parser is null or of an invalid type
 
     public DateTimeFormatterBuilder append(DateTimePrinter printerDateTimeParser parser) {
         checkPrinter(printer);
         checkParser(parser);
         return append0(printerparser);
     }

    
Appends a printer and a set of matching parsers. When parsing, the first parser in the list is selected for parsing. If it fails, the next is chosen, and so on. If none of these parsers succeeds, then the failed position of the parser that made the greatest progress is returned.

Only the printer is optional. In addition, it is illegal for any but the last of the parser array elements to be null. If the last element is null, this represents the empty parser. The presence of an empty parser indicates that the entire array of parse formats is optional.

The printer and parser interfaces are the low-level part of the formatting API. Normally, instances are extracted from another formatter. Note however that any formatter specific information, such as the locale, time-zone, chronology, offset parsing or pivot/default year, will not be extracted by this method.

Parameters:
printer the printer to add
parsers the parsers to add
Returns:
this DateTimeFormatterBuilder, for chaining
Throws:
java.lang.IllegalArgumentException if any printer or parser is of an invalid type
java.lang.IllegalArgumentException if any parser element but the last is null
 
     public DateTimeFormatterBuilder append(DateTimePrinter printerDateTimeParser[] parsers) {
         if (printer != null) {
             checkPrinter(printer);
         }
         if (parsers == null) {
             throw new IllegalArgumentException("No parsers supplied");
         }
         int length = parsers.length;
         if (length == 1) {
             if (parsers[0] == null) {
                 throw new IllegalArgumentException("No parser supplied");
             }
             return append0(printerparsers[0]);
         }
 
         DateTimeParser[] copyOfParsers = new DateTimeParser[length];
         int i;
         for (i = 0; i < length - 1; i++) {
             if ((copyOfParsers[i] = parsers[i]) == null) {
                 throw new IllegalArgumentException("Incomplete parser array");
             }
         }
         copyOfParsers[i] = parsers[i];
 
         return append0(printernew MatchingParser(copyOfParsers));
     }

    
Appends just a parser element which is optional. With no matching printer, a printer cannot be built from this DateTimeFormatterBuilder.

The parser interface is part of the low-level part of the formatting API. Normally, instances are extracted from another formatter. Note however that any formatter specific information, such as the locale, time-zone, chronology, offset parsing or pivot/default year, will not be extracted by this method.

Returns:
this DateTimeFormatterBuilder, for chaining
Throws:
java.lang.IllegalArgumentException if parser is null or of an invalid type
 
         checkParser(parser);
         DateTimeParser[] parsers = new DateTimeParser[] {parsernull};
         return append0(nullnew MatchingParser(parsers));
     }
 
     //-----------------------------------------------------------------------
     
Checks if the parser is non null and a provider.

Parameters:
parser the parser to check
 
     private void checkParser(DateTimeParser parser) {
         if (parser == null) {
             throw new IllegalArgumentException("No parser supplied");
         }
     }

    
Checks if the printer is non null and a provider.

Parameters:
printer the printer to check
 
     private void checkPrinter(DateTimePrinter printer) {
         if (printer == null) {
             throw new IllegalArgumentException("No printer supplied");
         }
     }
 
     private DateTimeFormatterBuilder append0(Object element) {
          = null;
         // Add the element as both a printer and parser.
         .add(element);
         .add(element);
         return this;
     }
 
             DateTimePrinter printerDateTimeParser parser) {
          = null;
         .add(printer);
         .add(parser);
         return this;
     }
 
     //-----------------------------------------------------------------------
     
Instructs the printer to emit a specific character, and the parser to expect it. The parser is case-insensitive.

Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendLiteral(char c) {
         return append0(new CharacterLiteral(c));
     }

    
Instructs the printer to emit specific text, and the parser to expect it. The parser is case-insensitive.

Returns:
this DateTimeFormatterBuilder, for chaining
Throws:
java.lang.IllegalArgumentException if text is null
 
     public DateTimeFormatterBuilder appendLiteral(String text) {
         if (text == null) {
             throw new IllegalArgumentException("Literal must not be null");
         }
         switch (text.length()) {
             case 0:
                 return this;
             case 1:
                 return append0(new CharacterLiteral(text.charAt(0)));
             default:
                 return append0(new StringLiteral(text));
         }
     }

    
Instructs the printer to emit a field value as a decimal number, and the parser to expect an unsigned decimal number.

Parameters:
fieldType type of field to append
minDigits minimum number of digits to print
maxDigits maximum number of digits to parse, or the estimated maximum number of digits to print
Returns:
this DateTimeFormatterBuilder, for chaining
Throws:
java.lang.IllegalArgumentException if field type is null
 
             DateTimeFieldType fieldTypeint minDigitsint maxDigits) {
         if (fieldType == null) {
             throw new IllegalArgumentException("Field type must not be null");
         }
         if (maxDigits < minDigits) {
             maxDigits = minDigits;
         }
         if (minDigits < 0 || maxDigits <= 0) {
             throw new IllegalArgumentException();
         }
         if (minDigits <= 1) {
             return append0(new UnpaddedNumber(fieldTypemaxDigitsfalse));
         } else {
             return append0(new PaddedNumber(fieldTypemaxDigitsfalseminDigits));
         }
     }

    
Instructs the printer to emit a field value as a fixed-width decimal number (smaller numbers will be left-padded with zeros), and the parser to expect an unsigned decimal number with the same fixed width.

Parameters:
fieldType type of field to append
numDigits the exact number of digits to parse or print, except if printed value requires more digits
Returns:
this DateTimeFormatterBuilder, for chaining
Throws:
java.lang.IllegalArgumentException if field type is null or if numDigits <= 0
Since:
1.5
 
             DateTimeFieldType fieldTypeint numDigits) {
         if (fieldType == null) {
             throw new IllegalArgumentException("Field type must not be null");
         }
         if (numDigits <= 0) {
             throw new IllegalArgumentException("Illegal number of digits: " + numDigits);
         }
         return append0(new FixedNumber(fieldTypenumDigitsfalse));
     }

    
Instructs the printer to emit a field value as a decimal number, and the parser to expect a signed decimal number.

Parameters:
fieldType type of field to append
minDigits minimum number of digits to print
maxDigits maximum number of digits to parse, or the estimated maximum number of digits to print
Returns:
this DateTimeFormatterBuilder, for chaining
Throws:
java.lang.IllegalArgumentException if field type is null
 
             DateTimeFieldType fieldTypeint minDigitsint maxDigits) {
         if (fieldType == null) {
             throw new IllegalArgumentException("Field type must not be null");
         }
         if (maxDigits < minDigits) {
             maxDigits = minDigits;
         }
         if (minDigits < 0 || maxDigits <= 0) {
             throw new IllegalArgumentException();
         }
         if (minDigits <= 1) {
             return append0(new UnpaddedNumber(fieldTypemaxDigitstrue));
         } else {
             return append0(new PaddedNumber(fieldTypemaxDigitstrueminDigits));
         }
     }

    
Instructs the printer to emit a field value as a fixed-width decimal number (smaller numbers will be left-padded with zeros), and the parser to expect an signed decimal number with the same fixed width.

Parameters:
fieldType type of field to append
numDigits the exact number of digits to parse or print, except if printed value requires more digits
Returns:
this DateTimeFormatterBuilder, for chaining
Throws:
java.lang.IllegalArgumentException if field type is null or if numDigits <= 0
Since:
1.5
 
             DateTimeFieldType fieldTypeint numDigits) {
         if (fieldType == null) {
             throw new IllegalArgumentException("Field type must not be null");
         }
         if (numDigits <= 0) {
             throw new IllegalArgumentException("Illegal number of digits: " + numDigits);
         }
         return append0(new FixedNumber(fieldTypenumDigitstrue));
     }

    
Instructs the printer to emit a field value as text, and the parser to expect text.

Parameters:
fieldType type of field to append
Returns:
this DateTimeFormatterBuilder, for chaining
Throws:
java.lang.IllegalArgumentException if field type is null
 
     public DateTimeFormatterBuilder appendText(DateTimeFieldType fieldType) {
         if (fieldType == null) {
             throw new IllegalArgumentException("Field type must not be null");
         }
         return append0(new TextField(fieldTypefalse));
     }

    
Instructs the printer to emit a field value as short text, and the parser to expect text.

Parameters:
fieldType type of field to append
Returns:
this DateTimeFormatterBuilder, for chaining
Throws:
java.lang.IllegalArgumentException if field type is null
 
         if (fieldType == null) {
             throw new IllegalArgumentException("Field type must not be null");
         }
         return append0(new TextField(fieldTypetrue));
     }

    
Instructs the printer to emit a remainder of time as a decimal fraction, without decimal point. For example, if the field is specified as minuteOfHour and the time is 12:30:45, the value printed is 75. A decimal point is implied, so the fraction is 0.75, or three-quarters of a minute.

Parameters:
fieldType type of field to append
minDigits minimum number of digits to print.
maxDigits maximum number of digits to print or parse.
Returns:
this DateTimeFormatterBuilder, for chaining
Throws:
java.lang.IllegalArgumentException if field type is null
 
             DateTimeFieldType fieldTypeint minDigitsint maxDigits) {
         if (fieldType == null) {
             throw new IllegalArgumentException("Field type must not be null");
         }
         if (maxDigits < minDigits) {
             maxDigits = minDigits;
         }
         if (minDigits < 0 || maxDigits <= 0) {
             throw new IllegalArgumentException();
         }
         return append0(new Fraction(fieldTypeminDigitsmaxDigits));
     }

    
Appends the print/parse of a fractional second.

This reliably handles the case where fractional digits are being handled beyond a visible decimal point. The digits parsed will always be treated as the most significant (numerically largest) digits. Thus '23' will be parsed as 230 milliseconds. Contrast this behaviour to appendMillisOfSecond(int). This method does not print or parse the decimal point itself.

Parameters:
minDigits minimum number of digits to print
maxDigits maximum number of digits to print or parse
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendFractionOfSecond(int minDigitsint maxDigits) {
         return appendFraction(DateTimeFieldType.secondOfDay(), minDigitsmaxDigits);
     }

    
Appends the print/parse of a fractional minute.

This reliably handles the case where fractional digits are being handled beyond a visible decimal point. The digits parsed will always be treated as the most significant (numerically largest) digits. Thus '23' will be parsed as 0.23 minutes (converted to milliseconds). This method does not print or parse the decimal point itself.

Parameters:
minDigits minimum number of digits to print
maxDigits maximum number of digits to print or parse
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendFractionOfMinute(int minDigitsint maxDigits) {
         return appendFraction(DateTimeFieldType.minuteOfDay(), minDigitsmaxDigits);
     }

    
Appends the print/parse of a fractional hour.

This reliably handles the case where fractional digits are being handled beyond a visible decimal point. The digits parsed will always be treated as the most significant (numerically largest) digits. Thus '23' will be parsed as 0.23 hours (converted to milliseconds). This method does not print or parse the decimal point itself.

Parameters:
minDigits minimum number of digits to print
maxDigits maximum number of digits to print or parse
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendFractionOfHour(int minDigitsint maxDigits) {
         return appendFraction(DateTimeFieldType.hourOfDay(), minDigitsmaxDigits);
     }

    
Appends the print/parse of a fractional day.

This reliably handles the case where fractional digits are being handled beyond a visible decimal point. The digits parsed will always be treated as the most significant (numerically largest) digits. Thus '23' will be parsed as 0.23 days (converted to milliseconds). This method does not print or parse the decimal point itself.

Parameters:
minDigits minimum number of digits to print
maxDigits maximum number of digits to print or parse
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendFractionOfDay(int minDigitsint maxDigits) {
         return appendFraction(DateTimeFieldType.dayOfYear(), minDigitsmaxDigits);
     }

    
Instructs the printer to emit a numeric millisOfSecond field.

This method will append a field that prints a three digit value. During parsing the value that is parsed is assumed to be three digits. If less than three digits are present then they will be counted as the smallest parts of the millisecond. This is probably not what you want if you are using the field as a fraction. Instead, a fractional millisecond should be produced using appendFractionOfSecond(int,int).

Parameters:
minDigits minimum number of digits to print
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendMillisOfSecond(int minDigits) {
         return appendDecimal(DateTimeFieldType.millisOfSecond(), minDigits, 3);
     }

    
Instructs the printer to emit a numeric millisOfDay field.

Parameters:
minDigits minimum number of digits to print
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendMillisOfDay(int minDigits) {
         return appendDecimal(DateTimeFieldType.millisOfDay(), minDigits, 8);
     }

    
Instructs the printer to emit a numeric secondOfMinute field.

Parameters:
minDigits minimum number of digits to print
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendSecondOfMinute(int minDigits) {
         return appendDecimal(DateTimeFieldType.secondOfMinute(), minDigits, 2);
     }

    
Instructs the printer to emit a numeric secondOfDay field.

Parameters:
minDigits minimum number of digits to print
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendSecondOfDay(int minDigits) {
         return appendDecimal(DateTimeFieldType.secondOfDay(), minDigits, 5);
     }

    
Instructs the printer to emit a numeric minuteOfHour field.

Parameters:
minDigits minimum number of digits to print
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendMinuteOfHour(int minDigits) {
         return appendDecimal(DateTimeFieldType.minuteOfHour(), minDigits, 2);
     }

    
Instructs the printer to emit a numeric minuteOfDay field.

Parameters:
minDigits minimum number of digits to print
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendMinuteOfDay(int minDigits) {
         return appendDecimal(DateTimeFieldType.minuteOfDay(), minDigits, 4);
     }

    
Instructs the printer to emit a numeric hourOfDay field.

Parameters:
minDigits minimum number of digits to print
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendHourOfDay(int minDigits) {
         return appendDecimal(DateTimeFieldType.hourOfDay(), minDigits, 2);
     }

    
Instructs the printer to emit a numeric clockhourOfDay field.

Parameters:
minDigits minimum number of digits to print
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendClockhourOfDay(int minDigits) {
         return appendDecimal(DateTimeFieldType.clockhourOfDay(), minDigits, 2);
     }

    
Instructs the printer to emit a numeric hourOfHalfday field.

Parameters:
minDigits minimum number of digits to print
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendHourOfHalfday(int minDigits) {
         return appendDecimal(DateTimeFieldType.hourOfHalfday(), minDigits, 2);
     }

    
Instructs the printer to emit a numeric clockhourOfHalfday field.

Parameters:
minDigits minimum number of digits to print
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendClockhourOfHalfday(int minDigits) {
         return appendDecimal(DateTimeFieldType.clockhourOfHalfday(), minDigits, 2);
     }

    
Instructs the printer to emit a numeric dayOfWeek field.

Parameters:
minDigits minimum number of digits to print
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendDayOfWeek(int minDigits) {
         return appendDecimal(DateTimeFieldType.dayOfWeek(), minDigits, 1);
     }

    
Instructs the printer to emit a numeric dayOfMonth field.

Parameters:
minDigits minimum number of digits to print
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendDayOfMonth(int minDigits) {
         return appendDecimal(DateTimeFieldType.dayOfMonth(), minDigits, 2);
     }

    
Instructs the printer to emit a numeric dayOfYear field.

Parameters:
minDigits minimum number of digits to print
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendDayOfYear(int minDigits) {
         return appendDecimal(DateTimeFieldType.dayOfYear(), minDigits, 3);
     }

    
Instructs the printer to emit a numeric weekOfWeekyear field.

Parameters:
minDigits minimum number of digits to print
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendWeekOfWeekyear(int minDigits) {
         return appendDecimal(DateTimeFieldType.weekOfWeekyear(), minDigits, 2);
     }

    
Instructs the printer to emit a numeric weekyear field.

Parameters:
minDigits minimum number of digits to print
maxDigits maximum number of digits to parse, or the estimated maximum number of digits to print
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendWeekyear(int minDigitsint maxDigits) {
         return appendSignedDecimal(DateTimeFieldType.weekyear(), minDigitsmaxDigits);
     }

    
Instructs the printer to emit a numeric monthOfYear field.

Parameters:
minDigits minimum number of digits to print
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendMonthOfYear(int minDigits) {
         return appendDecimal(DateTimeFieldType.monthOfYear(), minDigits, 2);
     }

    
Instructs the printer to emit a numeric year field.

Parameters:
minDigits minimum number of digits to print
maxDigits maximum number of digits to parse, or the estimated maximum number of digits to print
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendYear(int minDigitsint maxDigits) {
         return appendSignedDecimal(DateTimeFieldType.year(), minDigitsmaxDigits);
     }

    
Instructs the printer to emit a numeric year field which always prints and parses two digits. A pivot year is used during parsing to determine the range of supported years as (pivot - 50) .. (pivot + 49).
 pivot   supported range   00 is   20 is   40 is   60 is   80 is
 ---------------------------------------------------------------
 1950      1900..1999      1900    1920    1940    1960    1980
 1975      1925..2024      2000    2020    1940    1960    1980
 2000      1950..2049      2000    2020    2040    1960    1980
 2025      1975..2074      2000    2020    2040    2060    1980
 2050      2000..2099      2000    2020    2040    2060    2080
 

Parameters:
pivot pivot year to use when parsing
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendTwoDigitYear(int pivot) {
         return appendTwoDigitYear(pivotfalse);
     }

    
Instructs the printer to emit a numeric year field which always prints two digits. A pivot year is used during parsing to determine the range of supported years as (pivot - 50) .. (pivot + 49). If parse is instructed to be lenient and the digit count is not two, it is treated as an absolute year. With lenient parsing, specifying a positive or negative sign before the year also makes it absolute.

Parameters:
pivot pivot year to use when parsing
lenientParse when true, if digit count is not two, it is treated as an absolute year
Returns:
this DateTimeFormatterBuilder, for chaining
Since:
1.1
 
     public DateTimeFormatterBuilder appendTwoDigitYear(int pivotboolean lenientParse) {
         return append0(new TwoDigitYear(DateTimeFieldType.year(), pivotlenientParse));
     }

    
Instructs the printer to emit a numeric weekyear field which always prints and parses two digits. A pivot year is used during parsing to determine the range of supported years as (pivot - 50) .. (pivot + 49).
 pivot   supported range   00 is   20 is   40 is   60 is   80 is
 ---------------------------------------------------------------
 1950      1900..1999      1900    1920    1940    1960    1980
 1975      1925..2024      2000    2020    1940    1960    1980
 2000      1950..2049      2000    2020    2040    1960    1980
 2025      1975..2074      2000    2020    2040    2060    1980
 2050      2000..2099      2000    2020    2040    2060    2080
 

Parameters:
pivot pivot weekyear to use when parsing
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendTwoDigitWeekyear(int pivot) {
         return appendTwoDigitWeekyear(pivotfalse);
     }

    
Instructs the printer to emit a numeric weekyear field which always prints two digits. A pivot year is used during parsing to determine the range of supported years as (pivot - 50) .. (pivot + 49). If parse is instructed to be lenient and the digit count is not two, it is treated as an absolute weekyear. With lenient parsing, specifying a positive or negative sign before the weekyear also makes it absolute.

Parameters:
pivot pivot weekyear to use when parsing
lenientParse when true, if digit count is not two, it is treated as an absolute weekyear
Returns:
this DateTimeFormatterBuilder, for chaining
Since:
1.1
 
     public DateTimeFormatterBuilder appendTwoDigitWeekyear(int pivotboolean lenientParse) {
         return append0(new TwoDigitYear(DateTimeFieldType.weekyear(), pivotlenientParse));
     }

    
Instructs the printer to emit a numeric yearOfEra field.

Parameters:
minDigits minimum number of digits to print
maxDigits maximum number of digits to parse, or the estimated maximum number of digits to print
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendYearOfEra(int minDigitsint maxDigits) {
         return appendDecimal(DateTimeFieldType.yearOfEra(), minDigitsmaxDigits);
     }

    
Instructs the printer to emit a numeric year of century field.

Parameters:
minDigits minimum number of digits to print
maxDigits maximum number of digits to parse, or the estimated maximum number of digits to print
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendYearOfCentury(int minDigitsint maxDigits) {
         return appendDecimal(DateTimeFieldType.yearOfCentury(), minDigitsmaxDigits);
     }

    
Instructs the printer to emit a numeric century of era field.

Parameters:
minDigits minimum number of digits to print
maxDigits maximum number of digits to parse, or the estimated maximum number of digits to print
Returns:
this DateTimeFormatterBuilder, for chaining
 
     public DateTimeFormatterBuilder appendCenturyOfEra(int minDigitsint maxDigits) {
         return appendSignedDecimal(DateTimeFieldType.centuryOfEra(), minDigitsmaxDigits);
     }

    
Instructs the printer to emit a locale-specific AM/PM text, and the parser to expect it. The parser is case-insensitive.

Returns:
this DateTimeFormatterBuilder, for chaining
 
         return appendText(DateTimeFieldType.halfdayOfDay());
     }

    
Instructs the printer to emit a locale-specific dayOfWeek text. The parser will accept a long or short dayOfWeek text, case-insensitive.

Returns:
this DateTimeFormatterBuilder, for chaining
 
         return appendText(DateTimeFieldType.dayOfWeek());
     }

    
Instructs the printer to emit a short locale-specific dayOfWeek text. The parser will accept a long or short dayOfWeek text, case-insensitive.

Returns:
this DateTimeFormatterBuilder, for chaining
 
         return appendShortText(DateTimeFieldType.dayOfWeek());
     }

    
Instructs the printer to emit a short locale-specific monthOfYear text. The parser will accept a long or short monthOfYear text, case-insensitive.

Returns:
this DateTimeFormatterBuilder, for chaining
 
         return appendText(DateTimeFieldType.monthOfYear());
     }

    
Instructs the printer to emit a locale-specific monthOfYear text. The parser will accept a long or short monthOfYear text, case-insensitive.

Returns:
this DateTimeFormatterBuilder, for chaining
 
         return appendShortText(DateTimeFieldType.monthOfYear());
     }

    
Instructs the printer to emit a locale-specific era text (BC/AD), and the parser to expect it. The parser is case-insensitive.

Returns:
this DateTimeFormatterBuilder, for chaining
        return appendText(DateTimeFieldType.era());
    }

    
Instructs the printer to emit a locale-specific time zone name. Using this method prevents parsing, because time zone names are not unique. See appendTimeZoneName(java.util.Map).

Returns:
this DateTimeFormatterBuilder, for chaining
        return append0(new TimeZoneName(.null), null);
    }

    
Instructs the printer to emit a locale-specific time zone name, providing a lookup for parsing. Time zone names are not unique, thus the API forces you to supply the lookup. The names are searched in the order of the map, thus it is strongly recommended to use a LinkedHashMap or similar.

Parameters:
parseLookup the table of names, not null
Returns:
this DateTimeFormatterBuilder, for chaining
        TimeZoneName pp = new TimeZoneName(.parseLookup);
        return append0(pppp);
    }

    
Instructs the printer to emit a short locale-specific time zone name. Using this method prevents parsing, because time zone names are not unique. See appendTimeZoneShortName(java.util.Map).

Returns:
this DateTimeFormatterBuilder, for chaining
        return append0(new TimeZoneName(.null), null);
    }

    
Instructs the printer to emit a short locale-specific time zone name, providing a lookup for parsing. Time zone names are not unique, thus the API forces you to supply the lookup. The names are searched in the order of the map, thus it is strongly recommended to use a LinkedHashMap or similar.

Parameters:
parseLookup the table of names, null to use the default names
Returns:
this DateTimeFormatterBuilder, for chaining
        TimeZoneName pp = new TimeZoneName(.parseLookup);
        return append0(pppp);
    }

    
Instructs the printer to emit the identifier of the time zone. From version 2.0, this field can be parsed.

Returns:
this DateTimeFormatterBuilder, for chaining
        return append0(..);
    }

    
Instructs the printer to emit text and numbers to display time zone offset from UTC. A parser will use the parsed time zone offset to adjust the datetime.

If zero offset text is supplied, then it will be printed when the zone is zero. During parsing, either the zero offset text, or the offset will be parsed.

Parameters:
zeroOffsetText the text to use if time zone offset is zero. If null, offset is always shown.
showSeparators if true, prints ':' separator before minute and second field and prints '.' separator before fraction field.
minFields minimum number of fields to print, stopping when no more precision is required. 1=hours, 2=minutes, 3=seconds, 4=fraction
maxFields maximum number of fields to print
Returns:
this DateTimeFormatterBuilder, for chaining
            String zeroOffsetTextboolean showSeparators,
            int minFieldsint maxFields) {
        return append0(new TimeZoneOffset
                       (zeroOffsetTextzeroOffsetTextshowSeparatorsminFieldsmaxFields));
    }

    
Instructs the printer to emit text and numbers to display time zone offset from UTC. A parser will use the parsed time zone offset to adjust the datetime.

If zero offset print text is supplied, then it will be printed when the zone is zero. If zero offset parse text is supplied, then either it or the offset will be parsed.

Parameters:
zeroOffsetPrintText the text to print if time zone offset is zero. If null, offset is always shown.
zeroOffsetParseText the text to optionally parse to indicate that the time zone offset is zero. If null, then always use the offset.
showSeparators if true, prints ':' separator before minute and second field and prints '.' separator before fraction field.
minFields minimum number of fields to print, stopping when no more precision is required. 1=hours, 2=minutes, 3=seconds, 4=fraction
maxFields maximum number of fields to print
Returns:
this DateTimeFormatterBuilder, for chaining
Since:
2.0
            String zeroOffsetPrintTextString zeroOffsetParseTextboolean showSeparators,
            int minFieldsint maxFields) {
        return append0(new TimeZoneOffset
                       (zeroOffsetPrintTextzeroOffsetParseTextshowSeparatorsminFieldsmaxFields));
    }
    //-----------------------------------------------------------------------
    
Calls upon DateTimeFormat to parse the pattern and append the results into this builder.

Parameters:
pattern pattern specification
Throws:
java.lang.IllegalArgumentException if the pattern is invalid
See also:
DateTimeFormat
    public DateTimeFormatterBuilder appendPattern(String pattern) {
        DateTimeFormat.appendPatternTo(thispattern);
        return this;
    }
    //-----------------------------------------------------------------------
    private Object getFormatter() {
        Object f = ;
        if (f == null) {
            if (.size() == 2) {
                Object printer = .get(0);
                Object parser = .get(1);
                if (printer != null) {
                    if (printer == parser || parser == null) {
                        f = printer;
                    }
                } else {
                    f = parser;
                }
            }
            if (f == null) {
                f = new Composite();
            }
             = f;
        }
        return f;
    }
    private boolean isPrinter(Object f) {
        if (f instanceof DateTimePrinter) {
            if (f instanceof Composite) {
                return ((Composite)f).isPrinter();
            }
            return true;
        }
        return false;
    }
    private boolean isParser(Object f) {
        if (f instanceof DateTimeParser) {
            if (f instanceof Composite) {
                return ((Composite)f).isParser();
            }
            return true;
        }
        return false;
    }
    private boolean isFormatter(Object f) {
        return (isPrinter(f) || isParser(f));
    }
    static void appendUnknownString(StringBuffer bufint len) {
        for (int i = len; --i >= 0;) {
            buf.append('\ufffd');
        }
    }
    static void printUnknownString(Writer outint lenthrows IOException {
        for (int i = len; --i >= 0;) {
            out.write('\ufffd');
        }
    }
    //-----------------------------------------------------------------------
    static class CharacterLiteral
            implements DateTimePrinterDateTimeParser {
        private final char iValue;
        CharacterLiteral(char value) {
            super();
             = value;
        }
        public int estimatePrintedLength() {
            return 1;
        }
        public void printTo(
                StringBuffer buflong instantChronology chrono,
                int displayOffsetDateTimeZone displayZoneLocale locale) {
            buf.append();
        }
        public void printTo(
                Writer outlong instantChronology chrono,
                int displayOffsetDateTimeZone displayZoneLocale localethrows IOException {
            out.write();
        }
        public void printTo(StringBuffer bufReadablePartial partialLocale locale) {
            buf.append();
        }
        public void printTo(Writer outReadablePartial partialLocale localethrows IOException {
            out.write();
        }
        public int estimateParsedLength() {
            return 1;
        }
        public int parseInto(DateTimeParserBucket bucketString textint position) {
            if (position >= text.length()) {
                return ~position;
            }
            char a = text.charAt(position);
            char b = ;
            if (a != b) {
                a = Character.toUpperCase(a);
                b = Character.toUpperCase(b);
                if (a != b) {
                    a = Character.toLowerCase(a);
                    b = Character.toLowerCase(b);
                    if (a != b) {
                        return ~position;
                    }
                }
            }
            return position + 1;
        }
    }
    //-----------------------------------------------------------------------
    static class StringLiteral
            implements DateTimePrinterDateTimeParser {
        private final String iValue;
        StringLiteral(String value) {
            super();
             = value;
        }
        public int estimatePrintedLength() {
            return .length();
        }
        public void printTo(
                StringBuffer buflong instantChronology chrono,
                int displayOffsetDateTimeZone displayZoneLocale locale) {
            buf.append();
        }
        public void printTo(
                Writer outlong instantChronology chrono,
                int displayOffsetDateTimeZone displayZoneLocale localethrows IOException {
            out.write();
        }
        public void printTo(StringBuffer bufReadablePartial partialLocale locale) {
            buf.append();
        }
        public void printTo(Writer outReadablePartial partialLocale localethrows IOException {
            out.write();
        }
        public int estimateParsedLength() {
            return .length();
        }
        public int parseInto(DateTimeParserBucket bucketString textint position) {
            if (text.regionMatches(trueposition, 0, .length())) {
                return position + .length();
            }
            return ~position;
        }
    }
    //-----------------------------------------------------------------------
    static abstract class NumberFormatter
            implements DateTimePrinterDateTimeParser {
        protected final DateTimeFieldType iFieldType;
        protected final int iMaxParsedDigits;
        protected final boolean iSigned;
        NumberFormatter(DateTimeFieldType fieldType,
                int maxParsedDigitsboolean signed) {
            super();
             = fieldType;
             = maxParsedDigits;
             = signed;
        }
        public int estimateParsedLength() {
            return ;
        }
        public int parseInto(DateTimeParserBucket bucketString textint position) {
            int limit = Math.min(text.length() - position);
            boolean negative = false;
            int length = 0;
            while (length < limit) {
                char c = text.charAt(position + length);
                if (length == 0 && (c == '-' || c == '+') && ) {
                    negative = c == '-';
                    // Next character must be a digit.
                    if (length + 1 >= limit || 
                        (c = text.charAt(position + length + 1)) < '0' || c > '9')
                    {
                        break;
                    }
                    if (negative) {
                        length++;
                    } else {
                        // Skip the '+' for parseInt to succeed.
                        position++;
                    }
                    // Expand the limit to disregard the sign character.
                    limit = Math.min(limit + 1, text.length() - position);
                    continue;
                }
                if (c < '0' || c > '9') {
                    break;
                }
                length++;
            }
            if (length == 0) {
                return ~position;
            }
            int value;
            if (length >= 9) {
                // Since value may exceed integer limits, use stock parser
                // which checks for this.
                value = Integer.parseInt(text.substring(positionposition += length));
            } else {
                int i = position;
                if (negative) {
                    i++;
                }
                try {
                    value = text.charAt(i++) - '0';
                } catch (StringIndexOutOfBoundsException e) {
                    return ~position;
                }
                position += length;
                while (i < position) {
                    value = ((value << 3) + (value << 1)) + text.charAt(i++) - '0';
                }
                if (negative) {
                    value = -value;
                }
            }
            bucket.saveField(value);
            return position;
        }
    }
    //-----------------------------------------------------------------------
    static class UnpaddedNumber extends NumberFormatter {
        protected UnpaddedNumber(DateTimeFieldType fieldType,
                       int maxParsedDigitsboolean signed)
        {
            super(fieldTypemaxParsedDigitssigned);
        }
        public int estimatePrintedLength() {
            return ;
        }
        public void printTo(
                StringBuffer buflong instantChronology chrono,
                int displayOffsetDateTimeZone displayZoneLocale locale) {
            try {
                DateTimeField field = .getField(chrono);
                FormatUtils.appendUnpaddedInteger(buffield.get(instant));
            } catch (RuntimeException e) {
                buf.append('\ufffd');
            }
        }
        public void printTo(
                Writer outlong instantChronology chrono,
                int displayOffsetDateTimeZone displayZoneLocale localethrows IOException {
            try {
                DateTimeField field = .getField(chrono);
                FormatUtils.writeUnpaddedInteger(outfield.get(instant));
            } catch (RuntimeException e) {
                out.write('\ufffd');
            }
        }
        public void printTo(StringBuffer bufReadablePartial partialLocale locale) {
            if (partial.isSupported()) {
                try {
                    FormatUtils.appendUnpaddedInteger(bufpartial.get());
                } catch (RuntimeException e) {
                    buf.append('\ufffd');
                }
            } else {
                buf.append('\ufffd');
            }
        }
        public void printTo(Writer outReadablePartial partialLocale localethrows IOException {
            if (partial.isSupported()) {
                try {
                    FormatUtils.writeUnpaddedInteger(outpartial.get());
                } catch (RuntimeException e) {
                    out.write('\ufffd');
                }
            } else {
                out.write('\ufffd');
            }
        }
    }
    //-----------------------------------------------------------------------
    static class PaddedNumber extends NumberFormatter {
        protected final int iMinPrintedDigits;
        protected PaddedNumber(DateTimeFieldType fieldTypeint maxParsedDigits,
                     boolean signedint minPrintedDigits)
        {
            super(fieldTypemaxParsedDigitssigned);
             = minPrintedDigits;
        }
        public int estimatePrintedLength() {
            return ;
        }
        public void printTo(
                StringBuffer buflong instantChronology chrono,
                int displayOffsetDateTimeZone displayZoneLocale locale) {
            try {
                DateTimeField field = .getField(chrono);
                FormatUtils.appendPaddedInteger(buffield.get(instant), );
            } catch (RuntimeException e) {
                appendUnknownString(buf);
            }
        }
        public void printTo(
                Writer outlong instantChronology chrono,
                int displayOffsetDateTimeZone displayZoneLocale localethrows IOException {
            try {
                DateTimeField field = .getField(chrono);
                FormatUtils.writePaddedInteger(outfield.get(instant), );
            } catch (RuntimeException e) {
                printUnknownString(out);
            }
        }
        public void printTo(StringBuffer bufReadablePartial partialLocale locale) {
            if (partial.isSupported()) {
                try {
                    FormatUtils.appendPaddedInteger(bufpartial.get(), );
                } catch (RuntimeException e) {
                    appendUnknownString(buf);
                }
            } else {
                appendUnknownString(buf);
            }
        }
        public void printTo(Writer outReadablePartial partialLocale localethrows IOException {
            if (partial.isSupported()) {
                try {
                    FormatUtils.writePaddedInteger(outpartial.get(), );
                } catch (RuntimeException e) {
                    printUnknownString(out);
                }
            } else {
                printUnknownString(out);
            }
        }
    }
    //-----------------------------------------------------------------------
    static class FixedNumber extends PaddedNumber {
        protected FixedNumber(DateTimeFieldType fieldTypeint numDigitsboolean signed) {
            super(fieldTypenumDigitssignednumDigits);
        }
        public int parseInto(DateTimeParserBucket bucketString textint position) {
            int newPos = super.parseInto(buckettextposition);
            if (newPos < 0) {
                return newPos;
            }
            int expectedPos = position + ;
            if (newPos != expectedPos) {
                if () {
                    char c = text.charAt(position);
                    if (c == '-' || c == '+') {
                        expectedPos++;
                    }
                }
                if (newPos > expectedPos) {
                    // The failure is at the position of the first extra digit.
                    return ~(expectedPos + 1);
                } else if (newPos < expectedPos) {
                    // The failure is at the position where the next digit should be.
                    return ~newPos;
                }
            }
            return newPos;
        }
    }
    //-----------------------------------------------------------------------
    static class TwoDigitYear
            implements DateTimePrinterDateTimeParser {

        
The field to print/parse.
        private final DateTimeFieldType iType;
        
The pivot year.
        private final int iPivot;
        private final boolean iLenientParse;
        TwoDigitYear(DateTimeFieldType typeint pivotboolean lenientParse) {
            super();
             = type;
             = pivot;
             = lenientParse;
        }
        public int estimateParsedLength() {
            return  ? 4 : 2;
        }
        public int parseInto(DateTimeParserBucket bucketString textint position) {
            int limit = text.length() - position;
            if (!) {
                limit = Math.min(2, limit);
                if (limit < 2) {
                    return ~position;
                }
            } else {
                boolean hasSignChar = false;
                boolean negative = false;
                int length = 0;
                while (length < limit) {
                    char c = text.charAt(position + length);
                    if (length == 0 && (c == '-' || c == '+')) {
                        hasSignChar = true;
                        negative = c == '-';
                        if (negative) {
                            length++;
                        } else {
                            // Skip the '+' for parseInt to succeed.
                            position++;
                            limit--;
                        }
                        continue;
                    }
                    if (c < '0' || c > '9') {
                        break;
                    }
                    length++;
                }
                
                if (length == 0) {
                    return ~position;
                }
                if (hasSignChar || length != 2) {
                    int value;
                    if (length >= 9) {
                        // Since value may exceed integer limits, use stock
                        // parser which checks for this.
                        value = Integer.parseInt(text.substring(positionposition += length));
                    } else {
                        int i = position;
                        if (negative) {
                            i++;
                        }
                        try {
                            value = text.charAt(i++) - '0';