151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
22c87ad3a45cecf9e344487cad1abfdebe79f2c7cNarayan Kamath * Copyright (C) 2014 The Android Open Source Project
351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (C) Copyright IBM Corp. 1996-1998 - All Rights Reserved
3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *   The original version of this source code and documentation is copyrighted
3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * materials are provided under terms of a License Agreement between Taligent
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and Sun. This technology is protected by multiple US and International
3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * patents. This notice and attribution to Taligent may not be removed.
3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *   Taligent is a registered trademark of Taligent, Inc.
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.text;
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.IOException;
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.InvalidObjectException;
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.ObjectInputStream;
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Calendar;
4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Date;
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.GregorianCalendar;
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Locale;
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.Map;
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.SimpleTimeZone;
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.TimeZone;
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.concurrent.ConcurrentHashMap;
5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.concurrent.ConcurrentMap;
549c853c5b9ebbb0ef60a013ae10ee411d70dfa832Piotr Jastrzebskiimport libcore.icu.LocaleData;
55cdde6627c3b5fe67e086043cb789e88110a38028Joachim Sauerimport libcore.icu.TimeZoneNames;
56cdde6627c3b5fe67e086043cb789e88110a38028Joachim Sauer
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport sun.util.calendar.CalendarUtils;
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport static java.text.DateFormatSymbols.*;
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>SimpleDateFormat</code> is a concrete class for formatting and
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * parsing dates in a locale-sensitive manner. It allows for formatting
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * (date -> text), parsing (text -> date), and normalization.
6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>SimpleDateFormat</code> allows you to start by choosing
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * any user-defined patterns for date-time formatting. However, you
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * are encouraged to create a date-time formatter with either
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>getTimeInstance</code>, <code>getDateInstance</code>, or
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>getDateTimeInstance</code> in <code>DateFormat</code>. Each
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of these class methods can return a date/time formatter initialized
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * with a default format pattern. You may modify the format pattern
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * using the <code>applyPattern</code> methods as desired.
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * For more information on using these methods, see
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * {@link DateFormat}.
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <h4>Date and Time Patterns</h4>
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>
8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Date and time formats are specified by <em>date and time pattern</em>
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * strings.
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Within date and time pattern strings, unquoted letters from
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>'A'</code> to <code>'Z'</code> and from <code>'a'</code> to
8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>'z'</code> are interpreted as pattern letters representing the
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * components of a date or time string.
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Text can be quoted using single quotes (<code>'</code>) to avoid
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * interpretation.
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>"''"</code> represents a single quote.
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * All other characters are not interpreted; they're simply copied into the
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * output string during formatting or matched against the input string
9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * during parsing.
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>
9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The following pattern letters are defined (all other characters from
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>'A'</code> to <code>'Z'</code> and from <code>'a'</code> to
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>'z'</code> are reserved):
9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote>
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <table border=0 cellspacing=3 cellpadding=0 summary="Chart shows pattern letters, date/time component, presentation, and examples.">
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr bgcolor="#ccccff">
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <th align=left>Letter
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <th align=left>Date or Time Component
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <th align=left>Presentation
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <th align=left>Examples
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr>
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>G</code>
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td>Era designator
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><a href="#text">Text</a>
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>AD</code>
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr bgcolor="#eeeeff">
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>y</code>
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td>Year
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><a href="#year">Year</a>
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>1996</code>; <code>96</code>
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr>
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>Y</code>
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td>Week year
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><a href="#year">Year</a>
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>2009</code>; <code>09</code>
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr bgcolor="#eeeeff">
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>M</code>
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td>Month in year
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><a href="#month">Month</a>
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>July</code>; <code>Jul</code>; <code>07</code>
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr>
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>w</code>
12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td>Week in year
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><a href="#number">Number</a>
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>27</code>
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr bgcolor="#eeeeff">
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>W</code>
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td>Week in month
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><a href="#number">Number</a>
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>2</code>
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr>
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>D</code>
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td>Day in year
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><a href="#number">Number</a>
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>189</code>
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr bgcolor="#eeeeff">
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>d</code>
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td>Day in month
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><a href="#number">Number</a>
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>10</code>
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr>
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>F</code>
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td>Day of week in month
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><a href="#number">Number</a>
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>2</code>
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr bgcolor="#eeeeff">
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>E</code>
15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td>Day name in week
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><a href="#text">Text</a>
15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>Tuesday</code>; <code>Tue</code>
15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr>
15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>u</code>
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td>Day number of week (1 = Monday, ..., 7 = Sunday)
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><a href="#number">Number</a>
15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>1</code>
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr bgcolor="#eeeeff">
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>a</code>
16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td>Am/pm marker
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><a href="#text">Text</a>
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>PM</code>
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr>
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>H</code>
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td>Hour in day (0-23)
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><a href="#number">Number</a>
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>0</code>
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr bgcolor="#eeeeff">
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>k</code>
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td>Hour in day (1-24)
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><a href="#number">Number</a>
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>24</code>
17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr>
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>K</code>
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td>Hour in am/pm (0-11)
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><a href="#number">Number</a>
17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>0</code>
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr bgcolor="#eeeeff">
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>h</code>
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td>Hour in am/pm (1-12)
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><a href="#number">Number</a>
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>12</code>
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr>
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>m</code>
18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td>Minute in hour
18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><a href="#number">Number</a>
18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>30</code>
18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr bgcolor="#eeeeff">
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>s</code>
19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td>Second in minute
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><a href="#number">Number</a>
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>55</code>
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr>
19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>S</code>
19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td>Millisecond
19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><a href="#number">Number</a>
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>978</code>
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr bgcolor="#eeeeff">
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>z</code>
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td>Time zone
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><a href="#timezone">General time zone</a>
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>Pacific Standard Time</code>; <code>PST</code>; <code>GMT-08:00</code>
20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr>
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>Z</code>
20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td>Time zone
20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><a href="#rfc822timezone">RFC 822 time zone</a>
20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>-0800</code>
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr bgcolor="#eeeeff">
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>X</code>
21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td>Time zone
21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><a href="#iso8601timezone">ISO 8601 time zone</a>
21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>-08</code>; <code>-0800</code>;  <code>-08:00</code>
21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </table>
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </blockquote>
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Pattern letters are usually repeated, as their number determines the
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * exact presentation:
21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <ul>
21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li><strong><a name="text">Text:</a></strong>
21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     For formatting, if the number of pattern letters is 4 or more,
22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     the full form is used; otherwise a short or abbreviated form
22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     is used if available.
22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     For parsing, both forms are accepted, independent of the number
22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     of pattern letters.<br><br></li>
22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li><strong><a name="number">Number:</a></strong>
22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     For formatting, the number of pattern letters is the minimum
22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     number of digits, and shorter numbers are zero-padded to this amount.
22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     For parsing, the number of pattern letters is ignored unless
22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     it's needed to separate two adjacent fields.<br><br></li>
22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li><strong><a name="year">Year:</a></strong>
23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     If the formatter's {@link #getCalendar() Calendar} is the Gregorian
23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     calendar, the following rules are applied.<br>
23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <ul>
23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <li>For formatting, if the number of pattern letters is 2, the year
23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         is truncated to 2 digits; otherwise it is interpreted as a
23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <a href="#number">number</a>.
23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <li>For parsing, if the number of pattern letters is more than 2,
23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         the year is interpreted literally, regardless of the number of
23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         digits. So using the pattern "MM/dd/yyyy", "01/11/12" parses to
23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         Jan 11, 12 A.D.
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <li>For parsing with the abbreviated year pattern ("y" or "yy"),
24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <code>SimpleDateFormat</code> must interpret the abbreviated year
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         relative to some century.  It does this by adjusting dates to be
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         within 80 years before and 20 years after the time the <code>SimpleDateFormat</code>
24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         instance is created. For example, using a pattern of "MM/dd/yy" and a
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <code>SimpleDateFormat</code> instance created on Jan 1, 1997,  the string
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         "01/11/12" would be interpreted as Jan 11, 2012 while the string "05/04/64"
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         would be interpreted as May 4, 1964.
24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         During parsing, only strings consisting of exactly two digits, as defined by
24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         {@link Character#isDigit(char)}, will be parsed into the default century.
25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         Any other numeric string, such as a one digit string, a three or more digit
25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         string, or a two digit string that isn't all digits (for example, "-1"), is
25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         interpreted literally.  So "01/02/3" or "01/02/003" are parsed, using the
25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         same pattern, as Jan 2, 3 AD.  Likewise, "01/02/-3" is parsed as Jan 2, 4 BC.
25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     </ul>
25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     Otherwise, calendar system specific forms are applied.
25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     For both formatting and parsing, if the number of pattern
25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     letters is 4 or more, a calendar specific {@linkplain
25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     Calendar#LONG long form} is used. Otherwise, a calendar
25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     specific {@linkplain Calendar#SHORT short or abbreviated form}
26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     is used.<br>
26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <br>
26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     If week year {@code 'Y'} is specified and the {@linkplain
26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     #getCalendar() calendar} doesn't support any <a
26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     href="../util/GregorianCalendar.html#week_year"> week
26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     years</a>, the calendar year ({@code 'y'}) is used instead. The
26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     support of week years can be tested with a call to {@link
26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     DateFormat#getCalendar() getCalendar()}.{@link
26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     java.util.Calendar#isWeekDateSupported()
26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     isWeekDateSupported()}.<br><br></li>
27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li><strong><a name="month">Month:</a></strong>
27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     If the number of pattern letters is 3 or more, the month is
27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     interpreted as <a href="#text">text</a>; otherwise,
27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     it is interpreted as a <a href="#number">number</a>.<br><br></li>
27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li><strong><a name="timezone">General time zone:</a></strong>
27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     Time zones are interpreted as <a href="#text">text</a> if they have
27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     names. For time zones representing a GMT offset value, the
27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     following syntax is used:
27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <pre>
27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <a name="GMTOffsetTimeZone"><i>GMTOffsetTimeZone:</i></a>
28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *             <code>GMT</code> <i>Sign</i> <i>Hours</i> <code>:</code> <i>Minutes</i>
28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <i>Sign:</i> one of
28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *             <code>+ -</code>
28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <i>Hours:</i>
28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *             <i>Digit</i>
28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *             <i>Digit</i> <i>Digit</i>
28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <i>Minutes:</i>
28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *             <i>Digit</i> <i>Digit</i>
28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <i>Digit:</i> one of
28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *             <code>0 1 2 3 4 5 6 7 8 9</code></pre>
29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <i>Hours</i> must be between 0 and 23, and <i>Minutes</i> must be between
29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     00 and 59. The format is locale independent and digits must be taken
29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     from the Basic Latin block of the Unicode standard.
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <p>For parsing, <a href="#rfc822timezone">RFC 822 time zones</a> are also
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     accepted.<br><br></li>
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li><strong><a name="rfc822timezone">RFC 822 time zone:</a></strong>
29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     For formatting, the RFC 822 4-digit time zone format is used:
29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <pre>
29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <i>RFC822TimeZone:</i>
30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *             <i>Sign</i> <i>TwoDigitHours</i> <i>Minutes</i>
30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <i>TwoDigitHours:</i>
30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *             <i>Digit Digit</i></pre>
30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <i>TwoDigitHours</i> must be between 00 and 23. Other definitions
30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     are as for <a href="#timezone">general time zones</a>.
30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <p>For parsing, <a href="#timezone">general time zones</a> are also
30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     accepted.
30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <li><strong><a name="iso8601timezone">ISO 8601 Time zone:</a></strong>
30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     The number of pattern letters designates the format for both formatting
31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     and parsing as follows:
31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <pre>
31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <i>ISO8601TimeZone:</i>
31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *             <i>OneLetterISO8601TimeZone</i>
31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *             <i>TwoLetterISO8601TimeZone</i>
31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *             <i>ThreeLetterISO8601TimeZone</i>
31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <i>OneLetterISO8601TimeZone:</i>
31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *             <i>Sign</i> <i>TwoDigitHours</i>
31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *             {@code Z}
31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <i>TwoLetterISO8601TimeZone:</i>
32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *             <i>Sign</i> <i>TwoDigitHours</i> <i>Minutes</i>
32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *             {@code Z}
32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <i>ThreeLetterISO8601TimeZone:</i>
32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *             <i>Sign</i> <i>TwoDigitHours</i> {@code :} <i>Minutes</i>
32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *             {@code Z}</pre>
32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     Other definitions are as for <a href="#timezone">general time zones</a> or
32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <a href="#rfc822timezone">RFC 822 time zones</a>.
32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <p>For formatting, if the offset value from GMT is 0, {@code "Z"} is
32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     produced. If the number of pattern letters is 1, any fraction of an hour
33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     is ignored. For example, if the pattern is {@code "X"} and the time zone is
33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     {@code "GMT+05:30"}, {@code "+05"} is produced.
33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <p>For parsing, {@code "Z"} is parsed as the UTC time zone designator.
33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <a href="#timezone">General time zones</a> are <em>not</em> accepted.
33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <p>If the number of pattern letters is 4 or more, {@link
33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     IllegalArgumentException} is thrown when constructing a {@code
33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     SimpleDateFormat} or {@linkplain #applyPattern(String) applying a
33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     pattern}.
34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </ul>
34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>SimpleDateFormat</code> also supports <em>localized date and time
34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * pattern</em> strings. In these strings, the pattern letters described above
34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * may be replaced with other, locale dependent, pattern letters.
34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <code>SimpleDateFormat</code> does not deal with the localization of text
34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * other than the pattern letters; that's up to the client of the class.
34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>
34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <h4>Examples</h4>
34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The following examples show how date and time patterns are interpreted in
35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * the U.S. locale. The given date and time are 2001-07-04 12:08:56 local time
35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * in the U.S. Pacific Time time zone.
35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <blockquote>
35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <table border=0 cellspacing=3 cellpadding=0 summary="Examples of date and time patterns interpreted in the U.S. locale">
35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr bgcolor="#ccccff">
35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <th align=left>Date and Time Pattern
35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <th align=left>Result
35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr>
35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>"yyyy.MM.dd G 'at' HH:mm:ss z"</code>
36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>2001.07.04 AD at 12:08:56 PDT</code>
36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr bgcolor="#eeeeff">
36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>"EEE, MMM d, ''yy"</code>
36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>Wed, Jul 4, '01</code>
36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr>
36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>"h:mm a"</code>
36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>12:08 PM</code>
36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr bgcolor="#eeeeff">
36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>"hh 'o''clock' a, zzzz"</code>
36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>12 o'clock PM, Pacific Daylight Time</code>
37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr>
37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>"K:mm a, z"</code>
37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>0:08 PM, PDT</code>
37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr bgcolor="#eeeeff">
37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>"yyyyy.MMMMM.dd GGG hh:mm aaa"</code>
37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>02001.July.04 AD 12:08 PM</code>
37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr>
37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>"EEE, d MMM yyyy HH:mm:ss Z"</code>
37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>Wed, 4 Jul 2001 12:08:56 -0700</code>
37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr bgcolor="#eeeeff">
38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>"yyMMddHHmmssZ"</code>
38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>010704120856-0700</code>
38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr>
38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>"yyyy-MM-dd'T'HH:mm:ss.SSSZ"</code>
38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>2001-07-04T12:08:56.235-0700</code>
38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr bgcolor="#eeeeff">
38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>"yyyy-MM-dd'T'HH:mm:ss.SSSXXX"</code>
38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>2001-07-04T12:08:56.235-07:00</code>
38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *     <tr>
38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>"YYYY-'W'ww-u"</code>
39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *         <td><code>2001-W27-3</code>
39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </table>
39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * </blockquote>
39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <h4><a name="synchronization">Synchronization</a></h4>
39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * <p>
39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Date formats are not synchronized.
39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * It is recommended to create separate format instances for each thread.
39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * If multiple threads access a format concurrently, it must be synchronized
40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * externally.
40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see          <a href="http://java.sun.com/docs/books/tutorial/i18n/format/simpleDateFormat.html">Java Tutorial</a>
40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see          java.util.Calendar
40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see          java.util.TimeZone
40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see          DateFormat
40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @see          DateFormatSymbols
40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author       Mark Davis, Chen-Lieh Huang, Alan Liu
40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic class SimpleDateFormat extends DateFormat {
41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // the official serial version ID which says cryptically
41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // which version we're compatible with
41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static final long serialVersionUID = 4774881970558875024L;
41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // the internal serial version which says which version was written
41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // - 0 (default) for version up to JDK 1.1.3
41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // - 1 for version from JDK 1.1.4, which includes a new field
41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    static final int currentSerialVersion = 1;
41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The version of the serialized data on the stream.  Possible values:
42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <ul>
42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <li><b>0</b> or not present on stream: JDK 1.1.3.  This version
42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * has no <code>defaultCenturyStart</code> on stream.
42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <li><b>1</b> JDK 1.1.4 or later.  This version adds
42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>defaultCenturyStart</code>.
42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * </ul>
42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * When streaming out this class, the most recent format
42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * and the highest allowable <code>serialVersionOnStream</code>
43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * is written.
43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @serial
43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since JDK1.1.4
43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private int serialVersionOnStream = currentSerialVersion;
43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The pattern string of this formatter.  This is always a non-localized
43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * pattern.  May not be null.  See class documentation for details.
43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @serial
44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private String pattern;
44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Saved numberFormat and pattern.
44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see SimpleDateFormat#checkNegativeNumberExpression
44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    transient private NumberFormat originalNumberFormat;
44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    transient private String originalNumberPattern;
44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The minus sign to be used with format and parse.
45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    transient private char minusSign = '-';
45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * True when a negative sign follows a number.
45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * (True as default in Arabic.)
45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    transient private boolean hasFollowingMinusSign = false;
46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The compiled pattern.
46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    transient private char[] compiledPattern;
46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Tags for the compiled pattern.
46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final static int TAG_QUOTE_ASCII_CHAR       = 100;
47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final static int TAG_QUOTE_CHARS            = 101;
47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Locale dependent digit zero.
47451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see #zeroPaddingNumber
47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see java.text.DecimalFormatSymbols#getZeroDigit
47651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
47751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    transient private char zeroDigit;
47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The symbols used by this formatter for week names, month names,
48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * etc.  May not be null.
48251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @serial
48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see java.text.DateFormatSymbols
48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private DateFormatSymbols formatData;
48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * We map dates with two-digit years into the century starting at
48951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>defaultCenturyStart</code>, which may be any date.  May
49051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * not be null.
49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @serial
49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since JDK1.1.4
49351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Date defaultCenturyStart;
49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
49651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    transient private int defaultCenturyStartYear;
49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final int MILLIS_PER_MINUTE = 60 * 1000;
49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // For time zones that have no names, use strings GMT+minutes and
50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // GMT-minutes. For instance, in France the time zone is GMT+60.
50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final String GMT = "GMT";
50351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
50451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
50551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Cache NumberFormat instances with Locale key.
50651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
50751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final ConcurrentMap<Locale, NumberFormat> cachedNumberFormatData
50851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        = new ConcurrentHashMap<Locale, NumberFormat>(3);
50951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
51051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
51151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The Locale used to instantiate this
51251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>SimpleDateFormat</code>. The value may be null if this object
51351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * has been created by an older <code>SimpleDateFormat</code> and
51451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * deserialized.
51551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
51651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @serial
51751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.6
51851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
51951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private Locale locale;
52051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
52151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
52251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Indicates whether this <code>SimpleDateFormat</code> should use
52351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the DateFormatSymbols. If true, the format and parse methods
52451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * use the DateFormatSymbols values. If false, the format and
52551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * parse methods call Calendar.getDisplayName or
52651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Calendar.getDisplayNames.
52751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
52851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    transient boolean useDateFormatSymbols;
52951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
53051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
53151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Constructs a <code>SimpleDateFormat</code> using the default pattern and
53251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * date format symbols for the default locale.
53351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <b>Note:</b> This constructor may not support all locales.
53451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * For full coverage, use the factory methods in the {@link DateFormat}
53551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * class.
53651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
53751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public SimpleDateFormat() {
53851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this(SHORT, SHORT, Locale.getDefault(Locale.Category.FORMAT));
53951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
54051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
54151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
54251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Constructs a <code>SimpleDateFormat</code> using the given pattern and
54351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the default date format symbols for the default locale.
54451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <b>Note:</b> This constructor may not support all locales.
54551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * For full coverage, use the factory methods in the {@link DateFormat}
54651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * class.
54751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
54851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param pattern the pattern describing the date and time format
54951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception NullPointerException if the given pattern is null
55051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception IllegalArgumentException if the given pattern is invalid
55151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
55251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public SimpleDateFormat(String pattern)
55351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
55451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this(pattern, Locale.getDefault(Locale.Category.FORMAT));
55551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
55651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
55751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
55851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Constructs a <code>SimpleDateFormat</code> using the given pattern and
55951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the default date format symbols for the given locale.
56051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <b>Note:</b> This constructor may not support all locales.
56151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * For full coverage, use the factory methods in the {@link DateFormat}
56251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * class.
56351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
56451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param pattern the pattern describing the date and time format
56551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param locale the locale whose date format symbols should be used
56651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception NullPointerException if the given pattern or locale is null
56751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception IllegalArgumentException if the given pattern is invalid
56851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
56951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public SimpleDateFormat(String pattern, Locale locale)
57051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
57151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (pattern == null || locale == null) {
57251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException();
57351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
57451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
57551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        initializeCalendar(locale);
57651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.pattern = pattern;
57751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.formatData = DateFormatSymbols.getInstanceRef(locale);
57851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.locale = locale;
57951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        initialize(locale);
58051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
58151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
58251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
58351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Constructs a <code>SimpleDateFormat</code> using the given pattern and
58451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * date format symbols.
58551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
58651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param pattern the pattern describing the date and time format
58751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param formatSymbols the date format symbols to be used for formatting
58851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception NullPointerException if the given pattern or formatSymbols is null
58951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception IllegalArgumentException if the given pattern is invalid
59051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
59151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public SimpleDateFormat(String pattern, DateFormatSymbols formatSymbols)
59251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
59351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (pattern == null || formatSymbols == null) {
59451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException();
59551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
59651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
59751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.pattern = pattern;
59851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.formatData = (DateFormatSymbols) formatSymbols.clone();
59951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.locale = Locale.getDefault(Locale.Category.FORMAT);
60051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        initializeCalendar(this.locale);
60151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        initialize(this.locale);
60251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        useDateFormatSymbols = true;
60351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
60451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
60551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /* Package-private, called by DateFormat factory methods */
60651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    SimpleDateFormat(int timeStyle, int dateStyle, Locale loc) {
60751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (loc == null) {
60851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException();
60951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
61051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
61151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.locale = loc;
61251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // initialize calendar and related fields
61351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        initializeCalendar(loc);
61451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
61551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        formatData = DateFormatSymbols.getInstanceRef(loc);
6166fdc0bf198c455cbe73ecf825bd0f8f985481066Neil Fuller        LocaleData localeData = LocaleData.get(loc);
61751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if ((timeStyle >= 0) && (dateStyle >= 0)) {
6186fdc0bf198c455cbe73ecf825bd0f8f985481066Neil Fuller            Object[] dateTimeArgs = {
6196fdc0bf198c455cbe73ecf825bd0f8f985481066Neil Fuller                localeData.getDateFormat(dateStyle),
6206fdc0bf198c455cbe73ecf825bd0f8f985481066Neil Fuller                localeData.getTimeFormat(timeStyle),
6216fdc0bf198c455cbe73ecf825bd0f8f985481066Neil Fuller            };
6226fdc0bf198c455cbe73ecf825bd0f8f985481066Neil Fuller            pattern = MessageFormat.format("{0} {1}", dateTimeArgs);
62351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
62451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        else if (timeStyle >= 0) {
6256fdc0bf198c455cbe73ecf825bd0f8f985481066Neil Fuller            pattern = localeData.getTimeFormat(timeStyle);
62651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
62751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        else if (dateStyle >= 0) {
6286fdc0bf198c455cbe73ecf825bd0f8f985481066Neil Fuller            pattern = localeData.getDateFormat(dateStyle);
62951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
63051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        else {
63151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IllegalArgumentException("No date or time style specified");
63251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
63351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
63451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        initialize(loc);
63551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
63651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
63751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /* Initialize compiledPattern and numberFormat fields */
63851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void initialize(Locale loc) {
63951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Verify and compile the given pattern.
64051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        compiledPattern = compile(pattern);
64151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
64251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /* try the cache first */
64351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        numberFormat = cachedNumberFormatData.get(loc);
64451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (numberFormat == null) { /* cache miss */
64551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            numberFormat = NumberFormat.getIntegerInstance(loc);
64651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            numberFormat.setGroupingUsed(false);
64751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
64851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            /* update cache */
64951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            cachedNumberFormatData.putIfAbsent(loc, numberFormat);
65051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
65151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        numberFormat = (NumberFormat) numberFormat.clone();
65251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
65351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        initializeDefaultCentury();
65451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
65551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
65651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void initializeCalendar(Locale loc) {
65751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (calendar == null) {
65851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            assert loc != null;
65951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // The format object must be constructed using the symbols for this zone.
66051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // However, the calendar should use the current default TimeZone.
66151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // If this is not contained in the locale zone strings, then the zone
66251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // will be formatted using generic GMT+/-H:MM nomenclature.
66351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            calendar = Calendar.getInstance(TimeZone.getDefault(), loc);
66451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
66551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
66651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
66751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
66851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns the compiled form of the given pattern. The syntax of
66951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the compiled pattern is:
67051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <blockquote>
67151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * CompiledPattern:
67251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     EntryList
67351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * EntryList:
67451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     Entry
67551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     EntryList Entry
67651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Entry:
67751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     TagField
67851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     TagField data
67951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * TagField:
68051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     Tag Length
68151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     TaggedData
68251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Tag:
68351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     pattern_char_index
68451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     TAG_QUOTE_CHARS
68551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Length:
68651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     short_length
68751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     long_length
68851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * TaggedData:
68951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     TAG_QUOTE_ASCII_CHAR ascii_char
69051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
69151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * </blockquote>
69251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
69351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * where `short_length' is an 8-bit unsigned integer between 0 and
69451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * 254.  `long_length' is a sequence of an 8-bit integer 255 and a
69551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * 32-bit signed integer value which is split into upper and lower
69651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * 16-bit fields in two char's. `pattern_char_index' is an 8-bit
69751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * integer between 0 and 18. `ascii_char' is an 7-bit ASCII
69851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * character value. `data' depends on its Tag value.
69951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
70051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If Length is short_length, Tag and short_length are packed in a
70151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * single char, as illustrated below.
70251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <blockquote>
70351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     char[0] = (Tag << 8) | short_length;
70451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * </blockquote>
70551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
70651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If Length is long_length, Tag and 255 are packed in the first
70751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * char and a 32-bit integer, as illustrated below.
70851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <blockquote>
70951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     char[0] = (Tag << 8) | 255;
71051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     char[1] = (char) (long_length >>> 16);
71151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *     char[2] = (char) (long_length & 0xffff);
71251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * </blockquote>
71351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
71451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If Tag is a pattern_char_index, its Length is the number of
71551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * pattern characters. For example, if the given pattern is
71651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * "yyyy", Tag is 1 and Length is 4, followed by no data.
71751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
71851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If Tag is TAG_QUOTE_CHARS, its Length is the number of char's
71951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * following the TagField. For example, if the given pattern is
72051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * "'o''clock'", Length is 7 followed by a char sequence of
72151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>o&nbs;'&nbs;c&nbs;l&nbs;o&nbs;c&nbs;k</code>.
72251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
72351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * TAG_QUOTE_ASCII_CHAR is a special tag and has an ASCII
72451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * character in place of Length. For example, if the given pattern
72551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * is "'o'", the TaggedData entry is
72651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>((TAG_QUOTE_ASCII_CHAR&nbs;<<&nbs;8)&nbs;|&nbs;'o')</code>.
72751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
72851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception NullPointerException if the given pattern is null
72951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception IllegalArgumentException if the given pattern is invalid
73051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
73151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private char[] compile(String pattern) {
73251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int length = pattern.length();
73351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean inQuote = false;
73451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        StringBuilder compiledPattern = new StringBuilder(length * 2);
73551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        StringBuilder tmpBuffer = null;
73651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int count = 0;
73751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int lastTag = -1;
73851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
73951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 0; i < length; i++) {
74051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            char c = pattern.charAt(i);
74151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
74251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (c == '\'') {
74351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // '' is treated as a single quote regardless of being
74451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // in a quoted section.
74551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if ((i + 1) < length) {
74651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    c = pattern.charAt(i + 1);
74751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (c == '\'') {
74851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        i++;
74951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (count != 0) {
75051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            encode(lastTag, count, compiledPattern);
75151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            lastTag = -1;
75251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            count = 0;
75351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
75451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (inQuote) {
75551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            tmpBuffer.append(c);
75651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        } else {
75751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            compiledPattern.append((char)(TAG_QUOTE_ASCII_CHAR << 8 | c));
75851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
75951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        continue;
76051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
76151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
76251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!inQuote) {
76351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (count != 0) {
76451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        encode(lastTag, count, compiledPattern);
76551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        lastTag = -1;
76651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        count = 0;
76751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
76851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (tmpBuffer == null) {
76951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        tmpBuffer = new StringBuilder(length);
77051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } else {
77151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        tmpBuffer.setLength(0);
77251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
77351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    inQuote = true;
77451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
77551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int len = tmpBuffer.length();
77651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (len == 1) {
77751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        char ch = tmpBuffer.charAt(0);
77851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (ch < 128) {
77951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            compiledPattern.append((char)(TAG_QUOTE_ASCII_CHAR << 8 | ch));
78051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        } else {
78151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            compiledPattern.append((char)(TAG_QUOTE_CHARS << 8 | 1));
78251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            compiledPattern.append(ch);
78351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
78451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } else {
78551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        encode(TAG_QUOTE_CHARS, len, compiledPattern);
78651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        compiledPattern.append(tmpBuffer);
78751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
78851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    inQuote = false;
78951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
79051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                continue;
79151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
79251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (inQuote) {
79351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                tmpBuffer.append(c);
79451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                continue;
79551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
79651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) {
79751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (count != 0) {
79851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    encode(lastTag, count, compiledPattern);
79951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    lastTag = -1;
80051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    count = 0;
80151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
80251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (c < 128) {
80351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // In most cases, c would be a delimiter, such as ':'.
80451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    compiledPattern.append((char)(TAG_QUOTE_ASCII_CHAR << 8 | c));
80551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
80651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // Take any contiguous non-ASCII alphabet characters and
80751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // put them in a single TAG_QUOTE_CHARS.
80851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int j;
80951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    for (j = i + 1; j < length; j++) {
81051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        char d = pattern.charAt(j);
81151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (d == '\'' || (d >= 'a' && d <= 'z' || d >= 'A' && d <= 'Z')) {
81251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            break;
81351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
81451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
81551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    compiledPattern.append((char)(TAG_QUOTE_CHARS << 8 | (j - i)));
81651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    for (; i < j; i++) {
81751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        compiledPattern.append(pattern.charAt(i));
81851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
81951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    i--;
82051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
82151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                continue;
82251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
82351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
82451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int tag;
82551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if ((tag = DateFormatSymbols.patternChars.indexOf(c)) == -1) {
82651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new IllegalArgumentException("Illegal pattern character " +
82751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                                   "'" + c + "'");
82851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
82951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (lastTag == -1 || lastTag == tag) {
83051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                lastTag = tag;
83151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                count++;
83251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                continue;
83351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
83451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            encode(lastTag, count, compiledPattern);
83551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            lastTag = tag;
83651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            count = 1;
83751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
83851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
83951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (inQuote) {
84051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IllegalArgumentException("Unterminated quote");
84151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
84251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
84351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (count != 0) {
84451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            encode(lastTag, count, compiledPattern);
84551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
84651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
84751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Copy the compiled pattern to a char array
84851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int len = compiledPattern.length();
84951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        char[] r = new char[len];
85051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        compiledPattern.getChars(0, len, r, 0);
85151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return r;
85251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
85351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
85451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
85551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Encodes the given tag and length and puts encoded char(s) into buffer.
85651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
85751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final void encode(int tag, int length, StringBuilder buffer) {
85851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (tag == PATTERN_ISO_ZONE && length >= 4) {
85951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IllegalArgumentException("invalid ISO 8601 format: length=" + length);
86051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
86151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (length < 255) {
86251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            buffer.append((char)(tag << 8 | length));
86351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
86451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            buffer.append((char)((tag << 8) | 0xff));
86551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            buffer.append((char)(length >>> 16));
86651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            buffer.append((char)(length & 0xffff));
86751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
86851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
86951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
87051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /* Initialize the fields we use to disambiguate ambiguous years. Separate
87151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * so we can call it from readObject().
87251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
87351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void initializeDefaultCentury() {
87451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        calendar.setTimeInMillis(System.currentTimeMillis());
87551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        calendar.add( Calendar.YEAR, -80 );
87651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        parseAmbiguousDatesAsAfter(calendar.getTime());
87751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
87851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
87951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /* Define one-century window into which to disambiguate dates using
88051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * two-digit years.
88151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
88251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void parseAmbiguousDatesAsAfter(Date startDate) {
88351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        defaultCenturyStart = startDate;
88451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        calendar.setTime(startDate);
88551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        defaultCenturyStartYear = calendar.get(Calendar.YEAR);
88651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
88751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
88851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
88951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Sets the 100-year period 2-digit years will be interpreted as being in
89051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * to begin on the date the user specifies.
89151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
89251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param startDate During parsing, two digit years will be placed in the range
89351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>startDate</code> to <code>startDate + 100 years</code>.
89451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see #get2DigitYearStart
89551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.2
89651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
89751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void set2DigitYearStart(Date startDate) {
89851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        parseAmbiguousDatesAsAfter(new Date(startDate.getTime()));
89951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
90051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
90151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
90251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns the beginning date of the 100-year period 2-digit years are interpreted
90351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * as being within.
90451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
90551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the start of the 100-year period into which two digit years are
90651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * parsed
90751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see #set2DigitYearStart
90851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.2
90951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
91051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public Date get2DigitYearStart() {
91151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (Date) defaultCenturyStart.clone();
91251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
91351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
91451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
91551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Formats the given <code>Date</code> into a date/time string and appends
91651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the result to the given <code>StringBuffer</code>.
91751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
91851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param date the date-time value to be formatted into a date-time string.
91951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param toAppendTo where the new date-time text is to be appended.
92051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param pos the formatting position. On input: an alignment field,
92151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * if desired. On output: the offsets of the alignment field.
92251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the formatted date-time string.
92351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception NullPointerException if the given {@code date} is {@code null}.
92451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
92551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public StringBuffer format(Date date, StringBuffer toAppendTo,
92651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                               FieldPosition pos)
92751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
92851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        pos.beginIndex = pos.endIndex = 0;
92951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return format(date, toAppendTo, pos.getFieldDelegate());
93051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
93151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
93251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Called from Format after creating a FieldDelegate
93351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private StringBuffer format(Date date, StringBuffer toAppendTo,
93451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                FieldDelegate delegate) {
93551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Convert input date to time field list
93651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        calendar.setTime(date);
93751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
93851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean useDateFormatSymbols = useDateFormatSymbols();
93951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
94051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 0; i < compiledPattern.length; ) {
94151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int tag = compiledPattern[i] >>> 8;
94251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int count = compiledPattern[i++] & 0xff;
94351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (count == 255) {
94451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                count = compiledPattern[i++] << 16;
94551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                count |= compiledPattern[i++];
94651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
94751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
94851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            switch (tag) {
94951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case TAG_QUOTE_ASCII_CHAR:
95051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                toAppendTo.append((char)count);
95151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break;
95251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
95351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case TAG_QUOTE_CHARS:
95451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                toAppendTo.append(compiledPattern, i, count);
95551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                i += count;
95651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break;
95751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
95851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            default:
95951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                subFormat(tag, count, delegate, toAppendTo, useDateFormatSymbols);
96051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break;
96151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
96251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
96351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return toAppendTo;
96451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
96551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
96651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
96751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Formats an Object producing an <code>AttributedCharacterIterator</code>.
96851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * You can use the returned <code>AttributedCharacterIterator</code>
96951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * to build the resulting String, as well as to determine information
97051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * about the resulting String.
97151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
97251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Each attribute key of the AttributedCharacterIterator will be of type
97351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>DateFormat.Field</code>, with the corresponding attribute value
97451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * being the same as the attribute key.
97551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
97651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception NullPointerException if obj is null.
97751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception IllegalArgumentException if the Format cannot format the
97851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *            given object, or if the Format's pattern string is invalid.
97951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param obj The object to format
98051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return AttributedCharacterIterator describing the formatted value.
98151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since 1.4
98251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
98351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public AttributedCharacterIterator formatToCharacterIterator(Object obj) {
98451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        StringBuffer sb = new StringBuffer();
98551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        CharacterIteratorFieldDelegate delegate = new
98651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         CharacterIteratorFieldDelegate();
98751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
98851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (obj instanceof Date) {
98951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            format((Date)obj, sb, delegate);
99051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
99151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        else if (obj instanceof Number) {
99251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            format(new Date(((Number)obj).longValue()), sb, delegate);
99351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
99451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        else if (obj == null) {
99551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new NullPointerException(
99651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                   "formatToCharacterIterator must be passed non-null object");
99751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
99851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        else {
99951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IllegalArgumentException(
100051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                             "Cannot format given Object as a Date");
100151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
100251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return delegate.getIterator(sb.toString());
100351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
100451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
100551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Map index into pattern character string to Calendar field number
100651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final int[] PATTERN_INDEX_TO_CALENDAR_FIELD =
100751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
100851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Calendar.ERA, Calendar.YEAR, Calendar.MONTH, Calendar.DATE,
100951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Calendar.HOUR_OF_DAY, Calendar.HOUR_OF_DAY, Calendar.MINUTE,
101051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Calendar.SECOND, Calendar.MILLISECOND, Calendar.DAY_OF_WEEK,
101151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Calendar.DAY_OF_YEAR, Calendar.DAY_OF_WEEK_IN_MONTH,
101251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Calendar.WEEK_OF_YEAR, Calendar.WEEK_OF_MONTH,
101351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Calendar.AM_PM, Calendar.HOUR, Calendar.HOUR, Calendar.ZONE_OFFSET,
101451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Calendar.ZONE_OFFSET,
101551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Pseudo Calendar fields
101651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        CalendarBuilder.WEEK_YEAR,
101751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        CalendarBuilder.ISO_DAY_OF_WEEK,
1018b7554f779d330037a5cf591fcc8be73db73a0384Narayan Kamath        Calendar.ZONE_OFFSET,
1019b7554f779d330037a5cf591fcc8be73db73a0384Narayan Kamath        // 'L' and 'c',
1020b7554f779d330037a5cf591fcc8be73db73a0384Narayan Kamath        Calendar.MONTH,
1021b7554f779d330037a5cf591fcc8be73db73a0384Narayan Kamath        Calendar.DAY_OF_WEEK
102251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    };
102351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
102451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Map index into pattern character string to DateFormat field number
102551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final int[] PATTERN_INDEX_TO_DATE_FORMAT_FIELD = {
102651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        DateFormat.ERA_FIELD, DateFormat.YEAR_FIELD, DateFormat.MONTH_FIELD,
102751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        DateFormat.DATE_FIELD, DateFormat.HOUR_OF_DAY1_FIELD,
102851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        DateFormat.HOUR_OF_DAY0_FIELD, DateFormat.MINUTE_FIELD,
102951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        DateFormat.SECOND_FIELD, DateFormat.MILLISECOND_FIELD,
103051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        DateFormat.DAY_OF_WEEK_FIELD, DateFormat.DAY_OF_YEAR_FIELD,
103151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD, DateFormat.WEEK_OF_YEAR_FIELD,
103251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        DateFormat.WEEK_OF_MONTH_FIELD, DateFormat.AM_PM_FIELD,
103351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        DateFormat.HOUR1_FIELD, DateFormat.HOUR0_FIELD,
103451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        DateFormat.TIMEZONE_FIELD, DateFormat.TIMEZONE_FIELD,
103551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        DateFormat.YEAR_FIELD, DateFormat.DAY_OF_WEEK_FIELD,
1036b7554f779d330037a5cf591fcc8be73db73a0384Narayan Kamath        DateFormat.TIMEZONE_FIELD,
1037b7554f779d330037a5cf591fcc8be73db73a0384Narayan Kamath        // 'L' and 'c'
1038b7554f779d330037a5cf591fcc8be73db73a0384Narayan Kamath        DateFormat.MONTH_FIELD,
1039b7554f779d330037a5cf591fcc8be73db73a0384Narayan Kamath        DateFormat.DAY_OF_WEEK_FIELD
104051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    };
104151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
104251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    // Maps from DecimalFormatSymbols index to Field constant
104351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final Field[] PATTERN_INDEX_TO_DATE_FORMAT_FIELD_ID = {
104451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Field.ERA, Field.YEAR, Field.MONTH, Field.DAY_OF_MONTH,
104551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Field.HOUR_OF_DAY1, Field.HOUR_OF_DAY0, Field.MINUTE,
104651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Field.SECOND, Field.MILLISECOND, Field.DAY_OF_WEEK,
104751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Field.DAY_OF_YEAR, Field.DAY_OF_WEEK_IN_MONTH,
104851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Field.WEEK_OF_YEAR, Field.WEEK_OF_MONTH,
104951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Field.AM_PM, Field.HOUR1, Field.HOUR0, Field.TIME_ZONE,
105051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Field.TIME_ZONE,
105151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Field.YEAR, Field.DAY_OF_WEEK,
1052b7554f779d330037a5cf591fcc8be73db73a0384Narayan Kamath        Field.TIME_ZONE,
1053b7554f779d330037a5cf591fcc8be73db73a0384Narayan Kamath        // 'L' and 'c'
1054b7554f779d330037a5cf591fcc8be73db73a0384Narayan Kamath        Field.MONTH,
1055b7554f779d330037a5cf591fcc8be73db73a0384Narayan Kamath        Field.DAY_OF_WEEK
105651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    };
105751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
105851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
105951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Private member function that does the real date/time formatting.
106051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
106151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void subFormat(int patternCharIndex, int count,
106251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                           FieldDelegate delegate, StringBuffer buffer,
106351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                           boolean useDateFormatSymbols)
106451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
106551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int     maxIntCount = Integer.MAX_VALUE;
106651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String  current = null;
106751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int     beginOffset = buffer.length();
106851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
106951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex];
107051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int value;
107151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (field == CalendarBuilder.WEEK_YEAR) {
107251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (calendar.isWeekDateSupported()) {
107351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                value = calendar.getWeekYear();
107451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
107551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // use calendar year 'y' instead
107651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                patternCharIndex = PATTERN_YEAR;
107751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex];
107851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                value = calendar.get(field);
107951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
108051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (field == CalendarBuilder.ISO_DAY_OF_WEEK) {
108151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            value = CalendarBuilder.toISODayOfWeek(calendar.get(Calendar.DAY_OF_WEEK));
108251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
108351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            value = calendar.get(field);
108451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
108551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
108651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int style = (count >= 4) ? Calendar.LONG : Calendar.SHORT;
108751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!useDateFormatSymbols && field != CalendarBuilder.ISO_DAY_OF_WEEK) {
108851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            current = calendar.getDisplayName(field, style, locale);
108951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
109051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
109151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Note: zeroPaddingNumber() assumes that maxDigits is either
109251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // 2 or maxIntCount. If we make any changes to this,
109351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // zeroPaddingNumber() must be fixed.
109451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
109551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        switch (patternCharIndex) {
109651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        case PATTERN_ERA: // 'G'
109751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (useDateFormatSymbols) {
109851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                String[] eras = formatData.getEras();
109951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (value < eras.length)
110051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    current = eras[value];
110151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
110251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (current == null)
110351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                current = "";
110451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            break;
110551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
110651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        case PATTERN_WEEK_YEAR: // 'Y'
110751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        case PATTERN_YEAR:      // 'y'
110851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (calendar instanceof GregorianCalendar) {
110951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (count != 2)
111051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    zeroPaddingNumber(value, count, maxIntCount, buffer);
111151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                else // count == 2
111251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    zeroPaddingNumber(value, 2, 2, buffer); // clip 1996 to 96
111351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
111451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (current == null) {
111551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    zeroPaddingNumber(value, style == Calendar.LONG ? 1 : count,
111651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                      maxIntCount, buffer);
111751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
111851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
111951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            break;
112051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
1121d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        case PATTERN_STANDALONE_MONTH: // 'L'
1122d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        {
1123d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            current = formatMonth(count, value, maxIntCount, buffer, useDateFormatSymbols,
1124d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                    true /* standalone */);
1125d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            break;
1126d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        }
1127d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath
112851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        case PATTERN_MONTH: // 'M'
1129d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        {
1130d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            current = formatMonth(count, value, maxIntCount, buffer, useDateFormatSymbols,
1131d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                    false /* standalone */);
113251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            break;
1133d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        }
113451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
113551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        case PATTERN_HOUR_OF_DAY1: // 'k' 1-based.  eg, 23:59 + 1 hour =>> 24:59
113651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (current == null) {
113751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (value == 0)
113851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    zeroPaddingNumber(calendar.getMaximum(Calendar.HOUR_OF_DAY)+1,
113951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                      count, maxIntCount, buffer);
114051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                else
114151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    zeroPaddingNumber(value, count, maxIntCount, buffer);
114251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
114351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            break;
114451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
1145d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        case PATTERN_STANDALONE_DAY_OF_WEEK: // 'c'
1146d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        {
1147d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            current = formatWeekday(count, value, useDateFormatSymbols, true /* standalone */);
1148d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            break;
1149d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        }
1150d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath
115151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        case PATTERN_DAY_OF_WEEK: // 'E'
1152d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        {
1153d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            current = formatWeekday(count, value, useDateFormatSymbols, false /* standalone */);
115451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            break;
1155d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        }
115651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
115751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        case PATTERN_AM_PM:    // 'a'
115851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (useDateFormatSymbols) {
115951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                String[] ampm = formatData.getAmPmStrings();
116051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                current = ampm[value];
116151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
116251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            break;
116351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
116451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        case PATTERN_HOUR1:    // 'h' 1-based.  eg, 11PM + 1 hour =>> 12 AM
116551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (current == null) {
116651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (value == 0)
116751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    zeroPaddingNumber(calendar.getLeastMaximum(Calendar.HOUR)+1,
116851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                      count, maxIntCount, buffer);
116951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                else
117051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    zeroPaddingNumber(value, count, maxIntCount, buffer);
117151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
117251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            break;
117351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
117451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        case PATTERN_ZONE_NAME: // 'z'
117551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (current == null) {
11769c853c5b9ebbb0ef60a013ae10ee411d70dfa832Piotr Jastrzebski                TimeZone tz = calendar.getTimeZone();
11779c853c5b9ebbb0ef60a013ae10ee411d70dfa832Piotr Jastrzebski                boolean daylight = (calendar.get(Calendar.DST_OFFSET) != 0);
11789c853c5b9ebbb0ef60a013ae10ee411d70dfa832Piotr Jastrzebski                int tzstyle = count < 4 ? TimeZone.SHORT : TimeZone.LONG;
1179cdde6627c3b5fe67e086043cb789e88110a38028Joachim Sauer                String zoneString;
1180cdde6627c3b5fe67e086043cb789e88110a38028Joachim Sauer                if (formatData.isZoneStringsSet) {
1181cdde6627c3b5fe67e086043cb789e88110a38028Joachim Sauer                    zoneString = TimeZoneNames.getDisplayName(
1182cdde6627c3b5fe67e086043cb789e88110a38028Joachim Sauer                            formatData.getZoneStringsWrapper(), tz.getID(), daylight, tzstyle);
1183cdde6627c3b5fe67e086043cb789e88110a38028Joachim Sauer                } else {
1184cdde6627c3b5fe67e086043cb789e88110a38028Joachim Sauer                    zoneString = tz.getDisplayName(daylight, tzstyle, formatData.locale);
1185cdde6627c3b5fe67e086043cb789e88110a38028Joachim Sauer                }
11869c853c5b9ebbb0ef60a013ae10ee411d70dfa832Piotr Jastrzebski                if (zoneString != null) {
11879c853c5b9ebbb0ef60a013ae10ee411d70dfa832Piotr Jastrzebski                    buffer.append(zoneString);
118851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
11899c853c5b9ebbb0ef60a013ae10ee411d70dfa832Piotr Jastrzebski                    int offsetMillis = calendar.get(Calendar.ZONE_OFFSET) +
11909c853c5b9ebbb0ef60a013ae10ee411d70dfa832Piotr Jastrzebski                        calendar.get(Calendar.DST_OFFSET);
11919c853c5b9ebbb0ef60a013ae10ee411d70dfa832Piotr Jastrzebski                    buffer.append(TimeZone.createGmtOffsetString(true, true, offsetMillis));
119251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
119351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
119451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            break;
119551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
119651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        case PATTERN_ZONE_VALUE: // 'Z' ("-/+hhmm" form)
1197d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        {
1198d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            value = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET);
1199d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            final boolean includeSeparator = (count >= 4);
1200d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            final boolean includeGmt = (count == 4);
1201d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            buffer.append(TimeZone.createGmtOffsetString(includeGmt, includeSeparator, value));
120251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
120351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            break;
1204d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        }
120551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
120651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        case PATTERN_ISO_ZONE:   // 'X'
120751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            value = calendar.get(Calendar.ZONE_OFFSET)
120851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    + calendar.get(Calendar.DST_OFFSET);
120951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
121051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (value == 0) {
121151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                buffer.append('Z');
121251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break;
121351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
121451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
121551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            value /=  60000;
121651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (value >= 0) {
121751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                buffer.append('+');
121851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
121951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                buffer.append('-');
122051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                value = -value;
122151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
122251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
122351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            CalendarUtils.sprintf0d(buffer, value / 60, 2);
122451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (count == 1) {
122551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break;
122651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
122751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
122851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (count == 3) {
122951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                buffer.append(':');
123051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
123151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            CalendarUtils.sprintf0d(buffer, value % 60, 2);
123251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            break;
1233afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath        case PATTERN_MILLISECOND: // 'S'
1234afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath            // Fractional seconds must be treated specially. We must always convert the parsed
1235afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath            // value into a fractional second [0, 1) and then widen it out to the appropriate
1236afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath            // formatted size. For example, an initial value of 789 will be converted
1237afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath            // 0.789 and then become ".7" (S) or ".78" (SS) or "0.789" (SSS) or "0.7890" (SSSS)
1238afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath            // in the resulting formatted output.
1239afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath            if (current == null) {
1240afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath                value = (int) (((double) value / 1000) * Math.pow(10, count));
1241afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath                zeroPaddingNumber(value, count, count, buffer);
1242afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath            }
1243afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath            break;
124451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
124551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        default:
124651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     // case PATTERN_DAY_OF_MONTH:         // 'd'
124751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     // case PATTERN_HOUR_OF_DAY0:         // 'H' 0-based.  eg, 23:59 + 1 hour =>> 00:59
124851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     // case PATTERN_MINUTE:               // 'm'
124951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     // case PATTERN_SECOND:               // 's'
125051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     // case PATTERN_DAY_OF_YEAR:          // 'D'
125151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     // case PATTERN_DAY_OF_WEEK_IN_MONTH: // 'F'
125251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     // case PATTERN_WEEK_OF_YEAR:         // 'w'
125351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     // case PATTERN_WEEK_OF_MONTH:        // 'W'
125451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     // case PATTERN_HOUR0:                // 'K' eg, 11PM + 1 hour =>> 0 AM
125551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     // case PATTERN_ISO_DAY_OF_WEEK:      // 'u' pseudo field, Monday = 1, ..., Sunday = 7
125651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (current == null) {
125751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                zeroPaddingNumber(value, count, maxIntCount, buffer);
125851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
125951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            break;
126051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } // switch (patternCharIndex)
126151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
126251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (current != null) {
126351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            buffer.append(current);
126451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
126551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
126651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int fieldID = PATTERN_INDEX_TO_DATE_FORMAT_FIELD[patternCharIndex];
126751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Field f = PATTERN_INDEX_TO_DATE_FORMAT_FIELD_ID[patternCharIndex];
126851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
126951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        delegate.formatted(fieldID, f, f, beginOffset, buffer.length(), buffer);
127051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
127151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
1272d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath    private String formatWeekday(int count, int value, boolean useDateFormatSymbols,
1273d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                                 boolean standalone) {
1274d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        if (useDateFormatSymbols) {
1275d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            final String[] weekdays;
1276d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            if (count == 4) {
1277d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                weekdays = standalone ? formatData.getStandAloneWeekdays() : formatData.getWeekdays();
1278d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            } else if (count == 5) {
1279d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                weekdays =
1280d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                        standalone ? formatData.getTinyStandAloneWeekdays() : formatData.getTinyWeekdays();
1281d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath
1282d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            } else { // count < 4, use abbreviated form if exists
1283d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                weekdays = standalone ? formatData.getShortStandAloneWeekdays() : formatData.getShortWeekdays();
1284d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            }
1285d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath
1286d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            return weekdays[value];
1287d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        }
1288d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath
1289d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        return null;
1290d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath    }
1291d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath
1292d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath    private String formatMonth(int count, int value, int maxIntCount, StringBuffer buffer,
1293d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                               boolean useDateFormatSymbols, boolean standalone) {
1294d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        String current = null;
1295d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        if (useDateFormatSymbols) {
1296d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            final String[] months;
1297d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            if (count == 4) {
1298d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                months = standalone ? formatData.getStandAloneMonths() : formatData.getMonths();
1299d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            } else if (count == 5) {
1300d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                months = standalone ? formatData.getTinyStandAloneMonths() : formatData.getTinyMonths();
1301d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            } else if (count == 3) {
1302d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                months = standalone ? formatData.getShortStandAloneMonths() : formatData.getShortMonths();
1303d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            } else {
1304d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                months = null;
1305d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            }
1306d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath
1307d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            if (months != null) {
1308d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                current = months[value];
1309d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            }
1310d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        } else {
1311d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            if (count < 3) {
1312d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                current = null;
1313d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            }
1314d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        }
1315d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath
1316d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        if (current == null) {
1317d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            zeroPaddingNumber(value+1, count, maxIntCount, buffer);
1318d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        }
1319d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath
1320d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        return current;
1321d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath    }
1322d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath
132351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
132451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Formats a number with the specified minimum and maximum number of digits.
132551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
132651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final void zeroPaddingNumber(int value, int minDigits, int maxDigits, StringBuffer buffer)
132751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
132851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Optimization for 1, 2 and 4 digit numbers. This should
132951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // cover most cases of formatting date/time related items.
133051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Note: This optimization code assumes that maxDigits is
133151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // either 2 or Integer.MAX_VALUE (maxIntCount in format()).
133251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
133351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (zeroDigit == 0) {
133451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                zeroDigit = ((DecimalFormat)numberFormat).getDecimalFormatSymbols().getZeroDigit();
133551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
133651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (value >= 0) {
133751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (value < 100 && minDigits >= 1 && minDigits <= 2) {
133851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (value < 10) {
133951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (minDigits == 2) {
134051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            buffer.append(zeroDigit);
134151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
134251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        buffer.append((char)(zeroDigit + value));
134351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } else {
134451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        buffer.append((char)(zeroDigit + value / 10));
134551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        buffer.append((char)(zeroDigit + value % 10));
134651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
134751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return;
134851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else if (value >= 1000 && value < 10000) {
134951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (minDigits == 4) {
135051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        buffer.append((char)(zeroDigit + value / 1000));
135151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        value %= 1000;
135251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        buffer.append((char)(zeroDigit + value / 100));
135351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        value %= 100;
135451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        buffer.append((char)(zeroDigit + value / 10));
135551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        buffer.append((char)(zeroDigit + value % 10));
135651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return;
135751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
135851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (minDigits == 2 && maxDigits == 2) {
135951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        zeroPaddingNumber(value % 100, 2, 2, buffer);
136051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return;
136151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
136251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
136351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
136451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
136551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
136651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
136751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        numberFormat.setMinimumIntegerDigits(minDigits);
136851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        numberFormat.setMaximumIntegerDigits(maxDigits);
136951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        numberFormat.format((long)value, buffer, DontCareFieldPosition.INSTANCE);
137051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
137151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
137251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
137351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
137451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Parses text from a string to produce a <code>Date</code>.
137551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
137651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The method attempts to parse text starting at the index given by
137751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>pos</code>.
137851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If parsing succeeds, then the index of <code>pos</code> is updated
137951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * to the index after the last character used (parsing does not necessarily
138051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * use all characters up to the end of the string), and the parsed
138151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * date is returned. The updated <code>pos</code> can be used to
138251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * indicate the starting point for the next call to this method.
138351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If an error occurs, then the index of <code>pos</code> is not
138451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * changed, the error index of <code>pos</code> is set to the index of
138551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the character where the error occurred, and null is returned.
138651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
138751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>This parsing operation uses the {@link DateFormat#calendar
138851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * calendar} to produce a {@code Date}. All of the {@code
138951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * calendar}'s date-time fields are {@linkplain Calendar#clear()
139051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * cleared} before parsing, and the {@code calendar}'s default
139151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * values of the date-time fields are used for any missing
139251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * date-time information. For example, the year value of the
139351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * parsed {@code Date} is 1970 with {@link GregorianCalendar} if
139451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * no year value is given from the parsing operation.  The {@code
139551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * TimeZone} value may be overwritten, depending on the given
139651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * pattern and the time zone value in {@code text}. Any {@code
139751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * TimeZone} value that has previously been set by a call to
139851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * {@link #setTimeZone(java.util.TimeZone) setTimeZone} may need
139951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * to be restored for further operations.
140051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
140151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param text  A <code>String</code>, part of which should be parsed.
140251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param pos   A <code>ParsePosition</code> object with index and error
140351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *              index information as described above.
140451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return A <code>Date</code> parsed from the string. In case of
140551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *         error, returns null.
140651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception NullPointerException if <code>text</code> or <code>pos</code> is null.
140751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
140808db36e9a34896135e8b0883f65bde5b86ee90e6Narayan Kamath    public Date parse(String text, ParsePosition pos) {
140908db36e9a34896135e8b0883f65bde5b86ee90e6Narayan Kamath        // Make sure the timezone associated with this dateformat instance (set via
141008db36e9a34896135e8b0883f65bde5b86ee90e6Narayan Kamath        // {@code setTimeZone} isn't change as a side-effect of parsing a date.
141108db36e9a34896135e8b0883f65bde5b86ee90e6Narayan Kamath        final TimeZone tz = getTimeZone();
141208db36e9a34896135e8b0883f65bde5b86ee90e6Narayan Kamath        try {
141308db36e9a34896135e8b0883f65bde5b86ee90e6Narayan Kamath            return parseInternal(text, pos);
141408db36e9a34896135e8b0883f65bde5b86ee90e6Narayan Kamath        } finally {
141508db36e9a34896135e8b0883f65bde5b86ee90e6Narayan Kamath            setTimeZone(tz);
141608db36e9a34896135e8b0883f65bde5b86ee90e6Narayan Kamath        }
141708db36e9a34896135e8b0883f65bde5b86ee90e6Narayan Kamath    }
141808db36e9a34896135e8b0883f65bde5b86ee90e6Narayan Kamath
141908db36e9a34896135e8b0883f65bde5b86ee90e6Narayan Kamath    private Date parseInternal(String text, ParsePosition pos)
142051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
142151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        checkNegativeNumberExpression();
142251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
142351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int start = pos.index;
142451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int oldStart = start;
142551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int textLength = text.length();
142651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
142751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean[] ambiguousYear = {false};
142851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
142951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        CalendarBuilder calb = new CalendarBuilder();
143051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
143151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 0; i < compiledPattern.length; ) {
143251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int tag = compiledPattern[i] >>> 8;
143351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int count = compiledPattern[i++] & 0xff;
143451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (count == 255) {
143551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                count = compiledPattern[i++] << 16;
143651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                count |= compiledPattern[i++];
143751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
143851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
143951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            switch (tag) {
144051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case TAG_QUOTE_ASCII_CHAR:
144151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (start >= textLength || text.charAt(start) != (char)count) {
144251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    pos.index = oldStart;
144351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    pos.errorIndex = start;
144451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return null;
144551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
144651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                start++;
144751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break;
144851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
144951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case TAG_QUOTE_CHARS:
145051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                while (count-- > 0) {
145151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (start >= textLength || text.charAt(start) != compiledPattern[i++]) {
145251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        pos.index = oldStart;
145351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        pos.errorIndex = start;
145451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return null;
145551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
145651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    start++;
145751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
145851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break;
145951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
146051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            default:
146151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // Peek the next pattern to determine if we need to
146251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // obey the number of pattern letters for
146351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // parsing. It's required when parsing contiguous
146451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // digit text (e.g., "20010704") with a pattern which
146551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // has no delimiters between fields, like "yyyyMMdd".
146651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                boolean obeyCount = false;
146751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
146851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // In Arabic, a minus sign for a negative number is put after
146951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // the number. Even in another locale, a minus sign can be
147051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // put after a number using DateFormat.setNumberFormat().
147151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // If both the minus sign and the field-delimiter are '-',
147251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // subParse() needs to determine whether a '-' after a number
147351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // in the given text is a delimiter or is a minus sign for the
147451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // preceding number. We give subParse() a clue based on the
147551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // information in compiledPattern.
147651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                boolean useFollowingMinusSignAsDelimiter = false;
147751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
147851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (i < compiledPattern.length) {
147951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int nextTag = compiledPattern[i] >>> 8;
148051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (!(nextTag == TAG_QUOTE_ASCII_CHAR ||
148151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                          nextTag == TAG_QUOTE_CHARS)) {
148251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        obeyCount = true;
148351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
148451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
148551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (hasFollowingMinusSign &&
148651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        (nextTag == TAG_QUOTE_ASCII_CHAR ||
148751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         nextTag == TAG_QUOTE_CHARS)) {
148851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        int c;
148951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (nextTag == TAG_QUOTE_ASCII_CHAR) {
149051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            c = compiledPattern[i] & 0xff;
149151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        } else {
149251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            c = compiledPattern[i+1];
149351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
149451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
149551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (c == minusSign) {
149651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            useFollowingMinusSignAsDelimiter = true;
149751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
149851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
149951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
150051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                start = subParse(text, start, tag, count, obeyCount,
150151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                 ambiguousYear, pos,
150251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                 useFollowingMinusSignAsDelimiter, calb);
150351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (start < 0) {
150451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    pos.index = oldStart;
150551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return null;
150651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
150751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
150851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
150951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
151051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // At this point the fields of Calendar have been set.  Calendar
151151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // will fill in default values for missing fields when the time
151251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // is computed.
151351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
151451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        pos.index = start;
151551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
151651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Date parsedDate;
151751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
151851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            parsedDate = calb.establish(calendar).getTime();
151951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // If the year value is ambiguous,
152051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // then the two-digit year == the default start year
152151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (ambiguousYear[0]) {
152251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (parsedDate.before(defaultCenturyStart)) {
152351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    parsedDate = calb.addYear(100).establish(calendar).getTime();
152451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
152551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
152651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
152751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // An IllegalArgumentException will be thrown by Calendar.getTime()
152851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // if any fields are out of range, e.g., MONTH == 17.
152951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        catch (IllegalArgumentException e) {
153051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            pos.errorIndex = start;
153151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            pos.index = oldStart;
153251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return null;
153351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
153451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
153551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return parsedDate;
153651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
153751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
153851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
153951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Private code-size reduction function used by subParse.
154051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param text the time text being parsed.
154151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param start where to start parsing.
154251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param field the date field being parsed.
154351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param data the string array to parsed.
154451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the new start position if matching succeeded; a negative number
154551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * indicating matching failure, otherwise.
154651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
154751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private int matchString(String text, int start, int field, String[] data, CalendarBuilder calb)
154851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
154951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int i = 0;
155051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int count = data.length;
155151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
155251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (field == Calendar.DAY_OF_WEEK) i = 1;
155351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
155451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // There may be multiple strings in the data[] array which begin with
155551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // the same prefix (e.g., Cerven and Cervenec (June and July) in Czech).
155651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // We keep track of the longest match, and return that.  Note that this
155751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // unfortunately requires us to test all array elements.
155851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int bestMatchLength = 0, bestMatch = -1;
155951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (; i<count; ++i)
156051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        {
156151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int length = data[i].length();
156251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Always compare if we have no match yet; otherwise only compare
156351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // against potentially better matches (longer strings).
156451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (length > bestMatchLength &&
156551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                text.regionMatches(true, start, data[i], 0, length))
156651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            {
156751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                bestMatch = i;
156851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                bestMatchLength = length;
156951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
157000617c74e1f95fbe088f078341d607132575b0d6Narayan Kamath
157100617c74e1f95fbe088f078341d607132575b0d6Narayan Kamath            // When the input option ends with a period (usually an abbreviated form), attempt
157200617c74e1f95fbe088f078341d607132575b0d6Narayan Kamath            // to match all chars up to that period.
157300617c74e1f95fbe088f078341d607132575b0d6Narayan Kamath            if ((data[i].charAt(length - 1) == '.') &&
157400617c74e1f95fbe088f078341d607132575b0d6Narayan Kamath                    ((length - 1) > bestMatchLength) &&
157500617c74e1f95fbe088f078341d607132575b0d6Narayan Kamath                    text.regionMatches(true, start, data[i], 0, length - 1)) {
157600617c74e1f95fbe088f078341d607132575b0d6Narayan Kamath                bestMatch = i;
157700617c74e1f95fbe088f078341d607132575b0d6Narayan Kamath                bestMatchLength = (length - 1);
157800617c74e1f95fbe088f078341d607132575b0d6Narayan Kamath            }
157951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
158051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (bestMatch >= 0)
158151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        {
158251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            calb.set(field, bestMatch);
158351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return start + bestMatchLength;
158451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
158551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return -start;
158651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
158751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
158851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
158951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Performs the same thing as matchString(String, int, int,
159051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * String[]). This method takes a Map<String, Integer> instead of
159151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * String[].
159251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
159351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private int matchString(String text, int start, int field,
159451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            Map<String,Integer> data, CalendarBuilder calb) {
159551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (data != null) {
159651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String bestMatch = null;
159751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
159851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (String name : data.keySet()) {
159951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                int length = name.length();
160051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (bestMatch == null || length > bestMatch.length()) {
160151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (text.regionMatches(true, start, name, 0, length)) {
160251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        bestMatch = name;
160351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
160451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
160551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
160651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
160751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (bestMatch != null) {
160851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                calb.set(field, data.get(bestMatch));
160951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return start + bestMatch.length();
161051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
161151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
161251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return -start;
161351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
161451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
161551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private int matchZoneString(String text, int start, String[] zoneNames) {
161651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 1; i <= 4; ++i) {
161751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Checking long and short zones [1 & 2],
161851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // and long and short daylight [3 & 4].
161951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String zoneName = zoneNames[i];
162051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (text.regionMatches(true, start,
162151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                   zoneName, 0, zoneName.length())) {
162251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return i;
162351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
162451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
162551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return -1;
162651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
162751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
162851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean matchDSTString(String text, int start, int zoneIndex, int standardIndex,
162951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                   String[][] zoneStrings) {
163051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int index = standardIndex + 2;
163151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String zoneName  = zoneStrings[zoneIndex][index];
163251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (text.regionMatches(true, start,
163351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                               zoneName, 0, zoneName.length())) {
163451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return true;
163551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
163651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return false;
163751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
163851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
163951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
164051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * find time zone 'text' matched zoneStrings and set to internal
164151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * calendar.
164251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
164351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private int subParseZoneString(String text, int start, CalendarBuilder calb) {
164451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean useSameName = false; // true if standard and daylight time use the same abbreviation.
164551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        TimeZone currentTimeZone = getTimeZone();
164651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
164751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // At this point, check for named time zones by looking through
164851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // the locale data from the TimeZoneNames strings.
164951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Want to be able to parse both short and long forms.
165051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int zoneIndex = formatData.getZoneIndex(currentTimeZone.getID());
165151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        TimeZone tz = null;
165251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String[][] zoneStrings = formatData.getZoneStringsWrapper();
165351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        String[] zoneNames = null;
165451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int nameIndex = 0;
165551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (zoneIndex != -1) {
165651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            zoneNames = zoneStrings[zoneIndex];
165751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if ((nameIndex = matchZoneString(text, start, zoneNames)) > 0) {
165851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (nameIndex <= 2) {
165951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // Check if the standard name (abbr) and the daylight name are the same.
166051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    useSameName = zoneNames[nameIndex].equalsIgnoreCase(zoneNames[nameIndex + 2]);
166151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
166251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                tz = TimeZone.getTimeZone(zoneNames[0]);
166351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
166451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
166551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (tz == null) {
166651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            zoneIndex = formatData.getZoneIndex(TimeZone.getDefault().getID());
166751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (zoneIndex != -1) {
166851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                zoneNames = zoneStrings[zoneIndex];
166951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if ((nameIndex = matchZoneString(text, start, zoneNames)) > 0) {
167051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (nameIndex <= 2) {
167151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        useSameName = zoneNames[nameIndex].equalsIgnoreCase(zoneNames[nameIndex + 2]);
167251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
167351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    tz = TimeZone.getTimeZone(zoneNames[0]);
167451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
167551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
167651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
167751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
167851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (tz == null) {
167951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int len = zoneStrings.length;
168051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            for (int i = 0; i < len; i++) {
168151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                zoneNames = zoneStrings[i];
168251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if ((nameIndex = matchZoneString(text, start, zoneNames)) > 0) {
168351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (nameIndex <= 2) {
168451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        useSameName = zoneNames[nameIndex].equalsIgnoreCase(zoneNames[nameIndex + 2]);
168551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
168651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    tz = TimeZone.getTimeZone(zoneNames[0]);
168751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    break;
168851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
168951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
169051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
169151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (tz != null) { // Matched any ?
169251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!tz.equals(currentTimeZone)) {
169351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                setTimeZone(tz);
169451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
169551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // If the time zone matched uses the same name
169651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // (abbreviation) for both standard and daylight time,
169751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // let the time zone in the Calendar decide which one.
169851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            //
169951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Also if tz.getDSTSaving() returns 0 for DST, use tz to
170051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // determine the local time. (6645292)
170151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int dstAmount = (nameIndex >= 3) ? tz.getDSTSavings() : 0;
170251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!(useSameName || (nameIndex >= 3 && dstAmount == 0))) {
170351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                calb.clear(Calendar.ZONE_OFFSET).set(Calendar.DST_OFFSET, dstAmount);
170451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
170551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return (start + zoneNames[nameIndex].length());
170651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
170751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return 0;
170851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
170951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
171051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
171151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Parses numeric forms of time zone offset, such as "hh:mm", and
171251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * sets calb to the parsed value.
171351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
171451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param text  the text to be parsed
171551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param start the character position to start parsing
171651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param sign  1: positive; -1: negative
171751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param count 0: 'Z' or "GMT+hh:mm" parsing; 1 - 3: the number of 'X's
1718d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath     * @param colonRequired true - colon required between hh and mm; false - no colon required
171951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param calb  a CalendarBuilder in which the parsed value is stored
172051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return updated parsed position, or its negative value to indicate a parsing error
172151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
172251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private int subParseNumericZone(String text, int start, int sign, int count,
1723d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath                                    boolean colonRequired, CalendarBuilder calb) {
172451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int index = start;
172551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
172651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski      parse:
172751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
172851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            char c = text.charAt(index++);
172951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // Parse hh
173051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int hours;
173151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!isDigit(c)) {
173251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break parse;
173351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
173451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            hours = c - '0';
173551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            c = text.charAt(index++);
173651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (isDigit(c)) {
173751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                hours = hours * 10 + (c - '0');
173851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } else {
173951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                --index;
174051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
174151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (hours > 23) {
174251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break parse;
174351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
174451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int minutes = 0;
174551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (count != 1) {
174651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // Proceed with parsing mm
174751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                c = text.charAt(index++);
1748d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath                if (c == ':') {
174951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    c = text.charAt(index++);
1750d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath                } else if (colonRequired) {
1751d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath                    break parse;
175251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
175351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!isDigit(c)) {
175451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    break parse;
175551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
175651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                minutes = c - '0';
175751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                c = text.charAt(index++);
175851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!isDigit(c)) {
175951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    break parse;
176051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
176151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                minutes = minutes * 10 + (c - '0');
176251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (minutes > 59) {
176351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    break parse;
176451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
176551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
176651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            minutes += hours * 60;
176751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            calb.set(Calendar.ZONE_OFFSET, minutes * MILLIS_PER_MINUTE * sign)
176851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                .set(Calendar.DST_OFFSET, 0);
176951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return index;
177051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (IndexOutOfBoundsException e) {
177151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
177251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return  1 - index; // -(index - 1)
177351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
177451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
177551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean isDigit(char c) {
177651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return c >= '0' && c <= '9';
177751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
177851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
177951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
178051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Private member function that converts the parsed date strings into
178151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * timeFields. Returns -start (for ParsePosition) if failed.
178251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param text the time text to be parsed.
178351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param start where to start parsing.
178451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param ch the pattern character for the date field text to be parsed.
178551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param count the count of a pattern character.
178651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param obeyCount if true, then the next field directly abuts this one,
178751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * and we should use the count to know when to stop parsing.
178851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param ambiguousYear return parameter; upon return, if ambiguousYear[0]
178951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * is true, then a two-digit year was parsed and may need to be readjusted.
179051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param origPos origPos.errorIndex is used to return an error index
179151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * at which a parse error occurred, if matching failure occurs.
179251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the new start position if matching succeeded; -1 indicating
179351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * matching failure, otherwise. In case matching failure occurred,
179451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * an error index is set to origPos.errorIndex.
179551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
179651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private int subParse(String text, int start, int patternCharIndex, int count,
179751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         boolean obeyCount, boolean[] ambiguousYear,
179851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         ParsePosition origPos,
179951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         boolean useFollowingMinusSignAsDelimiter, CalendarBuilder calb) {
180051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        Number number = null;
180151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int value = 0;
180251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        ParsePosition pos = new ParsePosition(0);
180351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        pos.index = start;
180451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (patternCharIndex == PATTERN_WEEK_YEAR && !calendar.isWeekDateSupported()) {
180551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // use calendar year 'y' instead
180651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            patternCharIndex = PATTERN_YEAR;
180751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
180851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex];
180951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
181051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // If there are any spaces here, skip over them.  If we hit the end
181151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // of the string, then fail.
181251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (;;) {
181351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (pos.index >= text.length()) {
181451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                origPos.errorIndex = start;
181551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return -1;
181651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
181751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            char c = text.charAt(pos.index);
181851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (c != ' ' && c != '\t') break;
181951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ++pos.index;
182051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
182151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
182251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski      parsing:
182351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        {
182451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // We handle a few special cases here where we need to parse
182551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // a number value.  We handle further, more generic cases below.  We need
182651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // to handle some of them here because some fields require extra processing on
182751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // the parsed value.
182851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (patternCharIndex == PATTERN_HOUR_OF_DAY1 ||
182951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                patternCharIndex == PATTERN_HOUR1 ||
183051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                (patternCharIndex == PATTERN_MONTH && count <= 2) ||
183151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                patternCharIndex == PATTERN_YEAR ||
183251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                patternCharIndex == PATTERN_WEEK_YEAR) {
183351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // It would be good to unify this with the obeyCount logic below,
183451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // but that's going to be difficult.
183551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (obeyCount) {
183651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if ((start+count) > text.length()) {
183751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        break parsing;
183851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
183951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    number = numberFormat.parse(text.substring(0, start+count), pos);
184051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
184151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    number = numberFormat.parse(text, pos);
184251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
184351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (number == null) {
184451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (patternCharIndex != PATTERN_YEAR || calendar instanceof GregorianCalendar) {
184551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        break parsing;
184651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
184751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
184851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    value = number.intValue();
184951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
185051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (useFollowingMinusSignAsDelimiter && (value < 0) &&
185151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        (((pos.index < text.length()) &&
185251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         (text.charAt(pos.index) != minusSign)) ||
185351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         ((pos.index == text.length()) &&
185451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                          (text.charAt(pos.index-1) == minusSign)))) {
185551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        value = -value;
185651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        pos.index--;
185751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
185851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
185951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
186051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
186151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            boolean useDateFormatSymbols = useDateFormatSymbols();
186251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
186351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            int index;
186451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            switch (patternCharIndex) {
186551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case PATTERN_ERA: // 'G'
186651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (useDateFormatSymbols) {
186751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if ((index = matchString(text, start, Calendar.ERA, formatData.getEras(), calb)) > 0) {
186851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return index;
186951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
187051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
187151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    Map<String, Integer> map = calendar.getDisplayNames(field,
187251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                                                        Calendar.ALL_STYLES,
187351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                                                        locale);
187451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if ((index = matchString(text, start, field, map, calb)) > 0) {
187551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return index;
187651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
187751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
187851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break parsing;
187951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
188051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case PATTERN_WEEK_YEAR: // 'Y'
188151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case PATTERN_YEAR:      // 'y'
188251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!(calendar instanceof GregorianCalendar)) {
188351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // calendar might have text representations for year values,
188451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // such as "\u5143" in JapaneseImperialCalendar.
188551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int style = (count >= 4) ? Calendar.LONG : Calendar.SHORT;
188651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    Map<String, Integer> map = calendar.getDisplayNames(field, style, locale);
188751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (map != null) {
188851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if ((index = matchString(text, start, field, map, calb)) > 0) {
188951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            return index;
189051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
189151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
189251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    calb.set(field, value);
189351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return pos.index;
189451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
189551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
189651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // If there are 3 or more YEAR pattern characters, this indicates
189751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // that the year value is to be treated literally, without any
189851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // two-digit year adjustments (e.g., from "01" to 2001).  Otherwise
189951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // we made adjustments to place the 2-digit year in the proper
190051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // century, for parsed strings from "00" to "99".  Any other string
190151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // is treated literally:  "2250", "-1", "1", "002".
190251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (count <= 2 && (pos.index - start) == 2
190351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    && Character.isDigit(text.charAt(start))
190451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    && Character.isDigit(text.charAt(start+1))) {
190551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // Assume for example that the defaultCenturyStart is 6/18/1903.
190651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // This means that two-digit years will be forced into the range
190751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // 6/18/1903 to 6/17/2003.  As a result, years 00, 01, and 02
190851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // correspond to 2000, 2001, and 2002.  Years 04, 05, etc. correspond
190951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // to 1904, 1905, etc.  If the year is 03, then it is 2003 if the
191051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // other fields specify a date before 6/18, or 1903 if they specify a
191151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // date afterwards.  As a result, 03 is an ambiguous year.  All other
191251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // two-digit years are unambiguous.
191351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int ambiguousTwoDigitYear = defaultCenturyStartYear % 100;
191451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    ambiguousYear[0] = value == ambiguousTwoDigitYear;
191551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    value += (defaultCenturyStartYear/100)*100 +
191651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        (value < ambiguousTwoDigitYear ? 100 : 0);
191751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
191851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                calb.set(field, value);
191951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return pos.index;
192051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
1921d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            case PATTERN_STANDALONE_MONTH: // 'L'.
1922d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            {
1923d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                final int idx = parseMonth(text, count, value, start, field, pos,
1924d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                        useDateFormatSymbols, true /* isStandalone */, calb);
1925d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                if (idx > 0) {
1926d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                    return idx;
192751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
1928d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                break parsing;
1929d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            }
193051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
1931d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            case PATTERN_MONTH: // 'M'
1932d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            {
1933d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                final int idx = parseMonth(text, count, value, start, field, pos,
1934d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                        useDateFormatSymbols, false /* isStandalone */, calb);
1935d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                if (idx > 0) {
1936d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                    return idx;
193751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
1938d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath
193951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break parsing;
1940d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            }
194151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
194251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case PATTERN_HOUR_OF_DAY1: // 'k' 1-based.  eg, 23:59 + 1 hour =>> 24:59
194351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!isLenient()) {
194451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // Validate the hour value in non-lenient
194551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (value < 1 || value > 24) {
194651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        break parsing;
194751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
194851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
194951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // [We computed 'value' above.]
195051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (value == calendar.getMaximum(Calendar.HOUR_OF_DAY)+1)
195151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    value = 0;
195251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                calb.set(Calendar.HOUR_OF_DAY, value);
195351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return pos.index;
195451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
1955d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            case PATTERN_STANDALONE_DAY_OF_WEEK: // 'c'
1956d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            {
1957d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                final int idx = parseWeekday(text, start, field, useDateFormatSymbols,
195882c413526cc241290cc69170f28cac5213cf74edJoachim Sauer                        true /* standalone */, calb);
1959d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                if (idx > 0) {
1960d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                    return idx;
1961d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                }
1962d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath
1963d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                break parsing;
1964d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            }
1965d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath
196651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case PATTERN_DAY_OF_WEEK:  // 'E'
1967d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            {
1968d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                final int idx = parseWeekday(text, start, field, useDateFormatSymbols,
1969d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                        false /* standalone */, calb);
1970d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                if (idx > 0) {
1971d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                    return idx;
197251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
1973d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath
197451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break parsing;
1975d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            }
1976d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath
197751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
197851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case PATTERN_AM_PM:    // 'a'
197951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (useDateFormatSymbols) {
198051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if ((index = matchString(text, start, Calendar.AM_PM,
198151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                             formatData.getAmPmStrings(), calb)) > 0) {
198251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return index;
198351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
198451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
198551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    Map<String,Integer> map = calendar.getDisplayNames(field, Calendar.ALL_STYLES, locale);
198651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if ((index = matchString(text, start, field, map, calb)) > 0) {
198751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return index;
198851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
198951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
199051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break parsing;
199151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
199251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case PATTERN_HOUR1: // 'h' 1-based.  eg, 11PM + 1 hour =>> 12 AM
199351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (!isLenient()) {
199451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // Validate the hour value in non-lenient
199551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (value < 1 || value > 12) {
199651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        break parsing;
199751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
199851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
199951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // [We computed 'value' above.]
200051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (value == calendar.getLeastMaximum(Calendar.HOUR)+1)
200151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    value = 0;
200251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                calb.set(Calendar.HOUR, value);
200351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return pos.index;
200451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
200551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case PATTERN_ZONE_NAME:  // 'z'
200651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case PATTERN_ZONE_VALUE: // 'Z'
200751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                {
200851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int sign = 0;
200951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    try {
201051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        char c = text.charAt(pos.index);
201151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (c == '+') {
201251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            sign = 1;
201351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        } else if (c == '-') {
201451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            sign = -1;
201551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
201651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (sign == 0) {
201751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            // Try parsing a custom time zone "GMT+hh:mm" or "GMT".
201851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            if ((c == 'G' || c == 'g')
201951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                && (text.length() - start) >= GMT.length()
202051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                && text.regionMatches(true, start, GMT, 0, GMT.length())) {
202151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                pos.index = start + GMT.length();
202251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
202351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                if ((text.length() - pos.index) > 0) {
202451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                    c = text.charAt(pos.index);
202551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                    if (c == '+') {
202651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                        sign = 1;
202751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                    } else if (c == '-') {
202851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                        sign = -1;
202951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                    }
203051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                }
203151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
203251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                if (sign == 0) {    /* "GMT" without offset */
203351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                    calb.set(Calendar.ZONE_OFFSET, 0)
203451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                        .set(Calendar.DST_OFFSET, 0);
203551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                    return pos.index;
203651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                }
203751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2038d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath                                // Parse the rest as "hh[:]?mm"
2039d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath                                int i = subParseNumericZone(text, ++pos.index, sign, 0,
2040d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath                                        false, calb);
204151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                if (i > 0) {
204251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                    return i;
204351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                }
204451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                pos.index = -i;
204551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            } else {
204651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                // Try parsing the text as a time zone
204751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                // name or abbreviation.
204851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                int i = subParseZoneString(text, pos.index, calb);
204951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                if (i > 0) {
205051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                    return i;
205151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                }
205251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                pos.index = -i;
205351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            }
205451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        } else {
2055d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath                            // Parse the rest as "hh[:]?mm" (RFC 822)
2056d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath                            int i = subParseNumericZone(text, ++pos.index, sign, 0,
2057d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath                                    false, calb);
205851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            if (i > 0) {
205951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                return i;
206051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            }
206151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            pos.index = -i;
206251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
206351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } catch (IndexOutOfBoundsException e) {
206451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
206551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
206651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break parsing;
206751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
206851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            case PATTERN_ISO_ZONE:   // 'X'
206951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                {
207051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if ((text.length() - pos.index) <= 0) {
207151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        break parsing;
207251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
207351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
207451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int sign = 0;
207551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    char c = text.charAt(pos.index);
207651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (c == 'Z') {
207751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        calb.set(Calendar.ZONE_OFFSET, 0).set(Calendar.DST_OFFSET, 0);
207851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return ++pos.index;
207951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
208051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
208151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    // parse text as "+/-hh[[:]mm]" based on count
208251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (c == '+') {
208351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        sign = 1;
208451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } else if (c == '-') {
208551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        sign = -1;
208651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } else {
208751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        ++pos.index;
208851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        break parsing;
208951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
2090d06c9ff1e64308978a6db2135d744613e396b65eNarayan Kamath                    int i = subParseNumericZone(text, ++pos.index, sign, count, (count == 3), calb);
209151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (i > 0) {
209251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        return i;
209351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
209451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    pos.index = -i;
209551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
209651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break parsing;
209751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
209851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            default:
209951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         // case PATTERN_DAY_OF_MONTH:         // 'd'
210051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         // case PATTERN_HOUR_OF_DAY0:         // 'H' 0-based.  eg, 23:59 + 1 hour =>> 00:59
210151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         // case PATTERN_MINUTE:               // 'm'
210251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         // case PATTERN_SECOND:               // 's'
210351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         // case PATTERN_MILLISECOND:          // 'S'
210451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         // case PATTERN_DAY_OF_YEAR:          // 'D'
210551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         // case PATTERN_DAY_OF_WEEK_IN_MONTH: // 'F'
210651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         // case PATTERN_WEEK_OF_YEAR:         // 'w'
210751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         // case PATTERN_WEEK_OF_MONTH:        // 'W'
210851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         // case PATTERN_HOUR0:                // 'K' 0-based.  eg, 11PM + 1 hour =>> 0 AM
210951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         // case PATTERN_ISO_DAY_OF_WEEK:      // 'u' (pseudo field);
211051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
211151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // Handle "generic" fields
2112afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath                int parseStart = pos.getIndex();
211351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (obeyCount) {
211451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if ((start+count) > text.length()) {
211551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        break parsing;
211651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
211751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    number = numberFormat.parse(text.substring(0, start+count), pos);
211851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                } else {
211951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    number = numberFormat.parse(text, pos);
212051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
212151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (number != null) {
2122afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath                    if (patternCharIndex == PATTERN_MILLISECOND) {
2123afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath                        // Fractional seconds must be treated specially. We must always
2124afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath                        // normalize them to their fractional second value [0, 1) before we attempt
2125afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath                        // to parse them.
2126afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath                        //
2127afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath                        // Case 1: 11.78 seconds is 11 seconds and 780 (not 78) milliseconds.
2128afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath                        // Case 2: 11.7890567 seconds is 11 seconds and 789 (not 7890567) milliseconds.
2129afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath                        double doubleValue = number.doubleValue();
2130afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath                        int width = pos.getIndex() - parseStart;
2131afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath                        final double divisor = Math.pow(10, width);
2132afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath                        value = (int) ((doubleValue / divisor) * 1000);
2133afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath                    } else {
2134afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath                        value = number.intValue();
2135afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath                    }
213651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
213751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (useFollowingMinusSignAsDelimiter && (value < 0) &&
2138afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath                            (((pos.index < text.length()) &&
2139afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath                                    (text.charAt(pos.index) != minusSign)) ||
2140afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath                                    ((pos.index == text.length()) &&
2141afe86efb5d4b237c50df82b7dcb581d4d75b1132Narayan Kamath                                            (text.charAt(pos.index - 1) == minusSign)))) {
214251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        value = -value;
214351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        pos.index--;
214451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
214551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
214651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    calb.set(field, value);
214751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    return pos.index;
214851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
214951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                break parsing;
215051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
215151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
215251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
215351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // Parsing failed.
215451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        origPos.errorIndex = pos.index;
215551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return -1;
215651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
215751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2158d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath    private int parseMonth(String text, int count, int value, int start,
2159d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                           int field, ParsePosition pos, boolean useDateFormatSymbols,
2160d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                           boolean standalone,
2161d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                           CalendarBuilder out) {
2162d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        if (count <= 2) // i.e., M or MM.
2163d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        {
2164d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            // Don't want to parse the month if it is a string
2165d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            // while pattern uses numeric style: M or MM.
2166d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            // [We computed 'value' above.]
2167d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            out.set(Calendar.MONTH, value - 1);
2168d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            return pos.index;
2169d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        }
2170d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath
2171d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        int index = -1;
2172d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        if (useDateFormatSymbols) {
2173d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            // count >= 3 // i.e., MMM or MMMM
2174d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            // Want to be able to parse both short and long forms.
2175d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            // Try count == 4 first:
2176d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            if ((index = matchString(
2177d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                    text, start, Calendar.MONTH,
2178d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                    standalone ? formatData.getStandAloneMonths() : formatData.getMonths(),
2179d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                    out)) > 0) {
2180d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                return index;
2181d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            }
2182d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            // count == 4 failed, now try count == 3
2183d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            if ((index = matchString(
2184d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                    text, start, Calendar.MONTH,
2185d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                    standalone ? formatData.getShortStandAloneMonths() : formatData.getShortMonths(),
2186d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                    out)) > 0) {
2187d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                return index;
2188d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            }
2189d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        } else {
2190d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            Map<String, Integer> map = calendar.getDisplayNames(field,
2191d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                    Calendar.ALL_STYLES,
2192d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                    locale);
2193d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            if ((index = matchString(text, start, field, map, out)) > 0) {
2194d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                return index;
2195d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            }
2196d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        }
2197d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath
2198d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        return index;
2199d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath    }
2200d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath
2201d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath    private int parseWeekday(String text, int start, int field, boolean useDateFormatSymbols,
2202d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                             boolean standalone, CalendarBuilder out) {
2203d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        int index = -1;
2204d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        if (useDateFormatSymbols) {
2205d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            // Want to be able to parse both short and long forms.
2206d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            // Try count == 4 (DDDD) first:
2207d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            if ((index=matchString(
2208d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                    text, start, Calendar.DAY_OF_WEEK,
2209d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                    standalone ? formatData.getStandAloneWeekdays() : formatData.getWeekdays(),
2210d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                    out)) > 0) {
2211d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                return index;
2212d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            }
2213d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath
2214d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            // DDDD failed, now try DDD
2215d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            if ((index = matchString(
2216d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                    text, start, Calendar.DAY_OF_WEEK,
2217d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                    standalone ? formatData.getShortStandAloneWeekdays() : formatData.getShortWeekdays(),
2218d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                    out)) > 0) {
2219d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                return index;
2220d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            }
2221d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        } else {
2222d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            int[] styles = { Calendar.LONG, Calendar.SHORT };
2223d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            for (int style : styles) {
2224d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                Map<String,Integer> map = calendar.getDisplayNames(field, style, locale);
2225d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                if ((index = matchString(text, start, field, map, out)) > 0) {
2226d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                    return index;
2227d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath                }
2228d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath            }
2229d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        }
2230d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath
2231d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath        return index;
2232d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath    }
2233d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath
2234d6c54ba7af74286d2e310703a4aa2c924ec85c99Narayan Kamath
223551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private final String getCalendarName() {
223651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return calendar.getClass().getName();
223751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
223851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
223951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean useDateFormatSymbols() {
224051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (useDateFormatSymbols) {
224151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return true;
224251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
224351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return isGregorianCalendar() || locale == null;
224451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
224551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
224651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private boolean isGregorianCalendar() {
224751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return "java.util.GregorianCalendar".equals(getCalendarName());
224851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
224951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
225051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
225151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Translates a pattern, mapping each character in the from string to the
225251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * corresponding character in the to string.
225351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
225451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception IllegalArgumentException if the given pattern is invalid
225551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
225651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private String translatePattern(String pattern, String from, String to) {
225751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        StringBuilder result = new StringBuilder();
225851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        boolean inQuote = false;
225951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        for (int i = 0; i < pattern.length(); ++i) {
226051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            char c = pattern.charAt(i);
226151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (inQuote) {
226251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (c == '\'')
226351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    inQuote = false;
226451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
226551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            else {
226651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (c == '\'')
226751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    inQuote = true;
226851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
226951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int ci = from.indexOf(c);
227051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if (ci >= 0) {
227151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        // patternChars is longer than localPatternChars due
227251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        // to serialization compatibility. The pattern letters
227351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        // unsupported by localPatternChars pass through.
227451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        if (ci < to.length()) {
227551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                            c = to.charAt(ci);
227651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        }
227751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    } else {
227851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        throw new IllegalArgumentException("Illegal pattern " +
227951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                                           " character '" +
228051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                                           c + "'");
228151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
228251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
228351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
228451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            result.append(c);
228551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
228651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (inQuote)
228751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IllegalArgumentException("Unfinished quote in pattern");
228851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return result.toString();
228951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
229051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
229151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
229251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns a pattern string describing this date format.
229351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
229451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return a pattern string describing this date format.
229551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
229651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String toPattern() {
229751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return pattern;
229851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
229951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
230051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
230151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns a localized pattern string describing this date format.
230251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
230351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return a localized pattern string describing this date format.
230451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
230551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public String toLocalizedPattern() {
230651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return translatePattern(pattern,
230751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                DateFormatSymbols.patternChars,
230851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                formatData.getLocalPatternChars());
230951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
231051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
231151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
231251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Applies the given pattern string to this date format.
231351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
231451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param pattern the new date and time pattern for this date format
231551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception NullPointerException if the given pattern is null
231651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception IllegalArgumentException if the given pattern is invalid
231751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
231851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void applyPattern(String pattern)
231951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
232051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        compiledPattern = compile(pattern);
232151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.pattern = pattern;
232251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
232351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
232451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
232551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Applies the given localized pattern string to this date format.
232651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
232751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param pattern a String to be mapped to the new date and time format
232851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *        pattern for this format
232951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception NullPointerException if the given pattern is null
233051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception IllegalArgumentException if the given pattern is invalid
233151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
233251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void applyLocalizedPattern(String pattern) {
233351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         String p = translatePattern(pattern,
233451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                     formatData.getLocalPatternChars(),
233551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                                     DateFormatSymbols.patternChars);
233651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         compiledPattern = compile(p);
233751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski         this.pattern = p;
233851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
233951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
234051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
234151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Gets a copy of the date and time format symbols of this date format.
234251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
234351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the date and time format symbols of this date format
234451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see #setDateFormatSymbols
234551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
234651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public DateFormatSymbols getDateFormatSymbols()
234751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
234851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (DateFormatSymbols)formatData.clone();
234951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
235051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
235151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
235251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Sets the date and time format symbols of this date format.
235351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
235451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param newFormatSymbols the new date and time format symbols
235551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception NullPointerException if the given newFormatSymbols is null
235651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @see #getDateFormatSymbols
235751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
235851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void setDateFormatSymbols(DateFormatSymbols newFormatSymbols)
235951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
236051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this.formatData = (DateFormatSymbols)newFormatSymbols.clone();
236151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        useDateFormatSymbols = true;
236251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
236351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
236451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
236551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a copy of this <code>SimpleDateFormat</code>. This also
236651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * clones the format's date format symbols.
236751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
236851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return a clone of this <code>SimpleDateFormat</code>
236951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
237051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public Object clone() {
237151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        SimpleDateFormat other = (SimpleDateFormat) super.clone();
237251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        other.formatData = (DateFormatSymbols) formatData.clone();
237351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return other;
237451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
237551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
237651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
237751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Returns the hash code value for this <code>SimpleDateFormat</code> object.
237851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
237951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return the hash code value for this <code>SimpleDateFormat</code> object.
238051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
238151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public int hashCode()
238251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
238351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return pattern.hashCode();
238451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // just enough fields for a reasonable distribution
238551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
238651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
238751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
238851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Compares the given object with this <code>SimpleDateFormat</code> for
238951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * equality.
239051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
239151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return true if the given object is equal to this
239251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>SimpleDateFormat</code>
239351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
239451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean equals(Object obj)
239551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    {
239651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!super.equals(obj)) return false; // super does class check
239751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        SimpleDateFormat that = (SimpleDateFormat) obj;
239851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return (pattern.equals(that.pattern)
239951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                && formatData.equals(that.formatData));
240051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
240151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
240251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
240351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * After reading an object from the input stream, the format
240451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * pattern in the object is verified.
240551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
240651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception InvalidObjectException if the pattern is invalid
240751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
240851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void readObject(ObjectInputStream stream)
240951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                         throws IOException, ClassNotFoundException {
241051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        stream.defaultReadObject();
241151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
241251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        try {
241351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            compiledPattern = compile(pattern);
241451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } catch (Exception e) {
241551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new InvalidObjectException("invalid pattern");
241651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
241751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
241851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (serialVersionOnStream < 1) {
241951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // didn't have defaultCenturyStart field
242051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            initializeDefaultCentury();
242151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
242251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        else {
242351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            // fill in dependent transient field
242451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            parseAmbiguousDatesAsAfter(defaultCenturyStart);
242551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
242651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        serialVersionOnStream = currentSerialVersion;
242751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
242851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // If the deserialized object has a SimpleTimeZone, try
242951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // to replace it with a ZoneInfo equivalent in order to
243051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // be compatible with the SimpleTimeZone-based
243151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        // implementation as much as possible.
243251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        TimeZone tz = getTimeZone();
243351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (tz instanceof SimpleTimeZone) {
243451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String id = tz.getID();
243551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            TimeZone zi = TimeZone.getTimeZone(id);
243651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (zi != null && zi.hasSameRules(tz) && zi.getID().equals(id)) {
243751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                setTimeZone(zi);
243851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
243951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
244051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
244151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
244251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
244351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Analyze the negative subpattern of DecimalFormat and set/update values
244451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * as necessary.
244551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
244651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void checkNegativeNumberExpression() {
244751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if ((numberFormat instanceof DecimalFormat) &&
244851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            !numberFormat.equals(originalNumberFormat)) {
244951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            String numberPattern = ((DecimalFormat)numberFormat).toPattern();
245051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (!numberPattern.equals(originalNumberPattern)) {
245151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                hasFollowingMinusSign = false;
245251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
245351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                int separatorIndex = numberPattern.indexOf(';');
245451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // If the negative subpattern is not absent, we have to analayze
245551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // it in order to check if it has a following minus sign.
245651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (separatorIndex > -1) {
245751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    int minusIndex = numberPattern.indexOf('-', separatorIndex);
245851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    if ((minusIndex > numberPattern.lastIndexOf('0')) &&
245951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        (minusIndex > numberPattern.lastIndexOf('#'))) {
246051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        hasFollowingMinusSign = true;
246151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                        minusSign = ((DecimalFormat)numberFormat).getDecimalFormatSymbols().getMinusSign();
246251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    }
246351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
246451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                originalNumberPattern = numberPattern;
246551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
246651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            originalNumberFormat = numberFormat;
246751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
246851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
246951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
247051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
2471