/*
 *******************************************************************************
 * Copyright (C) 1996-2004, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */

package com.ibm.icu.text;

import com.ibm.icu.util.Calendar;
import com.ibm.icu.lang.UCharacter;
import com.ibm.icu.impl.CalendarData;
import com.ibm.icu.impl.UCharacterProperty;
import com.ibm.icu.util.TimeZone;
import com.ibm.icu.util.ULocale;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.lang.ref.SoftReference;
import java.text.FieldPosition;
import java.text.MessageFormat;
import java.text.ParsePosition;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Locale;
import java.util.Map;

/**
 * <code>SimpleDateFormat</code> is a concrete class for formatting and
 * parsing dates in a locale-sensitive manner. It allows for formatting
 * (date -> text), parsing (text -> date), and normalization.
 *
 * <p>
 * <code>SimpleDateFormat</code> allows you to start by choosing
 * any user-defined patterns for date-time formatting. However, you
 * are encouraged to create a date-time formatter with either
 * <code>getTimeInstance</code>, <code>getDateInstance</code>, or
 * <code>getDateTimeInstance</code> in <code>DateFormat</code>. Each
 * of these class methods can return a date/time formatter initialized
 * with a default format pattern. You may modify the format pattern
 * using the <code>applyPattern</code> methods as desired.
 * For more information on using these methods, see
 * {@link DateFormat}.
 *
 * <p>
 * <strong>Time Format Syntax:</strong>
 * <p>
 * To specify the time format use a <em>time pattern</em> string.
 * In this pattern, all ASCII letters are reserved as pattern letters,
 * which are defined as the following:
 * <blockquote>
 * <pre>
 * Symbol   Meaning                 Presentation        Example
 * ------   -------                 ------------        -------
 * G        era designator          (Text)              AD
 * y        year                    (Number)            1996
 * Y        year (week of year)     (Number)            1997
 * u        extended year           (Number)            4601
 * M        month in year           (Text & Number)     July & 07
 * d        day in month            (Number)            10
 * h        hour in am/pm (1~12)    (Number)            12
 * H        hour in day (0~23)      (Number)            0
 * m        minute in hour          (Number)            30
 * s        second in minute        (Number)            55
 * S        fractional second       (Number)            978
 * E        day of week             (Text)              Tuesday
 * e        day of week (local 1~7) (Number)            2
 * D        day in year             (Number)            189
 * F        day of week in month    (Number)            2 (2nd Wed in July)
 * w        week in year            (Number)            27
 * W        week in month           (Number)            2
 * a        am/pm marker            (Text)              PM
 * k        hour in day (1~24)      (Number)            24
 * K        hour in am/pm (0~11)    (Number)            0
 * z        time zone               (Text)              Pacific Standard Time
 * Z        time zone (RFC 822)     (Number)            -0800
 * g        Julian day              (Number)            2451334
 * A        milliseconds in day     (Number)            69540000
 * '        escape for text         (Delimiter)         'Date='
 * ''       single quote            (Literal)           'o''clock'
 * </pre>
 * </blockquote>
 * The count of pattern letters determine the format.
 * <p>
 * <strong>(Text)</strong>: 4 or more pattern letters--use full form,
 * &lt; 4--use short or abbreviated form if one exists.
 * <p>
 * <strong>(Number)</strong>: the minimum number of digits. Shorter
 * numbers are zero-padded to this amount. Year is handled specially;
 * that is, if the count of 'y' is 2, the Year will be truncated to 2 digits.
 * (e.g., if "yyyy" produces "1997", "yy" produces "97".)
 * Unlike other fields, fractional seconds are padded on the right with zero.
 * <p>
 * <strong>(Text & Number)</strong>: 3 or over, use text, otherwise use number.
 * <p>
 * Any characters in the pattern that are not in the ranges of ['a'..'z']
 * and ['A'..'Z'] will be treated as quoted text. For instance, characters
 * like ':', '.', ' ', '#' and '@' will appear in the resulting time text
 * even they are not embraced within single quotes.
 * <p>
 * A pattern containing any invalid pattern letter will result in a thrown
 * exception during formatting or parsing.
 *
 * <p>
 * <strong>Examples Using the US Locale:</strong>
 * <blockquote>
 * <pre>
 * Format Pattern                         Result
 * --------------                         -------
 * "yyyy.MM.dd G 'at' HH:mm:ss z"    ->>  1996.07.10 AD at 15:08:56 PDT
 * "EEE, MMM d, ''yy"                ->>  Wed, July 10, '96
 * "h:mm a"                          ->>  12:08 PM
 * "hh 'o''clock' a, zzzz"           ->>  12 o'clock PM, Pacific Daylight Time
 * "K:mm a, z"                       ->>  0:00 PM, PST
 * "yyyyy.MMMMM.dd GGG hh:mm aaa"    ->>  01996.July.10 AD 12:08 PM
 * </pre>
 * </blockquote>
 * <strong>Code Sample:</strong>
 * <blockquote>
 * <pre>
 * SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, "PST");
 * pdt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2*60*60*1000);
 * pdt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2*60*60*1000);
 * <br>
 * // Format the current time.
 * SimpleDateFormat formatter
 *     = new SimpleDateFormat ("yyyy.MM.dd G 'at' hh:mm:ss a zzz");
 * Date currentTime_1 = new Date();
 * String dateString = formatter.format(currentTime_1);
 * <br>
 * // Parse the previous string back into a Date.
 * ParsePosition pos = new ParsePosition(0);
 * Date currentTime_2 = formatter.parse(dateString, pos);
 * </pre>
 * </blockquote>
 * In the example, the time value <code>currentTime_2</code> obtained from
 * parsing will be equal to <code>currentTime_1</code>. However, they may not be
 * equal if the am/pm marker 'a' is left out from the format pattern while
 * the "hour in am/pm" pattern symbol is used. This information loss can
 * happen when formatting the time in PM.
 *
 * <p>
 * When parsing a date string using the abbreviated year pattern ("yy"),
 * SimpleDateFormat must interpret the abbreviated year
 * relative to some century.  It does this by adjusting dates to be
 * within 80 years before and 20 years after the time the SimpleDateFormat
 * instance is created. For example, using a pattern of "MM/dd/yy" and a
 * SimpleDateFormat instance created on Jan 1, 1997,  the string
 * "01/11/12" would be interpreted as Jan 11, 2012 while the string "05/04/64"
 * would be interpreted as May 4, 1964.
 * During parsing, only strings consisting of exactly two digits, as defined by
 * {@link java.lang.Character#isDigit(char)}, will be parsed into the default
 * century.
 * Any other numeric string, such as a one digit string, a three or more digit
 * string, or a two digit string that isn't all digits (for example, "-1"), is
 * interpreted literally.  So "01/02/3" or "01/02/003" are parsed, using the
 * same pattern, as Jan 2, 3 AD.  Likewise, "01/02/-3" is parsed as Jan 2, 4 BC.
 *
 * <p>
 * If the year pattern does not have exactly two 'y' characters, the year is
 * interpreted literally, regardless of the number of digits.  So using the
 * pattern "MM/dd/yyyy", "01/11/12" parses to Jan 11, 12 A.D.
 *
 * <p>
 * When numeric fields abut one another directly, with no intervening delimiter
 * characters, they constitute a run of abutting numeric fields.  Such runs are
 * parsed specially.  For example, the format "HHmmss" parses the input text
 * "123456" to 12:34:56, parses the input text "12345" to 1:23:45, and fails to
 * parse "1234".  In other words, the leftmost field of the run is flexible,
 * while the others keep a fixed width.  If the parse fails anywhere in the run,
 * then the leftmost field is shortened by one character, and the entire run is
 * parsed again. This is repeated until either the parse succeeds or the
 * leftmost field is one character in length.  If the parse still fails at that
 * point, the parse of the run fails.
 *
 * <p>
 * For time zones that have no names, use strings GMT+hours:minutes or
 * GMT-hours:minutes.
 *
 * <p>
 * The calendar defines what is the first day of the week, the first week
 * of the year, whether hours are zero based or not (0 vs 12 or 24), and the
 * time zone. There is one common decimal format to handle all the numbers;
 * the digit count is handled programmatically according to the pattern.
 *
 * <h4>Synchronization</h4>
 *
 * Date formats are not synchronized. It is recommended to create separate 
 * format instances for each thread. If multiple threads access a format 
 * concurrently, it must be synchronized externally. 
 *
 * @see          com.ibm.icu.util.Calendar
 * @see          com.ibm.icu.util.GregorianCalendar
 * @see          com.ibm.icu.util.TimeZone
 * @see          DateFormat
 * @see          DateFormatSymbols
 * @see          DecimalFormat
 * @author       Mark Davis, Chen-Lieh Huang, Alan Liu
 * @stable ICU 2.0
 */
public class SimpleDateFormat extends DateFormat {

    // the official serial version ID which says cryptically
    // which version we're compatible with
    static final long serialVersionUID = 4774881970558875024L;

    // the internal serial version which says which version was written
    // - 0 (default) for version up to JDK 1.1.3
    // - 1 for version from JDK 1.1.4, which includes a new field
    static final int currentSerialVersion = 1;

    /**
     * The version of the serialized data on the stream.  Possible values:
     * <ul>
     * <li><b>0</b> or not present on stream: JDK 1.1.3.  This version
     * has no <code>defaultCenturyStart</code> on stream.
     * <li><b>1</b> JDK 1.1.4 or later.  This version adds
     * <code>defaultCenturyStart</code>.
     * </ul>
     * When streaming out this class, the most recent format
     * and the highest allowable <code>serialVersionOnStream</code>
     * is written.
     * @serial
     */
    private int serialVersionOnStream = currentSerialVersion;

    /**
     * The pattern string of this formatter.  This is always a non-localized
     * pattern.  May not be null.  See class documentation for details.
     * @serial
     */
    private String pattern;

    /**
     * The symbols used by this formatter for week names, month names,
     * etc.  May not be null.
     * @serial
     * @see DateFormatSymbols
     */
    private DateFormatSymbols formatData;

    /**
     * We map dates with two-digit years into the century starting at
     * <code>defaultCenturyStart</code>, which may be any date.  May
     * not be null.
     * @serial
     * @since JDK1.1.4
     */
    private Date defaultCenturyStart;

    transient private int defaultCenturyStartYear;

    private static final int millisPerHour = 60 * 60 * 1000;
    private static final int millisPerMinute = 60 * 1000;

    // For time zones that have no names, use strings GMT+minutes and
    // GMT-minutes. For instance, in France the time zone is GMT+60.
    private static final String GMT_PLUS = "GMT+";
    private static final String GMT_MINUS = "GMT-";
    private static final String GMT = "GMT";

    // This prefix is designed to NEVER MATCH real text, in order to
    // suppress the parsing of negative numbers.  Adjust as needed (if
    // this becomes valid Unicode).
    private static final String SUPPRESS_NEGATIVE_PREFIX = "\uAB00";

    /**
     * Cache to hold the DateTimePatterns of a Locale.
     */
    private static Hashtable cachedLocaleData = new Hashtable(3);

    /**
     * If true, this object supports fast formatting using the
     * subFormat variant that takes a StringBuffer.
     */
    private transient boolean useFastFormat;

    /**
     * Construct a SimpleDateFormat using the default pattern for the default
     * locale.  <b>Note:</b> Not all locales support SimpleDateFormat; for full
     * generality, use the factory methods in the DateFormat class.
     *
     * @see DateFormat
     * @stable ICU 2.0
     */
    public SimpleDateFormat() {
        this(SHORT, SHORT, Locale.getDefault());
    }

    /**
     * Construct a SimpleDateFormat using the given pattern in the default
     * locale.  <b>Note:</b> Not all locales support SimpleDateFormat; for full
     * generality, use the factory methods in the DateFormat class.
     * @stable ICU 2.0
     */
    public SimpleDateFormat(String pattern)
    {
        this(pattern, Locale.getDefault());
    }

    /**
     * Construct a SimpleDateFormat using the given pattern and locale.
     * <b>Note:</b> Not all locales support SimpleDateFormat; for full
     * generality, use the factory methods in the DateFormat class.
     * @stable ICU 2.0
     */
    public SimpleDateFormat(String pattern, Locale loc)
    {
        this.pattern = pattern;
        this.formatData = new DateFormatSymbols(loc);
        initialize(loc);
    }

    /**
     * Construct a SimpleDateFormat using the given pattern and
     * locale-specific symbol data.
     * @stable ICU 2.0
     */
    public SimpleDateFormat(String pattern, DateFormatSymbols formatData)
    {
        this.pattern = pattern;
        this.formatData = (DateFormatSymbols) formatData.clone();
        initialize(Locale.getDefault());
    }

    /**
     * Package-private constructor that allows a subclass to specify
     * whether it supports fast formatting.
     *
     * TODO make this API public.
     */
    SimpleDateFormat(String pattern, DateFormatSymbols formatData,
                     boolean useFastFormat) {
        this.pattern = pattern;
        this.formatData = (DateFormatSymbols) formatData.clone();
        initialize(Locale.getDefault());
        // this.useFastFormat is set by initialize(); fix it up afterwards
        this.useFastFormat = useFastFormat;
    }

    // try caching
    private static final boolean CACHE = true;
    private static long cacheAge;
    private static SoftReference highCacheRef;
    
    /* Package-private, called by DateFormat factory methods */
    SimpleDateFormat(int timeStyle, int dateStyle, Locale loc) {
	// try a high level cache first!

	Map map = null;
	String key = null;
	if (CACHE) {
	    // age test is so we don't have to compute the century start all the time... once a day is enough.
	    long time = System.currentTimeMillis();
	    if (((time - cacheAge) < 1000*60*60*24L) && highCacheRef != null) {
		map = (Map)highCacheRef.get();
	    }
	    if (map == null) {
		map = new HashMap(3);
		highCacheRef = new SoftReference(map);
		cacheAge = time;
	    }
	    key = loc.toString() + timeStyle + dateStyle;
	    SimpleDateFormat target = (SimpleDateFormat)map.get(key);
	    if (target != null) { // kindof skanky
//  		if ("en_US22".equals(key))
//  		    System.out.println("\nfound key: " + key + " pat: " + target.pattern +
//  				       " cal: " + target.calendar + " fmt: " + target.numberFormat);
		this.pattern = target.pattern;
		this.formatData = target.formatData;
  		this.defaultCenturyStart = target.defaultCenturyStart;
  		this.defaultCenturyStartYear = target.defaultCenturyStartYear;
		this.calendar = (Calendar)target.calendar.clone();
		this.calendar.setTimeZone(TimeZone.getDefault()); // might have changed since cached
		this.numberFormat = (NumberFormat)target.numberFormat.clone();
		return;
	    }
	}
  
        /* try the cache first */
        String[] dateTimePatterns = (String[]) cachedLocaleData.get(loc);
        if (dateTimePatterns == null) { /* cache miss */
            CalendarData calData = new CalendarData(new ULocale(loc), null); // TODO: type?
            // TODO: get correct actual/valid locale here
            ULocale uloc = calData.getULocale();
            setLocale(uloc, uloc);
            
            dateTimePatterns = calData.getStringArray("DateTimePatterns");
            /* update cache */
            cachedLocaleData.put(loc, dateTimePatterns);
        }
        formatData = new DateFormatSymbols(loc);
        if ((timeStyle >= 0) && (dateStyle >= 0)) {
            Object[] dateTimeArgs = {dateTimePatterns[timeStyle],
                                     dateTimePatterns[dateStyle + 4]};
            pattern = MessageFormat.format(dateTimePatterns[8], dateTimeArgs);
        }
        else if (timeStyle >= 0) {
            pattern = dateTimePatterns[timeStyle];
        }
        else if (dateStyle >= 0) {
            pattern = dateTimePatterns[dateStyle + 4];
        }
        else {
            throw new IllegalArgumentException("No date or time style specified");
        }

        initialize(loc);

	if (CACHE) {
//  	    if ("en_US22".equals(key))
//  		System.out.println("\nregister key: " + key + " pat: " + this.pattern +
//  				   " cal: " + this.calendar + " fmt: " + this.numberFormat);
	    map.put(key, this.clone()); // ok if we stomp existing target due to threading
	}
    }

    /* Initialize calendar and numberFormat fields */
    private void initialize(Locale loc) {
        // The format object must be constructed using the symbols for this zone.
        // However, the calendar should use the current default TimeZone.
        // If this is not contained in the locale zone strings, then the zone
        // will be formatted using generic GMT+/-H:MM nomenclature.
        calendar = Calendar.getInstance(TimeZone.getDefault(), loc);
        numberFormat = NumberFormat.getInstance(loc);
        numberFormat.setGroupingUsed(false);
        ///CLOVER:OFF
        // difficult to test for case where NumberFormat.getInstance does not 
        // return a DecimalFormat
        if (numberFormat instanceof DecimalFormat)
            ((DecimalFormat)numberFormat).setDecimalSeparatorAlwaysShown(false);
        ///CLOVER:ON
        numberFormat.setParseIntegerOnly(true); /* So that dd.MM.yy can be parsed */
        numberFormat.setMinimumFractionDigits(0); // To prevent "Jan 1.00, 1997.00"

        initializeDefaultCentury();

        // Currently, we only support fast formatting in SimpleDateFormat
        // itself.  TODO add constructor parameters to allow subclasses
        // to say that they implement fast formatting.
        useFastFormat = (getClass() == SimpleDateFormat.class);
    }

    /* Initialize the fields we use to disambiguate ambiguous years. Separate
     * so we can call it from readObject().
     */
    private void initializeDefaultCentury() {
        calendar.setTime( new Date() );
        calendar.add( Calendar.YEAR, -80 );
        parseAmbiguousDatesAsAfter(calendar.getTime());
    }

    /* Define one-century window into which to disambiguate dates using
     * two-digit years.
     */
    private void parseAmbiguousDatesAsAfter(Date startDate) {
        defaultCenturyStart = startDate;
        calendar.setTime(startDate);
        defaultCenturyStartYear = calendar.get(Calendar.YEAR);
    }

    /**
     * Sets the 100-year period 2-digit years will be interpreted as being in
     * to begin on the date the user specifies.
     * @param startDate During parsing, two digit years will be placed in the range
     * <code>startDate</code> to <code>startDate + 100 years</code>.
     * @stable ICU 2.0
     */
    public void set2DigitYearStart(Date startDate) {
        parseAmbiguousDatesAsAfter(startDate);
    }

    /**
     * Returns the beginning date of the 100-year period 2-digit years are interpreted
     * as being within.
     * @return the start of the 100-year period into which two digit years are
     * parsed
     * @stable ICU 2.0
     */
    public Date get2DigitYearStart() {
        return defaultCenturyStart;
    }

    /**
     * Overrides DateFormat.
     * <p>Formats a date or time, which is the standard millis
     * since January 1, 1970, 00:00:00 GMT.
     * <p>Example: using the US locale:
     * "yyyy.MM.dd G 'at' HH:mm:ss zzz" ->> 1996.07.10 AD at 15:08:56 PDT
     * @param cal the calendar whose date-time value is to be formatted into a date-time string
     * @param toAppendTo where the new date-time text is to be appended
     * @param pos the formatting position. On input: an alignment field,
     * if desired. On output: the offsets of the alignment field.
     * @return the formatted date-time string.
     * @see DateFormat
     * @stable ICU 2.0
     */
    public StringBuffer format(Calendar cal, StringBuffer toAppendTo,
                               FieldPosition pos) {
        if (!useFastFormat) {
            return slowFormat(cal, toAppendTo, pos);
        }

        // Initialize
        pos.setBeginIndex(0);
        pos.setEndIndex(0);

        // Careful: For best performance, minimize the number of calls
        // to StringBuffer.append() by consolidating appends when
        // possible.

        int j, n = pattern.length();
        for (int i=0; i<n; ) {
            char ch = pattern.charAt(i);
            if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
                // ch is a date-time pattern character to be interpreted
                // by subFormat(); count the number of times it is repeated
                for (j=i+1; j<n && pattern.charAt(j)==ch; ++j) {}
                subFormat(toAppendTo, ch, j-i, toAppendTo.length(), pos, cal);
                i = j;
            } else if (ch == '\'') {
                // Handle an entire quoted string, included embedded
                // doubled apostrophes (as in 'o''clock').
                int start = i+1;
                for (;;) {
                    ++i; // i points after '
                    if (i==n) { // trailing ' (pathological)
                        break;
                    }
                
                    for (j=i; j<n && pattern.charAt(j)!='\''; ++j) {}
                    // j points to next ' or EOS

                    if (j==start) { // '' outside of quotes
                        toAppendTo.append('\'');
                        ++i;
                        break;
                    }

                    // look ahead to detect '' within quotes
                    int k = j, jj = j+1;
                    if (jj<n && pattern.charAt(jj)=='\'') {
                        ++k;
                    }
                    
                    // append this run, and if there is '' within
                    // quotes, append a trailing ' as well
                    toAppendTo.append(pattern.substring(i, k));

                    i = jj;

                    if (k==j) {
                        break;
                    }
                }
            } else {
                // Append unquoted literal characters
                toAppendTo.append(ch);
                ++i;
            }
        }

        return toAppendTo;
    }

    private StringBuffer slowFormat(Calendar cal, StringBuffer toAppendTo,
                                    FieldPosition pos) {
        // Initialize
        pos.setBeginIndex(0);
        pos.setEndIndex(0);

        boolean inQuote = false; // true when between single quotes
        char prevCh = 0; // previous pattern character
        int count = 0;  // number of time prevCh repeated
        for (int i=0; i<pattern.length(); ++i) {
            char ch = pattern.charAt(i);
            // Use subFormat() to format a repeated pattern character
            // when a different pattern or non-pattern character is seen
            if (ch != prevCh && count > 0) {
                toAppendTo.append(
                                  subFormat(prevCh, count, toAppendTo.length(), pos, formatData, cal));
                count = 0;
            }
            if (ch == '\'') {
                // Consecutive single quotes are a single quote literal,
                // either outside of quotes or between quotes
                if ((i+1)<pattern.length() && pattern.charAt(i+1) == '\'') {
                    toAppendTo.append('\'');
                    ++i;
                } else {
                    inQuote = !inQuote;
                }
            } else if (!inQuote
                       && (ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z')) {
                // ch is a date-time pattern character to be interpreted
                // by subFormat(); count the number of times it is repeated
                prevCh = ch;
                ++count;
            }
            else {
                // Append quoted characters and unquoted non-pattern characters
                toAppendTo.append(ch);
            }
        }
        // Format the last item in the pattern, if any
        if (count > 0) {
            toAppendTo.append(
                              subFormat(prevCh, count, toAppendTo.length(), pos, formatData, cal));
        }
        return toAppendTo;
    }

    // Map index into pattern character string to Calendar field number
    private static final int[] PATTERN_INDEX_TO_CALENDAR_FIELD =
    {
        /*GyM*/ Calendar.ERA, Calendar.YEAR, Calendar.MONTH,
        /*dkH*/ Calendar.DATE, Calendar.HOUR_OF_DAY, Calendar.HOUR_OF_DAY,
        /*msS*/ Calendar.MINUTE, Calendar.SECOND, Calendar.MILLISECOND,
        /*EDF*/ Calendar.DAY_OF_WEEK, Calendar.DAY_OF_YEAR, Calendar.DAY_OF_WEEK_IN_MONTH,
        /*wWa*/ Calendar.WEEK_OF_YEAR, Calendar.WEEK_OF_MONTH, Calendar.AM_PM,
        /*hKz*/ Calendar.HOUR, Calendar.HOUR, Calendar.ZONE_OFFSET,
        /*Yeu*/ Calendar.YEAR_WOY, Calendar.DOW_LOCAL, Calendar.EXTENDED_YEAR,
        /*gAZ*/ Calendar.JULIAN_DAY, Calendar.MILLISECONDS_IN_DAY, Calendar.ZONE_OFFSET
    };

    // Map index into pattern character string to DateFormat field number
    private static final int[] PATTERN_INDEX_TO_DATE_FORMAT_FIELD = {
        /*GyM*/ DateFormat.ERA_FIELD, DateFormat.YEAR_FIELD, DateFormat.MONTH_FIELD,
        /*dkH*/ DateFormat.DATE_FIELD, DateFormat.HOUR_OF_DAY1_FIELD, DateFormat.HOUR_OF_DAY0_FIELD,
        /*msS*/ DateFormat.MINUTE_FIELD, DateFormat.SECOND_FIELD, DateFormat.FRACTIONAL_SECOND_FIELD,
        /*EDF*/ DateFormat.DAY_OF_WEEK_FIELD, DateFormat.DAY_OF_YEAR_FIELD, DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD,
        /*wWa*/ DateFormat.WEEK_OF_YEAR_FIELD, DateFormat.WEEK_OF_MONTH_FIELD, DateFormat.AM_PM_FIELD,
        /*hKz*/ DateFormat.HOUR1_FIELD, DateFormat.HOUR0_FIELD, DateFormat.TIMEZONE_FIELD,
        /*Yeu*/ DateFormat.YEAR_WOY_FIELD, DateFormat.DOW_LOCAL_FIELD, DateFormat.EXTENDED_YEAR_FIELD,
        /*gAZ*/ DateFormat.JULIAN_DAY_FIELD, DateFormat.MILLISECONDS_IN_DAY_FIELD, DateFormat.TIMEZONE_RFC_FIELD
    };

    /**
     * Format a single field, given its pattern character.  Subclasses may
     * override this method in order to modify or add formatting
     * capabilities.
     * @param ch the pattern character
     * @param count the number of times ch is repeated in the pattern
     * @param beginOffset the offset of the output string at the start of
     * this field; used to set pos when appropriate
     * @param pos receives the position of a field, when appropriate
     * @param formatData the symbols for this formatter
     * @stable ICU 2.0
     */
    protected String subFormat(char ch, int count, int beginOffset,
                               FieldPosition pos, DateFormatSymbols formatData,
                               Calendar cal)
        throws IllegalArgumentException
    {
        // Note: formatData is ignored
        StringBuffer buf = new StringBuffer();
        subFormat(buf, ch, count, beginOffset, pos, cal);
        return buf.toString();
    }

    /**
     * Format a single field; useFastFormat variant.  Reuses a
     * StringBuffer for results instead of creating a String on the
     * heap for each call.
     *
     * NOTE We don't really need the beginOffset parameter, EXCEPT for
     * the need to support the slow subFormat variant (above) which
     * has to pass it in to us.
     *
     * TODO make this API public
     *
     * @internal
     */
    protected void subFormat(StringBuffer buf,
                             char ch, int count, int beginOffset,
                             FieldPosition pos,
                             Calendar cal) {
        final int maxIntCount = Integer.MAX_VALUE;
        final int bufstart = buf.length();

        final int patternCharIndex = DateFormatSymbols.patternChars.indexOf(ch);
        if (patternCharIndex == -1) {
            throw new IllegalArgumentException("Illegal pattern character " +
                                               "'" + ch + "' in \"" +
                                               new String(pattern) + '"');
        }

        final int field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex];
        int value = cal.get(field);

        switch (patternCharIndex) {
        case 0: // 'G' - ERA
            buf.append(formatData.eras[value]);
            break;
        case 1: // 'y' - YEAR
            /* According to the specification, if the number of pattern letters ('y') is 2, 
             * the year is truncated to 2 digits; otherwise it is interpreted as a number. 
             * But the original code process 'y', 'yy', 'yyy' in the same way. and process 
             * patterns with 4 or more than 4 'y' characters in the same way. 
             * So I change the codes to meet the specification. [Richard/GCl]
             */
            if (count == 2)
                zeroPaddingNumber(buf, value, 2, 2); // clip 1996 to 96
            else //count = 1 or count > 2
                zeroPaddingNumber(buf, value, count, maxIntCount);
            break;
        case 2: // 'M' - MONTH
            if (count >= 4)
                buf.append(formatData.months[value]);
            else if (count == 3)
                buf.append(formatData.shortMonths[value]);
            else
                zeroPaddingNumber(buf, value+1, count, maxIntCount);
            break;
        case 4: // 'k' - HOUR_OF_DAY (1..24)
            if (value == 0)
                zeroPaddingNumber(buf, 
                                  cal.getMaximum(Calendar.HOUR_OF_DAY)+1,
                                  count, maxIntCount);
            else
                zeroPaddingNumber(buf, value, count, maxIntCount);
            break;
        case 8: // 'S' - FRACTIONAL_SECOND
            // Fractional seconds left-justify
            {
                numberFormat.setMinimumIntegerDigits(Math.min(3, count));
                numberFormat.setMaximumIntegerDigits(maxIntCount);
                if (count == 1) {
                    value = (value + 50) / 100;
                } else if (count == 2) {
                    value = (value + 5) / 10;
                }
                FieldPosition p = new FieldPosition(-1);
                numberFormat.format((long) value, buf, p);
                if (count > 3) {
                    numberFormat.setMinimumIntegerDigits(count - 3);
                    numberFormat.format(0L, buf, p);
                }
            }
            break;
        case 9: // 'E' - DAY_OF_WEEK
            if (count >= 4)
                buf.append(formatData.weekdays[value]);
            else // count < 4, use abbreviated form if exists
                buf.append(formatData.shortWeekdays[value]);
            break;
        case 14: // 'a' - AM_PM
            buf.append(formatData.ampms[value]);
            break;
        case 15: // 'h' - HOUR (1..12)
            if (value == 0)
                zeroPaddingNumber(buf, 
                                  cal.getLeastMaximum(Calendar.HOUR)+1,
                                  count, maxIntCount);
            else
                zeroPaddingNumber(buf, value, count, maxIntCount);
            break;
        case 17: // 'z' - ZONE_OFFSET
            int zoneIndex
                = formatData.getZoneIndex (cal.getTimeZone().getID());
            if (zoneIndex == -1)
            {
                // For time zones that have no names, use strings
                // GMT+hours:minutes and GMT-hours:minutes.
                // For instance, France time zone uses GMT+01:00.
                value = cal.get(Calendar.ZONE_OFFSET) +
                    cal.get(Calendar.DST_OFFSET);

                if (value < 0)
                {
                    buf.append(GMT_MINUS);
                    value = -value; // suppress the '-' sign for text display.
                }
                else
                    buf.append(GMT_PLUS);
                zeroPaddingNumber(buf, (int)(value/millisPerHour), 2, 2);
                buf.append(':');
                zeroPaddingNumber(buf, (int)((value%millisPerHour)/millisPerMinute), 2, 2);
            }
            else if (cal.get(Calendar.DST_OFFSET) != 0)
            {
                if (count >= 4)
                    buf.append(formatData.zoneStrings[zoneIndex][3]);
                else
                    // count < 4, use abbreviated form if exists
                    buf.append(formatData.zoneStrings[zoneIndex][4]);
            }
            else
            {
                if (count >= 4)
                    buf.append(formatData.zoneStrings[zoneIndex][1]);
                else
                    buf.append(formatData.zoneStrings[zoneIndex][2]);
            }
            break;
        case 23: // 'Z' - TIMEZONE_RFC
            {
                char sign = '+';
                value = (cal.get(Calendar.ZONE_OFFSET) +
                         cal.get(Calendar.DST_OFFSET)) / millisPerMinute;
                if (value < 0) {
                    value = -value;
                    sign = '-';
                }
                value = (value / 3) * 5 + (value % 60); // minutes => KKmm
                buf.append(sign);
                zeroPaddingNumber(buf, value, 4, 4);
            }
            break;
        default:
            // case 3: // 'd' - DATE
            // case 5: // 'H' - HOUR_OF_DAY (0..23)
            // case 6: // 'm' - MINUTE
            // case 7: // 's' - SECOND
            // case 10: // 'D' - DAY_OF_YEAR
            // case 11: // 'F' - DAY_OF_WEEK_IN_MONTH
            // case 12: // 'w' - WEEK_OF_YEAR
            // case 13: // 'W' - WEEK_OF_MONTH
            // case 16: // 'K' - HOUR (0..11)
            // case 18: // 'Y' - YEAR_WOY
            // case 19: // 'e' - DOW_LOCAL
            // case 20: // 'u' - EXTENDED_YEAR
            // case 21: // 'g' - JULIAN_DAY
            // case 22: // 'A' - MILLISECONDS_IN_DAY

            zeroPaddingNumber(buf, value, count, maxIntCount);
            break;
        } // switch (patternCharIndex)

        // Set the FieldPosition (for the first occurence only)
        if (pos.getBeginIndex() == pos.getEndIndex() &&
            pos.getField() == PATTERN_INDEX_TO_DATE_FORMAT_FIELD[patternCharIndex]) {
            pos.setBeginIndex(beginOffset);
            pos.setEndIndex(beginOffset + buf.length() - bufstart);
        }
    }

    /**
     * Internal high-speed method.  Reuses a StringBuffer for results
     * instead of creating a String on the heap for each call.
     * @internal
     */
    protected void zeroPaddingNumber(StringBuffer buf, int value,
                                     int minDigits, int maxDigits) {
        FieldPosition pos = new FieldPosition(-1);
        numberFormat.setMinimumIntegerDigits(minDigits);
        numberFormat.setMaximumIntegerDigits(maxDigits);
        numberFormat.format(value, buf, pos);
    }

    /**
     * Formats a number with the specified minimum and maximum number of digits.
     * @stable ICU 2.0
     */
    protected String zeroPaddingNumber(long value, int minDigits, int maxDigits)
    {
        numberFormat.setMinimumIntegerDigits(minDigits);
        numberFormat.setMaximumIntegerDigits(maxDigits);
        return numberFormat.format(value);
    }

    /**
     * Format characters that indicate numeric fields.  The character
     * at index 0 is treated specially.
     */
    private static final String NUMERIC_FORMAT_CHARS = "MyudhHmsSDFwWkK";

    /**
     * Return true if the given format character, occuring count
     * times, represents a numeric field.
     */
    private static final boolean isNumeric(char formatChar, int count) {
        int i = NUMERIC_FORMAT_CHARS.indexOf(formatChar);
        return (i > 0 || (i == 0 && count < 3));
    }

    /**
     * Overrides DateFormat
     * @see DateFormat
     * @stable ICU 2.0
     */
    public void parse(String text, Calendar cal, ParsePosition parsePos)
    {
        int pos = parsePos.getIndex();
        int start = pos;
        boolean[] ambiguousYear = {false};
        int count = 0;

        // For parsing abutting numeric fields. 'abutPat' is the
        // offset into 'pattern' of the first of 2 or more abutting
        // numeric fields.  'abutStart' is the offset into 'text'
        // where parsing the fields begins. 'abutPass' starts off as 0
        // and increments each time we try to parse the fields.
        int abutPat = -1; // If >=0, we are in a run of abutting numeric fields
        int abutStart = 0;
        int abutPass = 0;
        boolean inQuote = false;

        for (int i=0; i<pattern.length(); ++i) {
            char ch = pattern.charAt(i);

            // Handle alphabetic field characters.
            if (!inQuote && (ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z')) {
                int fieldPat = i;

                // Count the length of this field specifier
                count = 1;
                while ((i+1)<pattern.length() &&
                       pattern.charAt(i+1) == ch) {
                    ++count;
                    ++i;
                }

                if (isNumeric(ch, count)) {
                    if (abutPat < 0) {
                        // Determine if there is an abutting numeric field.  For
                        // most fields we can just look at the next characters,
                        // but the 'm' field is either numeric or text,
                        // depending on the count, so we have to look ahead for
                        // that field.
                        if ((i+1)<pattern.length()) {
                            boolean abutting;
                            char nextCh = pattern.charAt(i+1);
                            int k = NUMERIC_FORMAT_CHARS.indexOf(nextCh);
                            if (k == 0) {
                                int j = i+2;
                                while (j<pattern.length() &&
                                       pattern.charAt(j) == nextCh) {
                                    ++j;
                                }
                                abutting = (j-i) < 4; // nextCount < 3
                            } else {
                                abutting = k > 0;
                            }

                            // Record the start of a set of abutting numeric
                            // fields.
                            if (abutting) {
                                abutPat = fieldPat;
                                abutStart = pos;
                                abutPass = 0;
                            }
                        }
                    }
                } else {
                    abutPat = -1; // End of any abutting fields
                }

                // Handle fields within a run of abutting numeric fields.  Take
                // the pattern "HHmmss" as an example. We will try to parse
                // 2/2/2 characters of the input text, then if that fails,
                // 1/2/2.  We only adjust the width of the leftmost field; the
                // others remain fixed.  This allows "123456" => 12:34:56, but
                // "12345" => 1:23:45.  Likewise, for the pattern "yyyyMMdd" we
                // try 4/2/2, 3/2/2, 2/2/2, and finally 1/2/2.
                if (abutPat >= 0) {
                    // If we are at the start of a run of abutting fields, then
                    // shorten this field in each pass.  If we can't shorten
                    // this field any more, then the parse of this set of
                    // abutting numeric fields has failed.
                    if (fieldPat == abutPat) {
                        count -= abutPass++;
                        if (count == 0) {
                            parsePos.setIndex(start);
                            parsePos.setErrorIndex(pos);
                            return;
                        }
                    }

                    pos = subParse(text, pos, ch, count,
                                   true, false, ambiguousYear, cal);

                    // If the parse fails anywhere in the run, back up to the
                    // start of the run and retry.
                    if (pos < 0) {
                        i = abutPat - 1;
                        pos = abutStart;
                        continue;
                    }
                }

                // Handle non-numeric fields and non-abutting numeric
                // fields.
                else {
                    int s = pos;
                    pos = subParse(text, pos, ch, count,
                                   false, true, ambiguousYear, cal);

                    if (pos < 0) {
                        parsePos.setErrorIndex(s);
                        parsePos.setIndex(start);
                        return;
                    }
                }
            }

            // Handle literal pattern characters.  These are any
            // quoted characters and non-alphabetic unquoted
            // characters.
            else {
                
                abutPat = -1; // End of any abutting fields

                // Handle quotes.  Two consecutive quotes is a quote
                // literal, inside or outside of quotes.  Otherwise a
                // quote indicates entry or exit from a quoted region.
                if (ch == '\'') {
                    // Match a quote literal '' within OR outside of quotes
                    if ((i+1)<pattern.length() && pattern.charAt(i+1)==ch) {
                        ++i; // Skip over doubled quote
                        // Fall through and treat quote as a literal
                    } else {
                        // Enter or exit quoted region
                        inQuote = !inQuote;
                        continue;
                    }
                }

                // A run of white space in the pattern matches a run
                // of white space in the input text.
                if (UCharacterProperty.isRuleWhiteSpace(ch)) {
                    // Advance over run in pattern
                    while ((i+1)<pattern.length() &&
                           UCharacterProperty.isRuleWhiteSpace(pattern.charAt(i+1))) {
                        ++i;
                    }
                    
                    // Advance over run in input text
                    int s = pos;
                    while (pos<text.length() &&
                           UCharacter.isUWhiteSpace(text.charAt(pos))) {
                        ++pos;
                    }

                    // Must see at least one white space char in input
                    if (pos > s) {
                        continue;
                    }
                } else if (pos<text.length() && text.charAt(pos)==ch) {
                    // Match a literal
                    ++pos;
                    continue;
                }

                // We fall through to this point if the match fails
                parsePos.setIndex(start);
                parsePos.setErrorIndex(pos);
                return;
            }
        }

        // At this point the fields of Calendar have been set.  Calendar
        // will fill in default values for missing fields when the time
        // is computed.

        parsePos.setIndex(pos);

        // This part is a problem:  When we call parsedDate.after, we compute the time.
        // Take the date April 3 2004 at 2:30 am.  When this is first set up, the year
        // will be wrong if we're parsing a 2-digit year pattern.  It will be 1904.
        // April 3 1904 is a Sunday (unlike 2004) so it is the DST onset day.  2:30 am
        // is therefore an "impossible" time, since the time goes from 1:59 to 3:00 am
        // on that day.  It is therefore parsed out to fields as 3:30 am.  Then we
        // add 100 years, and get April 3 2004 at 3:30 am.  Note that April 3 2004 is
        // a Saturday, so it can have a 2:30 am -- and it should. [LIU]
        /*
          Date parsedDate = cal.getTime();
          if( ambiguousYear[0] && !parsedDate.after(defaultCenturyStart) ) {
          cal.add(Calendar.YEAR, 100);
          parsedDate = cal.getTime();
          }
        */
        // Because of the above condition, save off the fields in case we need to readjust.
        // The procedure we use here is not particularly efficient, but there is no other
        // way to do this given the API restrictions present in Calendar.  We minimize
        // inefficiency by only performing this computation when it might apply, that is,
        // when the two-digit year is equal to the start year, and thus might fall at the
        // front or the back of the default century.  This only works because we adjust
        // the year correctly to start with in other cases -- see subParse().
        try {
            if (ambiguousYear[0]) // If this is true then the two-digit year == the default start year
            {
                // We need a copy of the fields, and we need to avoid triggering a call to
                // complete(), which will recalculate the fields.  Since we can't access
                // the fields[] array in Calendar, we clone the entire object.  This will
                // stop working if Calendar.clone() is ever rewritten to call complete().
                Calendar copy = (Calendar)cal.clone();
                Date parsedDate = copy.getTime();
                if (parsedDate.before(defaultCenturyStart))
                {
                    // We can't use add here because that does a complete() first.
                    cal.set(Calendar.YEAR, defaultCenturyStartYear + 100);
                }
            }
        }
        // An IllegalArgumentException will be thrown by Calendar.getTime()
        // if any fields are out of range, e.g., MONTH == 17.
        catch (IllegalArgumentException e) {
            parsePos.setErrorIndex(pos);
            parsePos.setIndex(start);
        }
    }

    /**
     * Attempt to match the text at a given position against an array of
     * strings.  Since multiple strings in the array may match (for
     * example, if the array contains "a", "ab", and "abc", all will match
     * the input string "abcd") the longest match is returned.  As a side
     * effect, the given field of <code>cal</code> is set to the index
     * of the best match, if there is one.
     * @param text the time text being parsed.
     * @param start where to start parsing.
     * @param field the date field being parsed.
     * @param data the string array to parsed.
     * @return the new start position if matching succeeded; a negative
     * number indicating matching failure, otherwise.  As a side effect,
     * sets the <code>cal</code> field <code>field</code> to the index
     * of the best match, if matching succeeded.
     * @stable ICU 2.0
     */
    protected int matchString(String text, int start, int field, String[] data, Calendar cal)
    {
        int i = 0;
        int count = data.length;

        if (field == Calendar.DAY_OF_WEEK) i = 1;

        // There may be multiple strings in the data[] array which begin with
        // the same prefix (e.g., Cerven and Cervenec (June and July) in Czech).
        // We keep track of the longest match, and return that.  Note that this
        // unfortunately requires us to test all array elements.
        int bestMatchLength = 0, bestMatch = -1;
        for (; i<count; ++i)
        {
            int length = data[i].length();
            // Always compare if we have no match yet; otherwise only compare
            // against potentially better matches (longer strings).
            if (length > bestMatchLength &&
                text.regionMatches(true, start, data[i], 0, length))
            {
                bestMatch = i;
                bestMatchLength = length;
            }
        }
        if (bestMatch >= 0)
        {
            cal.set(field, bestMatch);
            return start + bestMatchLength;
        }
        return -start;
    }

    private int matchZoneString(String text, int start, int zoneIndex) {
        int j;
        for (j = 1; j <= 4; ++j) {
            // Checking long and short zones [1 & 2],
            // and long and short daylight [3 & 4].
            if (text.regionMatches(true, start,
                                   formatData.zoneStrings[zoneIndex][j], 0,
                                   formatData.zoneStrings[zoneIndex][j].length())) {
                break;
            }
        }
        return (j > 4) ? -1 : j;
    }   

    /**
     * find time zone 'text' matched zoneStrings and set cal
     */
    private int subParseZoneString(String text, int start, Calendar cal) {
        // At this point, check for named time zones by looking through
        // the locale data from the DateFormatZoneData strings.
        // Want to be able to parse both short and long forms.
        int zoneIndex = 
            formatData.getZoneIndex (getTimeZone().getID());
        TimeZone tz = null;
        int j = 0, i = 0;
        if (zoneIndex != -1) {
            j = matchZoneString(text, start, zoneIndex);
            if (j > 0) {
        	tz = TimeZone.getTimeZone(formatData.zoneStrings[zoneIndex][0]);
        	i = zoneIndex;
            }
        }
    
        if (tz == null) {
            zoneIndex = 
                formatData.getZoneIndex (TimeZone.getDefault().getID());
            if (zoneIndex != -1) {
        	j = matchZoneString(text, start, zoneIndex);
        	if (j > 0) {
                    tz = TimeZone.getTimeZone(formatData.zoneStrings[zoneIndex][0]);
                    i = zoneIndex;
        	}
            }
        }       

        if (tz == null) {
            for (i = 0; i < formatData.zoneStrings.length; i++) {
                j = matchZoneString(text, start, i);
        	if (j > 0) {
                    tz = TimeZone.getTimeZone(formatData.zoneStrings[i][0]);
                    break;
        	}
            }
        }
    
        if (tz != null) { // Matched any ?
            cal.set(Calendar.ZONE_OFFSET, tz.getRawOffset());
            int savings = 0;
            if (j >= 3) {
        	savings = tz.getDSTSavings();
            }
            cal.set(Calendar.DST_OFFSET, savings);
            return (start + formatData.zoneStrings[i][j].length());
        }
        return 0;
    }

    /**
     * Protected method that converts one field of the input string into a
     * numeric field value in <code>cal</code>.  Returns -start (for
     * ParsePosition) if failed.  Subclasses may override this method to
     * modify or add parsing capabilities.
     * @param text the time text to be parsed.
     * @param start where to start parsing.
     * @param ch the pattern character for the date field text to be parsed.
     * @param count the count of a pattern character.
     * @param obeyCount if true, then the next field directly abuts this one,
     * and we should use the count to know when to stop parsing.
     * @param ambiguousYear return parameter; upon return, if ambiguousYear[0]
     * is true, then a two-digit year was parsed and may need to be readjusted.
     * @return the new start position if matching succeeded; a negative
     * number indicating matching failure, otherwise.  As a side effect,
     * set the appropriate field of <code>cal</code> with the parsed
     * value.
     * @stable ICU 2.0
     */
    protected int subParse(String text, int start, char ch, int count,
                           boolean obeyCount, boolean allowNegative,
                           boolean[] ambiguousYear, Calendar cal)
    {
        Number number = null;
        int value = 0;
        int i;
        ParsePosition pos = new ParsePosition(0);
        int patternCharIndex = DateFormatSymbols.patternChars.indexOf(ch);

        if (patternCharIndex == -1) {
            return -start;
        }

        int field = PATTERN_INDEX_TO_CALENDAR_FIELD[patternCharIndex];

        // If there are any spaces here, skip over them.  If we hit the end
        // of the string, then fail.
        for (;;) {
            if (start >= text.length()) {
                return -start;
            }
            int c = UTF16.charAt(text, start);
            if (!UCharacter.isUWhiteSpace(c)) {
                break;
            }
            start += UTF16.getCharCount(c);
        }
        pos.setIndex(start);

        // We handle a few special cases here where we need to parse
        // a number value.  We handle further, more generic cases below.  We need
        // to handle some of them here because some fields require extra processing on
        // the parsed value.
        if (patternCharIndex == 4 /*HOUR_OF_DAY1_FIELD*/ ||
            patternCharIndex == 15 /*HOUR1_FIELD*/ ||
            (patternCharIndex == 2 /*MONTH_FIELD*/ && count <= 2) ||
            patternCharIndex == 1 ||
            patternCharIndex == 8)
        {
            // It would be good to unify this with the obeyCount logic below,
            // but that's going to be difficult.
            if (obeyCount)
            {
                if ((start+count) > text.length()) return -start;
                number = parseInt(text.substring(0, start+count), pos, allowNegative);
            }
            else number = parseInt(text, pos, allowNegative);
            if (number == null)
                return -start;
            value = number.intValue();
        }

        switch (patternCharIndex)
        {
        case 0: // 'G' - ERA
            return matchString(text, start, Calendar.ERA, formatData.eras, cal);
        case 1: // 'y' - YEAR
            // If there are 3 or more YEAR pattern characters, this indicates
            // that the year value is to be treated literally, without any
            // two-digit year adjustments (e.g., from "01" to 2001).  Otherwise
            // we made adjustments to place the 2-digit year in the proper
            // century, for parsed strings from "00" to "99".  Any other string
            // is treated literally:  "2250", "-1", "1", "002".
            /* 'yy' is the only special case, 'y' is interpreted as number. [Richard/GCL]*/
            if (count == 2 && (pos.getIndex() - start) == 2
                && Character.isDigit(text.charAt(start))
                && Character.isDigit(text.charAt(start+1)))
            {
                // Assume for example that the defaultCenturyStart is 6/18/1903.
                // This means that two-digit years will be forced into the range
                // 6/18/1903 to 6/17/2003.  As a result, years 00, 01, and 02
                // correspond to 2000, 2001, and 2002.  Years 04, 05, etc. correspond
                // to 1904, 1905, etc.  If the year is 03, then it is 2003 if the
                // other fields specify a date before 6/18, or 1903 if they specify a
                // date afterwards.  As a result, 03 is an ambiguous year.  All other
                // two-digit years are unambiguous.
                int ambiguousTwoDigitYear = defaultCenturyStartYear % 100;
                ambiguousYear[0] = value == ambiguousTwoDigitYear;
                value += (defaultCenturyStartYear/100)*100 +
                    (value < ambiguousTwoDigitYear ? 100 : 0);
            }
            cal.set(Calendar.YEAR, value);
            return pos.getIndex();
        case 2: // 'M' - MONTH
            if (count <= 2) // i.e., M or MM.
            {
                // Don't want to parse the month if it is a string
                // while pattern uses numeric style: M or MM.
                // [We computed 'value' above.]
                cal.set(Calendar.MONTH, value - 1);
                return pos.getIndex();
            }
            else
            {
                // count >= 3 // i.e., MMM or MMMM
                // Want to be able to parse both short and long forms.
                // Try count == 4 first:
                int newStart = matchString(text, start, Calendar.MONTH,
                                           formatData.months, cal);
                if (newStart > 0) {
                    return newStart;
                } else { // count == 4 failed, now try count == 3
                    return matchString(text, start, Calendar.MONTH,
                                       formatData.shortMonths, cal);
                }
            }
        case 4: // 'k' - HOUR_OF_DAY (1..24)
            // [We computed 'value' above.]
            if (value == cal.getMaximum(Calendar.HOUR_OF_DAY)+1) value = 0;
            cal.set(Calendar.HOUR_OF_DAY, value);
            return pos.getIndex();
        case 8: // 'S' - FRACTIONAL_SECOND
            // Fractional seconds left-justify
            i = pos.getIndex() - start;
            if (i < 3) {
                while (i < 3) {
                    value *= 10;
                    i++;
                }
            } else {
                int a = 1;
                while (i > 3) {
                    a *= 10;
                    i--;
                }
                value = (value + (a>>1)) / a;
            }
            cal.set(Calendar.MILLISECOND, value);
            return pos.getIndex();
        case 9: { // 'E' - DAY_OF_WEEK
            // Want to be able to parse both short and long forms.
            // Try count == 4 (DDDD) first:
            int newStart = matchString(text, start, Calendar.DAY_OF_WEEK,
                                       formatData.weekdays, cal);
            if (newStart > 0) {
                return newStart;
            } else { // DDDD failed, now try DDD
                return matchString(text, start, Calendar.DAY_OF_WEEK,
                                   formatData.shortWeekdays, cal);
            }
        }
        case 14: // 'a' - AM_PM
            return matchString(text, start, Calendar.AM_PM, formatData.ampms, cal);
        case 15: // 'h' - HOUR (1..12)
            // [We computed 'value' above.]
            if (value == cal.getLeastMaximum(Calendar.HOUR)+1) value = 0;
            cal.set(Calendar.HOUR, value);
            return pos.getIndex();
        case 17: // 'z' - ZONE_OFFSET
        case 23: // 'Z' - TIMEZONE_RFC
            // First try to parse generic forms such as GMT-07:00. Do this first
            // in case localized DateFormatZoneData contains the string "GMT"
            // for a zone; in that case, we don't want to match the first three
            // characters of GMT+/-HH:MM etc.
            {
                int sign = 0;
                int offset;

                // For time zones that have no known names, look for strings
                // of the form:
                //    GMT[+-]hours:minutes or
                //    GMT[+-]hhmm or
                //    GMT.
                if ((text.length() - start) >= GMT.length() &&
                    text.regionMatches(true, start, GMT, 0, GMT.length()))
                {
                    cal.set(Calendar.DST_OFFSET, 0);

                    pos.setIndex(start + GMT.length());

                    try { // try-catch for "GMT" only time zone string
                        switch (text.charAt(pos.getIndex())) {
                        case '+':
                            sign = 1;
                            break;
                        case '-':
                            sign = -1;
                            break;
                        }
                    } catch(StringIndexOutOfBoundsException e) {
                    }
                    if (sign == 0) {
                        cal.set(Calendar.ZONE_OFFSET, 0 );
                        return pos.getIndex();
                    }

                    // Look for hours:minutes or hhmm.
                    pos.setIndex(pos.getIndex() + 1);
                    int st = pos.getIndex();
                    Number tzNumber = numberFormat.parse(text, pos);
                    if( tzNumber == null) {
                        return -start;
                    }
                    if( pos.getIndex() < text.length() &&
                    	text.charAt(pos.getIndex()) == ':' ) {
                    		
                        // This is the hours:minutes case
                        offset = tzNumber.intValue() * 60;
                        pos.setIndex(pos.getIndex() + 1);
                        tzNumber = numberFormat.parse(text, pos);
                        if( tzNumber == null) {
                            return -start;
                        }
                        offset += tzNumber.intValue();
                    }
                    else {
                        // This is the hhmm case.
                        offset = tzNumber.intValue();
                        // Assume "-23".."+23" refers to hours.
                        if( offset < 24 && (pos.getIndex() - st) <= 2)
                            offset *= 60;
                        else
                            // todo: this looks questionable, should have more error checking
                            offset = offset % 100 + offset / 100 * 60;
                    }

                    // Fall through for final processing below of 'offset' and 'sign'.
                }
                else {
                    // At this point, check for named time zones by looking through
                    // the locale data from the DateFormatZoneData strings.
                    // Want to be able to parse both short and long forms.
                    i = subParseZoneString(text, start, cal);
                    if (i != 0)
                        return i;

                    // As a last resort, look for numeric timezones of the form
                    // [+-]hhmm as specified by RFC 822.  This code is actually
                    // a little more permissive than RFC 822.  It will try to do
                    // its best with numbers that aren't strictly 4 digits long.
                    DecimalFormat fmt = new DecimalFormat("+####;-####");
                    fmt.setParseIntegerOnly(true);
                    Number tzNumber = fmt.parse( text, pos );
                    if( tzNumber == null) {
                        return -start;   // Wasn't actually a number.
                    }
                    offset = tzNumber.intValue();
                    sign = 1;
                    if( offset < 0 ) {
                        sign = -1;
                        offset = -offset;
                    }
                    // Assume "-23".."+23" refers to hours. Length includes sign.
                    if( offset < 24 && (pos.getIndex() - start) <= 3)
                        offset = offset * 60;
                    else
                        offset = offset % 100 + offset / 100 * 60;

                    // Fall through for final processing below of 'offset' and 'sign'.
                }

                // Do the final processing for both of the above cases.  We only
                // arrive here if the form GMT+/-... or an RFC 822 form was seen.

                // assert (sign != 0) : sign; // enable when guaranteed JDK >= 1.4
                offset *= millisPerMinute * sign;

                if (cal.getTimeZone().useDaylightTime())
                {
                    cal.set(Calendar.DST_OFFSET, millisPerHour);
                    offset -= millisPerHour;
                }
                cal.set(Calendar.ZONE_OFFSET, offset);

                return pos.getIndex();
            }

        default:
            // case 3: // 'd' - DATE
            // case 5: // 'H' - HOUR_OF_DAY (0..23)
            // case 6: // 'm' - MINUTE
            // case 7: // 's' - SECOND
            // case 10: // 'D' - DAY_OF_YEAR
            // case 11: // 'F' - DAY_OF_WEEK_IN_MONTH
            // case 12: // 'w' - WEEK_OF_YEAR
            // case 13: // 'W' - WEEK_OF_MONTH
            // case 16: // 'K' - HOUR (0..11)
            // case 18: // 'Y' - YEAR_WOY
            // case 19: // 'e' - DOW_LOCAL
            // case 20: // 'u' - EXTENDED_YEAR
            // case 21: // 'g' - JULIAN_DAY
            // case 22: // 'A' - MILLISECONDS_IN_DAY

            // Handle "generic" fields
            if (obeyCount)
            {
                if ((start+count) > text.length()) return -start;
                number = parseInt(text.substring(0, start+count), pos, allowNegative);
            }
            else number = parseInt(text, pos, allowNegative);
            if (number != null) {
                cal.set(field, number.intValue());
                return pos.getIndex();
            }
            return -start;
        }
    }

    /**
     * Parse an integer using fNumberFormat.  This method is semantically
     * const, but actually may modify fNumberFormat.
     */
    private Number parseInt(String text,
                            ParsePosition pos,
                            boolean allowNegative) {
        String oldPrefix = null;
        DecimalFormat df = null;
        if (!allowNegative) {
            try {
                df = (DecimalFormat)numberFormat;
                oldPrefix = df.getNegativePrefix();
                df.setNegativePrefix(SUPPRESS_NEGATIVE_PREFIX);
            } catch (ClassCastException e1) {}
        }
        Number number = numberFormat.parse(text, pos);
        if (df != null) {
            df.setNegativePrefix(oldPrefix);
        }
        return number;
    }

    /**
     * Translate a pattern, mapping each character in the from string to the
     * corresponding character in the to string.
     */
    private String translatePattern(String pattern, String from, String to) {
        StringBuffer result = new StringBuffer();
        boolean inQuote = false;
        for (int i = 0; i < pattern.length(); ++i) {
            char c = pattern.charAt(i);
            if (inQuote) {
                if (c == '\'')
                    inQuote = false;
            }
            else {
                if (c == '\'')
                    inQuote = true;
                else if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
                    int ci = from.indexOf(c);
                    if (ci == -1)
                        throw new IllegalArgumentException("Illegal pattern " +
                                                           " character '" +
                                                           c + "'");
                    c = to.charAt(ci);
                }
            }
            result.append(c);
        }
        if (inQuote)
            throw new IllegalArgumentException("Unfinished quote in pattern");
        return result.toString();
    }

    /**
     * Return a pattern string describing this date format.
     * @stable ICU 2.0
     */
    public String toPattern() {
        return pattern;
    }

    /**
     * Return a localized pattern string describing this date format.
     * @stable ICU 2.0
     */
    public String toLocalizedPattern() {
        return translatePattern(pattern,
                             DateFormatSymbols.patternChars,
                             formatData.localPatternChars);
    }

    /**
     * Apply the given unlocalized pattern string to this date format.
     * @stable ICU 2.0
     */
    public void applyPattern(String pattern)
    {
        this.pattern = pattern;
        setLocale(null, null);
    }

    /**
     * Apply the given localized pattern string to this date format.
     * @stable ICU 2.0
     */
    public void applyLocalizedPattern(String pattern) {
        this.pattern = translatePattern(pattern,
                             formatData.localPatternChars,
                             DateFormatSymbols.patternChars);
        setLocale(null, null);
    }

    /**
     * Gets the date/time formatting data.
     * @return a copy of the date-time formatting data associated
     * with this date-time formatter.
     * @stable ICU 2.0
     */
    public DateFormatSymbols getDateFormatSymbols()
    {
        return (DateFormatSymbols)formatData.clone();
    }

    /**
     * Allows you to set the date/time formatting data.
     * @param newFormatSymbols the new symbols
     * @stable ICU 2.0
     */
    public void setDateFormatSymbols(DateFormatSymbols newFormatSymbols)
    {
        this.formatData = (DateFormatSymbols)newFormatSymbols.clone();
    }

    /**
     * Method for subclasses to access the DateFormatSymbols.
     * @stable ICU 2.0
     */
    protected DateFormatSymbols getSymbols() {
        return formatData;
    }

    /**
     * Overrides Cloneable
     * @stable ICU 2.0
     */
    public Object clone() {
        SimpleDateFormat other = (SimpleDateFormat) super.clone();
        other.formatData = (DateFormatSymbols) formatData.clone();
        return other;
    }

    /**
     * Override hashCode.
     * Generates the hash code for the SimpleDateFormat object
     * @stable ICU 2.0
     */
    public int hashCode()
    {
        return pattern.hashCode();
        // just enough fields for a reasonable distribution
    }

    /**
     * Override equals.
     * @stable ICU 2.0
     */
    public boolean equals(Object obj)
    {
        if (!super.equals(obj)) return false; // super does class check
        SimpleDateFormat that = (SimpleDateFormat) obj;
        return (pattern.equals(that.pattern)
                && formatData.equals(that.formatData));
    }

    /**
     * Override readObject.
     */
    private void readObject(ObjectInputStream stream)
        throws IOException, ClassNotFoundException {
        stream.defaultReadObject();
        ///CLOVER:OFF
        // don't have old serial data to test with
        if (serialVersionOnStream < 1) {
            // didn't have defaultCenturyStart field
            initializeDefaultCentury();
        }
        ///CLOVER:ON
        else {
            // fill in dependent transient field
            parseAmbiguousDatesAsAfter(defaultCenturyStart);
        }
        serialVersionOnStream = currentSerialVersion;
    }
}
