Home | History | Annotate | Download | only in text
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *     http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 package java.text;
     19 
     20 import java.io.InvalidObjectException;
     21 import java.util.Calendar;
     22 import java.util.Date;
     23 import java.util.Hashtable;
     24 import java.util.Locale;
     25 import java.util.TimeZone;
     26 import libcore.icu.ICU;
     27 import libcore.icu.LocaleData;
     28 
     29 /**
     30  * An abstract class for date/time formatting subclasses which formats and
     31  * parses dates or time in a language-independent manner. The date/time
     32  * formatting subclass, such as {@link SimpleDateFormat}, allows for formatting
     33  * (i.e., date -> text), parsing (text -> date), and normalization. The date is
     34  * represented as a {@code Date} object or as the milliseconds since January 1,
     35  * 1970, 00:00:00 GMT.
     36  * <p>
     37  * DateFormat provides many class methods for obtaining default date/time
     38  * formatters based on the default or a given locale and a number of formatting
     39  * styles. The formatting styles include FULL, LONG, MEDIUM, and SHORT. More
     40  * details and examples for using these styles are provided in the method
     41  * descriptions.
     42  * <p>
     43  * {@code DateFormat} helps you to format and parse dates for any locale. Your
     44  * code can be completely independent of the locale conventions for months, days
     45  * of the week, or even the calendar format: lunar vs. solar.
     46  * <p>
     47  * To format a date for the current Locale, use one of the static factory
     48  * methods:
     49  * <blockquote>
     50  *
     51  * <pre>
     52  * myString = DateFormat.getDateInstance().format(myDate);
     53  * </pre>
     54  *
     55  * </blockquote>
     56  * <p>
     57  * If you are formatting multiple dates, it is more efficient to get the format
     58  * and use it multiple times so that the system doesn't have to fetch the
     59  * information about the local language and country conventions multiple times.
     60  * <blockquote>
     61  *
     62  * <pre>
     63  * DateFormat df = DateFormat.getDateInstance();
     64  * for (int i = 0; i &lt; a.length; ++i) {
     65  *     output.println(df.format(myDate[i]) + &quot;; &quot;);
     66  * }
     67  * </pre>
     68  *
     69  * </blockquote>
     70  * <p>
     71  * To format a number for a different locale, specify it in the call to
     72  * {@code getDateInstance}:
     73  * <blockquote>
     74  *
     75  * <pre>
     76  * DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, Locale.FRANCE);
     77  * </pre>
     78  *
     79  * </blockquote>
     80  * <p>
     81  * {@code DateFormat} can also be used to parse strings:
     82  * <blockquote>
     83  *
     84  * <pre>
     85  * myDate = df.parse(myString);
     86  * </pre>
     87  *
     88  * </blockquote>
     89  * <p>
     90  * Use {@code getDateInstance} to get the normal date format for a country.
     91  * Other static factory methods are available: Use {@code getTimeInstance} to
     92  * get the time format for a country. Use {@code getDateTimeInstance} to get the
     93  * date and time format. You can pass in different options to these factory
     94  * methods to control the length of the result; from SHORT to MEDIUM to LONG to
     95  * FULL. The exact result depends on the locale, but generally:
     96  * <ul>
     97  * <li>SHORT is completely numeric, such as 12.13.52 or 3:30pm
     98  * <li>MEDIUM is longer, such as Jan 12, 1952
     99  * <li>LONG is longer, such as January 12, 1952 or 3:30:32pm
    100  * <li>FULL is pretty completely specified, such as Tuesday, April 12, 1952 AD
    101  * or 3:30:42pm PST.
    102  * </ul>
    103  * <p>
    104  * If needed, the time zone can be set on the format. For even greater control
    105  * over the formatting or parsing, try casting the {@code DateFormat} you get
    106  * from the factory methods to a {@code SimpleDateFormat}. This will work for
    107  * the majority of countries; just remember to put it in a try block in case you
    108  * encounter an unusual one.
    109  * <p>
    110  * There are versions of the parse and format methods which use
    111  * {@code ParsePosition} and {@code FieldPosition} to allow you to
    112  * <ul>
    113  * <li>progressively parse through pieces of a string;
    114  * <li>align any particular field.
    115  * </ul>
    116  * <h4>Synchronization</h4>
    117  * <p>
    118  * Date formats are not synchronized. It is recommended to create separate
    119  * format instances for each thread. If multiple threads access a format
    120  * concurrently, it must be synchronized externally.
    121  *
    122  * @see NumberFormat
    123  * @see SimpleDateFormat
    124  * @see Calendar
    125  * @see TimeZone
    126  */
    127 public abstract class DateFormat extends Format {
    128 
    129     private static final long serialVersionUID = 7218322306649953788L;
    130 
    131     /**
    132      * The calendar that this {@code DateFormat} uses to format a number
    133      * representing a date.
    134      */
    135     protected Calendar calendar;
    136 
    137     /**
    138      * The number format used to format a number.
    139      */
    140     protected NumberFormat numberFormat;
    141 
    142     /**
    143      * The format style constant defining the default format style. The default
    144      * is MEDIUM.
    145      */
    146     public static final int DEFAULT = 2;
    147 
    148     /**
    149      * The format style constant defining the full style.
    150      */
    151     public static final int FULL = 0;
    152 
    153     /**
    154      * The format style constant defining the long style.
    155      */
    156     public static final int LONG = 1;
    157 
    158     /**
    159      * The format style constant defining the medium style.
    160      */
    161     public static final int MEDIUM = 2;
    162 
    163     /**
    164      * The format style constant defining the short style.
    165      */
    166     public static final int SHORT = 3;
    167 
    168     /**
    169      * The {@code FieldPosition} selector for 'G' field alignment, corresponds
    170      * to the {@link Calendar#ERA} field.
    171      */
    172     public static final int ERA_FIELD = 0;
    173 
    174     /**
    175      * The {@code FieldPosition} selector for 'y' field alignment, corresponds
    176      * to the {@link Calendar#YEAR} field.
    177      */
    178     public static final int YEAR_FIELD = 1;
    179 
    180     /**
    181      * The {@code FieldPosition} selector for 'M' field alignment, corresponds
    182      * to the {@link Calendar#MONTH} field.
    183      */
    184     public static final int MONTH_FIELD = 2;
    185 
    186     /**
    187      * The {@code FieldPosition} selector for 'd' field alignment, corresponds
    188      * to the {@link Calendar#DATE} field.
    189      */
    190     public static final int DATE_FIELD = 3;
    191 
    192     /**
    193      * The {@code FieldPosition} selector for 'k' field alignment, corresponds
    194      * to the {@link Calendar#HOUR_OF_DAY} field. {@code HOUR_OF_DAY1_FIELD} is
    195      * used for the one-based 24-hour clock. For example, 23:59 + 01:00 results
    196      * in 24:59.
    197      */
    198     public static final int HOUR_OF_DAY1_FIELD = 4;
    199 
    200     /**
    201      * The {@code FieldPosition} selector for 'H' field alignment, corresponds
    202      * to the {@link Calendar#HOUR_OF_DAY} field. {@code HOUR_OF_DAY0_FIELD} is
    203      * used for the zero-based 24-hour clock. For example, 23:59 + 01:00 results
    204      * in 00:59.
    205      */
    206     public static final int HOUR_OF_DAY0_FIELD = 5;
    207 
    208     /**
    209      * FieldPosition selector for 'm' field alignment, corresponds to the
    210      * {@link Calendar#MINUTE} field.
    211      */
    212     public static final int MINUTE_FIELD = 6;
    213 
    214     /**
    215      * FieldPosition selector for 's' field alignment, corresponds to the
    216      * {@link Calendar#SECOND} field.
    217      */
    218     public static final int SECOND_FIELD = 7;
    219 
    220     /**
    221      * FieldPosition selector for 'S' field alignment, corresponds to the
    222      * {@link Calendar#MILLISECOND} field.
    223      */
    224     public static final int MILLISECOND_FIELD = 8;
    225 
    226     /**
    227      * FieldPosition selector for 'E' field alignment, corresponds to the
    228      * {@link Calendar#DAY_OF_WEEK} field.
    229      */
    230     public static final int DAY_OF_WEEK_FIELD = 9;
    231 
    232     /**
    233      * FieldPosition selector for 'D' field alignment, corresponds to the
    234      * {@link Calendar#DAY_OF_YEAR} field.
    235      */
    236     public static final int DAY_OF_YEAR_FIELD = 10;
    237 
    238     /**
    239      * FieldPosition selector for 'F' field alignment, corresponds to the
    240      * {@link Calendar#DAY_OF_WEEK_IN_MONTH} field.
    241      */
    242     public static final int DAY_OF_WEEK_IN_MONTH_FIELD = 11;
    243 
    244     /**
    245      * FieldPosition selector for 'w' field alignment, corresponds to the
    246      * {@link Calendar#WEEK_OF_YEAR} field.
    247      */
    248     public static final int WEEK_OF_YEAR_FIELD = 12;
    249 
    250     /**
    251      * FieldPosition selector for 'W' field alignment, corresponds to the
    252      * {@link Calendar#WEEK_OF_MONTH} field.
    253      */
    254     public static final int WEEK_OF_MONTH_FIELD = 13;
    255 
    256     /**
    257      * FieldPosition selector for 'a' field alignment, corresponds to the
    258      * {@link Calendar#AM_PM} field.
    259      */
    260     public static final int AM_PM_FIELD = 14;
    261 
    262     /**
    263      * FieldPosition selector for 'h' field alignment, corresponding to the
    264      * {@link Calendar#HOUR} field.
    265      */
    266     public static final int HOUR1_FIELD = 15;
    267 
    268     /**
    269      * The {@code FieldPosition} selector for 'K' field alignment, corresponding to the
    270      * {@link Calendar#HOUR} field.
    271      */
    272     public static final int HOUR0_FIELD = 16;
    273 
    274     /**
    275      * The {@code FieldPosition} selector for 'z' field alignment, corresponds
    276      * to the {@link Calendar#ZONE_OFFSET} and {@link Calendar#DST_OFFSET}
    277      * fields.
    278      */
    279     public static final int TIMEZONE_FIELD = 17;
    280 
    281     /**
    282      * Constructs a new instance of {@code DateFormat}.
    283      */
    284     protected DateFormat() {
    285     }
    286 
    287     /**
    288      * Returns a new instance of {@code DateFormat} with the same properties.
    289      */
    290     @Override
    291     public Object clone() {
    292         DateFormat clone = (DateFormat) super.clone();
    293         clone.calendar = (Calendar) calendar.clone();
    294         clone.numberFormat = (NumberFormat) numberFormat.clone();
    295         return clone;
    296     }
    297 
    298     /**
    299      * Compares this date format with the specified object and indicates if they
    300      * are equal.
    301      *
    302      * @param object
    303      *            the object to compare with this date format.
    304      * @return {@code true} if {@code object} is a {@code DateFormat} object and
    305      *         it has the same properties as this date format; {@code false}
    306      *         otherwise.
    307      * @see #hashCode
    308      */
    309     @Override
    310     public boolean equals(Object object) {
    311         if (this == object) {
    312             return true;
    313         }
    314         if (!(object instanceof DateFormat)) {
    315             return false;
    316         }
    317         DateFormat dateFormat = (DateFormat) object;
    318         return numberFormat.equals(dateFormat.numberFormat)
    319                 && calendar.getTimeZone().equals(
    320                         dateFormat.calendar.getTimeZone())
    321                 && calendar.getFirstDayOfWeek() == dateFormat.calendar
    322                         .getFirstDayOfWeek()
    323                 && calendar.getMinimalDaysInFirstWeek() == dateFormat.calendar
    324                         .getMinimalDaysInFirstWeek()
    325                 && calendar.isLenient() == dateFormat.calendar.isLenient();
    326     }
    327 
    328     /**
    329      * Formats the specified object as a string using the pattern of this date
    330      * format and appends the string to the specified string buffer.
    331      * <p>
    332      * If the {@code field} member of {@code field} contains a value specifying
    333      * a format field, then its {@code beginIndex} and {@code endIndex} members
    334      * will be updated with the position of the first occurrence of this field
    335      * in the formatted text.
    336      *
    337      * @param object
    338      *            the source object to format, must be a {@code Date} or a
    339      *            {@code Number}. If {@code object} is a number then a date is
    340      *            constructed using the {@code longValue()} of the number.
    341      * @param buffer
    342      *            the target string buffer to append the formatted date/time to.
    343      * @param field
    344      *            on input: an optional alignment field; on output: the offsets
    345      *            of the alignment field in the formatted text.
    346      * @return the string buffer.
    347      * @throws IllegalArgumentException
    348      *            if {@code object} is neither a {@code Date} nor a
    349      *            {@code Number} instance.
    350      */
    351     @Override
    352     public final StringBuffer format(Object object, StringBuffer buffer,
    353             FieldPosition field) {
    354         if (object instanceof Date) {
    355             return format((Date) object, buffer, field);
    356         }
    357         if (object instanceof Number) {
    358             return format(new Date(((Number) object).longValue()), buffer,
    359                     field);
    360         }
    361         throw new IllegalArgumentException();
    362     }
    363 
    364     /**
    365      * Formats the specified date using the rules of this date format.
    366      *
    367      * @param date
    368      *            the date to format.
    369      * @return the formatted string.
    370      */
    371     public final String format(Date date) {
    372         return format(date, new StringBuffer(), new FieldPosition(0))
    373                 .toString();
    374     }
    375 
    376     /**
    377      * Formats the specified date as a string using the pattern of this date
    378      * format and appends the string to the specified string buffer.
    379      * <p>
    380      * If the {@code field} member of {@code field} contains a value specifying
    381      * a format field, then its {@code beginIndex} and {@code endIndex} members
    382      * will be updated with the position of the first occurrence of this field
    383      * in the formatted text.
    384      *
    385      * @param date
    386      *            the date to format.
    387      * @param buffer
    388      *            the target string buffer to append the formatted date/time to.
    389      * @param field
    390      *            on input: an optional alignment field; on output: the offsets
    391      *            of the alignment field in the formatted text.
    392      * @return the string buffer.
    393      */
    394     public abstract StringBuffer format(Date date, StringBuffer buffer,
    395             FieldPosition field);
    396 
    397     /**
    398      * Returns an array of locales for which custom {@code DateFormat} instances
    399      * are available.
    400      * <p>Note that Android does not support user-supplied locale service providers.
    401      */
    402     public static Locale[] getAvailableLocales() {
    403         return ICU.getAvailableDateFormatLocales();
    404     }
    405 
    406     /**
    407      * Returns the calendar used by this {@code DateFormat}.
    408      *
    409      * @return the calendar used by this date format.
    410      */
    411     public Calendar getCalendar() {
    412         return calendar;
    413     }
    414 
    415     /**
    416      * Returns a {@code DateFormat} instance for formatting and parsing dates in
    417      * the DEFAULT style for the default locale.
    418      *
    419      * @return the {@code DateFormat} instance for the default style and locale.
    420      */
    421     public static final DateFormat getDateInstance() {
    422         return getDateInstance(DEFAULT);
    423     }
    424 
    425     /**
    426      * Returns a {@code DateFormat} instance for formatting and parsing dates in
    427      * the specified style for the user's default locale.
    428      * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
    429      * @param style
    430      *            one of SHORT, MEDIUM, LONG, FULL, or DEFAULT.
    431      * @return the {@code DateFormat} instance for {@code style} and the default
    432      *         locale.
    433      * @throws IllegalArgumentException
    434      *             if {@code style} is not one of SHORT, MEDIUM, LONG, FULL, or
    435      *             DEFAULT.
    436      */
    437     public static final DateFormat getDateInstance(int style) {
    438         checkDateStyle(style);
    439         return getDateInstance(style, Locale.getDefault());
    440     }
    441 
    442     /**
    443      * Returns a {@code DateFormat} instance for formatting and parsing dates in
    444      * the specified style for the specified locale.
    445      *
    446      * @param style
    447      *            one of SHORT, MEDIUM, LONG, FULL, or DEFAULT.
    448      * @param locale
    449      *            the locale.
    450      * @throws IllegalArgumentException
    451      *             if {@code style} is not one of SHORT, MEDIUM, LONG, FULL, or
    452      *             DEFAULT.
    453      * @return the {@code DateFormat} instance for {@code style} and
    454      *         {@code locale}.
    455      */
    456     public static final DateFormat getDateInstance(int style, Locale locale) {
    457         checkDateStyle(style);
    458         return new SimpleDateFormat(LocaleData.get(locale).getDateFormat(style), locale);
    459     }
    460 
    461     /**
    462      * Returns a {@code DateFormat} instance for formatting and parsing dates
    463      * and time values in the DEFAULT style for the default locale.
    464      *
    465      * @return the {@code DateFormat} instance for the default style and locale.
    466      */
    467     public static final DateFormat getDateTimeInstance() {
    468         return getDateTimeInstance(DEFAULT, DEFAULT);
    469     }
    470 
    471     /**
    472      * Returns a {@code DateFormat} instance for formatting and parsing of both
    473      * dates and time values in the manner appropriate for the user's default locale.
    474      * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
    475      * @param dateStyle
    476      *            one of SHORT, MEDIUM, LONG, FULL, or DEFAULT.
    477      * @param timeStyle
    478      *            one of SHORT, MEDIUM, LONG, FULL, or DEFAULT.
    479      * @return the {@code DateFormat} instance for {@code dateStyle},
    480      *         {@code timeStyle} and the default locale.
    481      * @throws IllegalArgumentException
    482      *             if {@code dateStyle} or {@code timeStyle} is not one of
    483      *             SHORT, MEDIUM, LONG, FULL, or DEFAULT.
    484      */
    485     public static final DateFormat getDateTimeInstance(int dateStyle, int timeStyle) {
    486         checkTimeStyle(timeStyle);
    487         checkDateStyle(dateStyle);
    488         return getDateTimeInstance(dateStyle, timeStyle, Locale.getDefault());
    489     }
    490 
    491     /**
    492      * Returns a {@code DateFormat} instance for formatting and parsing dates
    493      * and time values in the specified styles for the specified locale.
    494      *
    495      * @param dateStyle
    496      *            one of SHORT, MEDIUM, LONG, FULL, or DEFAULT.
    497      * @param timeStyle
    498      *            one of SHORT, MEDIUM, LONG, FULL, or DEFAULT.
    499      * @param locale
    500      *            the locale.
    501      * @return the {@code DateFormat} instance for {@code dateStyle},
    502      *         {@code timeStyle} and {@code locale}.
    503      * @throws IllegalArgumentException
    504      *             if {@code dateStyle} or {@code timeStyle} is not one of
    505      *             SHORT, MEDIUM, LONG, FULL, or DEFAULT.
    506      */
    507     public static final DateFormat getDateTimeInstance(int dateStyle, int timeStyle, Locale locale) {
    508         checkTimeStyle(timeStyle);
    509         checkDateStyle(dateStyle);
    510         LocaleData localeData = LocaleData.get(locale);
    511         String pattern = localeData.getDateFormat(dateStyle) + " " + localeData.getTimeFormat(timeStyle);
    512         return new SimpleDateFormat(pattern, locale);
    513     }
    514 
    515     /**
    516      * Returns a {@code DateFormat} instance for formatting and parsing dates
    517      * and times in the SHORT style for the default locale.
    518      *
    519      * @return the {@code DateFormat} instance for the SHORT style and default
    520      *         locale.
    521      */
    522     public static final DateFormat getInstance() {
    523         return getDateTimeInstance(SHORT, SHORT);
    524     }
    525 
    526     /**
    527      * Returns the {@code NumberFormat} used by this {@code DateFormat}.
    528      *
    529      * @return the {@code NumberFormat} used by this date format.
    530      */
    531     public NumberFormat getNumberFormat() {
    532         return numberFormat;
    533     }
    534 
    535     /**
    536      * Returns a {@code DateFormat} instance for formatting and parsing time
    537      * values in the DEFAULT style for the default locale.
    538      *
    539      * @return the {@code DateFormat} instance for the default style and locale.
    540      */
    541     public static final DateFormat getTimeInstance() {
    542         return getTimeInstance(DEFAULT);
    543     }
    544 
    545     /**
    546      * Returns a {@code DateFormat} instance for formatting and parsing time
    547      * values in the specified style for the user's default locale.
    548      * See "<a href="../util/Locale.html#default_locale">Be wary of the default locale</a>".
    549      * @param style
    550      *            one of SHORT, MEDIUM, LONG, FULL, or DEFAULT.
    551      * @return the {@code DateFormat} instance for {@code style} and the default
    552      *         locale.
    553      * @throws IllegalArgumentException
    554      *             if {@code style} is not one of SHORT, MEDIUM, LONG, FULL, or
    555      *             DEFAULT.
    556      */
    557     public static final DateFormat getTimeInstance(int style) {
    558         checkTimeStyle(style);
    559         return getTimeInstance(style, Locale.getDefault());
    560     }
    561 
    562     /**
    563      * Returns a {@code DateFormat} instance for formatting and parsing time
    564      * values in the specified style for the specified locale.
    565      *
    566      * @param style
    567      *            one of SHORT, MEDIUM, LONG, FULL, or DEFAULT.
    568      * @param locale
    569      *            the locale.
    570      * @throws IllegalArgumentException
    571      *             if {@code style} is not one of SHORT, MEDIUM, LONG, FULL, or
    572      *             DEFAULT.
    573      * @return the {@code DateFormat} instance for {@code style} and
    574      *         {@code locale}.
    575      */
    576     public static final DateFormat getTimeInstance(int style, Locale locale) {
    577         checkTimeStyle(style);
    578         return new SimpleDateFormat(LocaleData.get(locale).getTimeFormat(style), locale);
    579     }
    580 
    581     /**
    582      * Returns the time zone of this date format's calendar.
    583      *
    584      * @return the time zone of the calendar used by this date format.
    585      */
    586     public TimeZone getTimeZone() {
    587         return calendar.getTimeZone();
    588     }
    589 
    590     @Override
    591     public int hashCode() {
    592         return calendar.getFirstDayOfWeek()
    593                 + calendar.getMinimalDaysInFirstWeek()
    594                 + calendar.getTimeZone().hashCode()
    595                 + (calendar.isLenient() ? 1231 : 1237)
    596                 + numberFormat.hashCode();
    597     }
    598 
    599     /**
    600      * Indicates whether the calendar used by this date format is lenient.
    601      *
    602      * @return {@code true} if the calendar is lenient; {@code false} otherwise.
    603      */
    604     public boolean isLenient() {
    605         return calendar.isLenient();
    606     }
    607 
    608     /**
    609      * Parses a date from the specified string using the rules of this date
    610      * format.
    611      *
    612      * @param string
    613      *            the string to parse.
    614      * @return the {@code Date} resulting from the parsing.
    615      * @throws ParseException
    616      *         if an error occurs during parsing.
    617      */
    618     public Date parse(String string) throws ParseException {
    619         ParsePosition position = new ParsePosition(0);
    620         Date date = parse(string, position);
    621         if (position.getIndex() == 0) {
    622             throw new ParseException("Unparseable date: \"" + string + "\"",
    623                     position.getErrorIndex());
    624         }
    625         return date;
    626     }
    627 
    628     /**
    629      * Parses a date from the specified string starting at the index specified
    630      * by {@code position}. If the string is successfully parsed then the index
    631      * of the {@code ParsePosition} is updated to the index following the parsed
    632      * text. On error, the index is unchanged and the error index of {@code
    633      * ParsePosition} is set to the index where the error occurred.
    634      * <p>
    635      * By default, parsing is lenient: If the input is not in the form used by
    636      * this object's format method but can still be parsed as a date, then the
    637      * parse succeeds. Clients may insist on strict adherence to the format by
    638      * calling {@code setLenient(false)}.
    639      *
    640      * @param string
    641      *            the string to parse.
    642      * @param position
    643      *            input/output parameter, specifies the start index in {@code
    644      *            string} from where to start parsing. If parsing is successful,
    645      *            it is updated with the index following the parsed text; on
    646      *            error, the index is unchanged and the error index is set to
    647      *            the index where the error occurred.
    648      * @return the date resulting from the parse, or {@code null} if there is an
    649      *         error.
    650      */
    651     public abstract Date parse(String string, ParsePosition position);
    652 
    653     /**
    654      * Parses a date from the specified string starting at the index specified
    655      * by {@code position}. If the string is successfully parsed then the index
    656      * of the {@code ParsePosition} is updated to the index following the parsed
    657      * text. On error, the index is unchanged and the error index of
    658      * {@code ParsePosition} is set to the index where the error occurred.
    659      * <p>
    660      * By default, parsing is lenient: If the input is not in the form used by
    661      * this object's format method but can still be parsed as a date, then the
    662      * parse succeeds. Clients may insist on strict adherence to the format by
    663      * calling {@code setLenient(false)}.
    664      *
    665      * @param string
    666      *            the string to parse.
    667      * @param position
    668      *            input/output parameter, specifies the start index in
    669      *            {@code string} from where to start parsing. If parsing is
    670      *            successful, it is updated with the index following the parsed
    671      *            text; on error, the index is unchanged and the error index
    672      *            is set to the index where the error occurred.
    673      * @return the date resulting from the parsing, or {@code null} if there is
    674      *         an error.
    675      */
    676     @Override
    677     public Object parseObject(String string, ParsePosition position) {
    678         return parse(string, position);
    679     }
    680 
    681     /**
    682      * Sets the calendar used by this date format.
    683      *
    684      * @param cal
    685      *            the new calendar.
    686      */
    687     public void setCalendar(Calendar cal) {
    688         calendar = cal;
    689     }
    690 
    691     /**
    692      * Specifies whether or not date/time parsing shall be lenient. With lenient
    693      * parsing, the parser may use heuristics to interpret inputs that do not
    694      * precisely match this object's format. With strict parsing, inputs must
    695      * match this object's format.
    696      *
    697      * @param value
    698      *            {@code true} to set the calendar to be lenient, {@code false}
    699      *            otherwise.
    700      */
    701     public void setLenient(boolean value) {
    702         calendar.setLenient(value);
    703     }
    704 
    705     /**
    706      * Sets the {@code NumberFormat} used by this date format.
    707      *
    708      * @param format
    709      *            the new number format.
    710      */
    711     public void setNumberFormat(NumberFormat format) {
    712         numberFormat = format;
    713     }
    714 
    715     /**
    716      * Sets the time zone of the calendar used by this date format.
    717      *
    718      * @param timezone
    719      *            the new time zone.
    720      */
    721     public void setTimeZone(TimeZone timezone) {
    722         calendar.setTimeZone(timezone);
    723     }
    724 
    725     /**
    726      * The instances of this inner class are used as attribute keys and values
    727      * in {@code AttributedCharacterIterator} that the
    728      * {@link SimpleDateFormat#formatToCharacterIterator(Object)} method returns.
    729      * <p>
    730      * There is no public constructor in this class, the only instances are the
    731      * constants defined here.
    732      */
    733     public static class Field extends Format.Field {
    734 
    735         private static final long serialVersionUID = 7441350119349544720L;
    736 
    737         private static Hashtable<Integer, Field> table = new Hashtable<Integer, Field>();
    738 
    739         /**
    740          * Marks the era part of a date.
    741          */
    742         public static final Field ERA = new Field("era", Calendar.ERA);
    743 
    744         /**
    745          * Marks the year part of a date.
    746          */
    747         public static final Field YEAR = new Field("year", Calendar.YEAR);
    748 
    749         /**
    750          * Marks the month part of a date.
    751          */
    752         public static final Field MONTH = new Field("month", Calendar.MONTH);
    753 
    754         /**
    755          * Marks the hour of the day part of a date (0-11).
    756          */
    757         public static final Field HOUR_OF_DAY0 = new Field("hour of day", Calendar.HOUR_OF_DAY);
    758 
    759         /**
    760          * Marks the hour of the day part of a date (1-12).
    761          */
    762         public static final Field HOUR_OF_DAY1 = new Field("hour of day 1", -1);
    763 
    764         /**
    765          * Marks the minute part of a time.
    766          */
    767         public static final Field MINUTE = new Field("minute", Calendar.MINUTE);
    768 
    769         /**
    770          * Marks the second part of a time.
    771          */
    772         public static final Field SECOND = new Field("second", Calendar.SECOND);
    773 
    774         /**
    775          * Marks the millisecond part of a time.
    776          */
    777         public static final Field MILLISECOND = new Field("millisecond", Calendar.MILLISECOND);
    778 
    779         /**
    780          * Marks the day of the week part of a date.
    781          */
    782         public static final Field DAY_OF_WEEK = new Field("day of week", Calendar.DAY_OF_WEEK);
    783 
    784         /**
    785          * Marks the day of the month part of a date.
    786          */
    787         public static final Field DAY_OF_MONTH = new Field("day of month", Calendar.DAY_OF_MONTH);
    788 
    789         /**
    790          * Marks the day of the year part of a date.
    791          */
    792         public static final Field DAY_OF_YEAR = new Field("day of year", Calendar.DAY_OF_YEAR);
    793 
    794         /**
    795          * Marks the day of the week in the month part of a date.
    796          */
    797         public static final Field DAY_OF_WEEK_IN_MONTH = new Field("day of week in month",
    798                 Calendar.DAY_OF_WEEK_IN_MONTH);
    799 
    800         /**
    801          * Marks the week of the year part of a date.
    802          */
    803         public static final Field WEEK_OF_YEAR = new Field("week of year",
    804                 Calendar.WEEK_OF_YEAR);
    805 
    806         /**
    807          * Marks the week of the month part of a date.
    808          */
    809         public static final Field WEEK_OF_MONTH = new Field("week of month",
    810                 Calendar.WEEK_OF_MONTH);
    811 
    812         /**
    813          * Marks the time indicator part of a date.
    814          */
    815         public static final Field AM_PM = new Field("am pm", Calendar.AM_PM);
    816 
    817         /**
    818          * Marks the hour part of a date (0-11).
    819          */
    820         public static final Field HOUR0 = new Field("hour", Calendar.HOUR);
    821 
    822         /**
    823          * Marks the hour part of a date (1-12).
    824          */
    825         public static final Field HOUR1 = new Field("hour 1", -1);
    826 
    827         /**
    828          * Marks the time zone part of a date.
    829          */
    830         public static final Field TIME_ZONE = new Field("time zone", -1);
    831 
    832         /**
    833          * The calendar field that this field represents.
    834          */
    835         private int calendarField = -1;
    836 
    837         /**
    838          * Constructs a new instance of {@code DateFormat.Field} with the given
    839          * fieldName and calendar field.
    840          *
    841          * @param fieldName
    842          *            the field name.
    843          * @param calendarField
    844          *            the calendar field type of the field.
    845          */
    846         protected Field(String fieldName, int calendarField) {
    847             super(fieldName);
    848             this.calendarField = calendarField;
    849             if (calendarField != -1 && table.get(Integer.valueOf(calendarField)) == null) {
    850                 table.put(Integer.valueOf(calendarField), this);
    851             }
    852         }
    853 
    854         /**
    855          * Returns the Calendar field that this field represents.
    856          *
    857          * @return the calendar field.
    858          */
    859         public int getCalendarField() {
    860             return calendarField;
    861         }
    862 
    863         /**
    864          * Returns the {@code DateFormat.Field} instance for the given calendar
    865          * field.
    866          *
    867          * @param calendarField
    868          *            a calendar field constant.
    869          * @return the {@code DateFormat.Field} corresponding to
    870          *         {@code calendarField}.
    871          * @throws IllegalArgumentException
    872          *             if {@code calendarField} is negative or greater than the
    873          *             field count of {@code Calendar}.
    874          */
    875         public static Field ofCalendarField(int calendarField) {
    876             if (calendarField < 0 || calendarField >= Calendar.FIELD_COUNT) {
    877                 throw new IllegalArgumentException();
    878             }
    879 
    880             return table.get(Integer.valueOf(calendarField));
    881         }
    882     }
    883 
    884     private static void checkDateStyle(int style) {
    885         if (!(style == SHORT || style == MEDIUM || style == LONG
    886                 || style == FULL || style == DEFAULT)) {
    887             throw new IllegalArgumentException("Illegal date style " + style);
    888         }
    889     }
    890 
    891     private static void checkTimeStyle(int style) {
    892         if (!(style == SHORT || style == MEDIUM || style == LONG
    893                 || style == FULL || style == DEFAULT)) {
    894             throw new IllegalArgumentException("Illegal time style " + style);
    895         }
    896     }
    897 }
    898