/* SimpleDateFormat.java -- A class for parsing/formating simple 
   date constructs
   Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005
   Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
 
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.text;

import gnu.java.lang.CPStringBuilder;

import gnu.java.text.AttributedFormatBuffer;
import gnu.java.text.FormatBuffer;
import gnu.java.text.FormatCharacterIterator;
import gnu.java.text.StringFormatBuffer;

import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Iterator;
import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * SimpleDateFormat provides convenient methods for parsing and formatting
 * dates using Gregorian calendars (see java.util.GregorianCalendar). 
 * This class is not thread-safe; external synchronisation should be applied
 * if an instance is to be accessed from multiple threads.
 */
public class SimpleDateFormat extends DateFormat 
{
  /** 
   * This class is used by <code>SimpleDateFormat</code> as a
   * compiled representation of a format string.  The field
   * ID, size, and character used are stored for each sequence
   * of pattern characters.
   */
  private class CompiledField
  {
    /**
     * The ID of the field within the local pattern characters.
     * Package private for use in out class.
     */
    int field;

    /**
     * The size of the character sequence.
     * Package private for use in out class.
     */
    int size;

    /**
     * The character used.
     */
    private char character;

    /** 
     * Constructs a compiled field using the
     * the given field ID, size and character
     * values.
     *
     * @param f the field ID.
     * @param s the size of the field.
     * @param c the character used.
     */
    public CompiledField(int f, int s, char c)
    {
      field = f;
      size = s;
      character = c;
    }

    /**
     * Retrieves the ID of the field relative to
     * the local pattern characters.
     */
    public int getField()
    {
      return field;
    }

    /**
     * Retrieves the size of the character sequence.
     */
    public int getSize()
    {
      return size;
    }

    /**
     * Retrieves the character used in the sequence.
     */
    public char getCharacter()
    {
      return character;
    }

    /**
     * Returns a <code>String</code> representation
     * of the compiled field, primarily for debugging
     * purposes.
     *
     * @return a <code>String</code> representation.
     */
    public String toString()
    {
      CPStringBuilder builder;

      builder = new CPStringBuilder(getClass().getName());
      builder.append("[field=");
      builder.append(field);
      builder.append(", size=");
      builder.append(size);
      builder.append(", character=");
      builder.append(character);
      builder.append("]");

      return builder.toString();
    }
  }

  /**
   * A list of <code>CompiledField</code>s and {@code String}s
   * representing the compiled version of the pattern.
   *
   * @see CompiledField
   * @serial Ignored.
   */
  private transient ArrayList<Object> tokens;

  /**
   * The localised data used in formatting,
   * such as the day and month names in the local
   * language, and the localized pattern characters.
   *
   * @see DateFormatSymbols
   * @serial The localisation data.  May not be null.
   */
  private DateFormatSymbols formatData;

  /**
   * The date representing the start of the century
   * used for interpreting two digit years.  For
   * example, 24/10/2004 would cause two digit
   * years to be interpreted as representing
   * the years between 2004 and 2104.
   *
   * @see #get2DigitYearStart()
   * @see #set2DigitYearStart(java.util.Date)
   * @see Date
   * @serial The start date of the century for parsing two digit years.
   *         May not be null.
   */
  private Date defaultCenturyStart;

  /**
   * The year at which interpretation of two
   * digit years starts.
   *
   * @see #get2DigitYearStart()
   * @see #set2DigitYearStart(java.util.Date)
   * @serial Ignored.
   */
  private transient int defaultCentury;

  /**
   * The non-localized pattern string.  This
   * only ever contains the pattern characters
   * stored in standardChars.  Localized patterns
   * are translated to this form.
   *
   * @see #applyPattern(String)
   * @see #applyLocalizedPattern(String)
   * @see #toPattern()
   * @see #toLocalizedPattern()
   * @serial The non-localized pattern string.  May not be null.
   */
  private String pattern;

  /**
   * The version of serialized data used by this class.
   * Version 0 only includes the pattern and formatting
   * data.  Version 1 adds the start date for interpreting
   * two digit years.
   *
   * @serial This specifies the version of the data being serialized.
   *         Version 0 (or no version) specifies just <code>pattern</code>
   *         and <code>formatData</code>.  Version 1 adds
   *         the <code>defaultCenturyStart</code>.  This implementation
   *         always writes out version 1 data.
   */
  private int serialVersionOnStream = 1; // 0 indicates JDK1.1.3 or earlier

  /**
   * For compatability.
   */
  private static final long serialVersionUID = 4774881970558875024L;

  // This string is specified in the root of the CLDR.
  private static final String standardChars = "GyMdkHmsSEDFwWahKzYeugAZvcL";

  /**  
   * Represents the position of the RFC822 timezone pattern character
   * in the array of localized pattern characters.  In the
   * U.S. locale, this is 'Z'.  The value is the offset of the current
   * time from GMT e.g. -0500 would be five hours prior to GMT.
   */  
  private static final int RFC822_TIMEZONE_FIELD = 23;

  /**
   * Reads the serialized version of this object.
   * If the serialized data is only version 0,
   * then the date for the start of the century
   * for interpreting two digit years is computed.
   * The pattern is parsed and compiled following the process
   * of reading in the serialized data.
   *
   * @param stream the object stream to read the data from.
   * @throws IOException if an I/O error occurs.
   * @throws ClassNotFoundException if the class of the serialized data
   *         could not be found.
   * @throws InvalidObjectException if the pattern is invalid.
   */ 
  private void readObject(ObjectInputStream stream)
    throws IOException, ClassNotFoundException
  {
    stream.defaultReadObject();
    if (serialVersionOnStream < 1)
      {
        computeCenturyStart ();
	serialVersionOnStream = 1;
      }
    else
      // Ensure that defaultCentury gets set.
      set2DigitYearStart(defaultCenturyStart);

    // Set up items normally taken care of by the constructor.
    tokens = new ArrayList<Object>();
    try
      {
	compileFormat(pattern);
      }
    catch (IllegalArgumentException e)
      {
	throw new InvalidObjectException("The stream pattern was invalid.");
      }
  }

  /**
   * Compiles the supplied non-localized pattern into a form
   * from which formatting and parsing can be performed.
   * This also detects errors in the pattern, which will
   * be raised on later use of the compiled data.
   *
   * @param pattern the non-localized pattern to compile.
   * @throws IllegalArgumentException if the pattern is invalid.
   */
  private void compileFormat(String pattern) 
  {
    // Any alphabetical characters are treated as pattern characters
    // unless enclosed in single quotes.

    char thisChar;
    int pos;
    int field;
    CompiledField current = null;

    for (int i = 0; i < pattern.length(); i++)
      {
	thisChar = pattern.charAt(i);
	field = standardChars.indexOf(thisChar);
	if (field == -1)
	  {
	    current = null;
	    if ((thisChar >= 'A' && thisChar <= 'Z')
		|| (thisChar >= 'a' && thisChar <= 'z'))
	      {
		// Not a valid letter
		throw new IllegalArgumentException("Invalid letter "
						   + thisChar +
						   " encountered at character "
						   + i + ".");
	      }
	    else if (thisChar == '\'')
	      {
		// Quoted text section; skip to next single quote
		pos = pattern.indexOf('\'', i + 1);
		// First look for '' -- meaning a single quote.
		if (pos == i + 1)
		  tokens.add("'");
		else
		  {
		    // Look for the terminating quote.  However, if we
		    // see a '', that represents a literal quote and
		    // we must iterate.
		    CPStringBuilder buf = new CPStringBuilder();
		    int oldPos = i + 1;
		    do
		      {
			if (pos == -1)
			  throw new IllegalArgumentException("Quotes starting at character "
							     + i +
							     " not closed.");
			buf.append(pattern.substring(oldPos, pos));
			if (pos + 1 >= pattern.length()
			    || pattern.charAt(pos + 1) != '\'')
			  break;
			buf.append('\'');
			oldPos = pos + 2;
			pos = pattern.indexOf('\'', pos + 2);
		      }
		    while (true);
		    tokens.add(buf.toString());
		  }
		i = pos;
	      }
	    else
	      {
		// A special character
		tokens.add(Character.valueOf(thisChar));
	      }
	  }
	else
	  {
	    // A valid field
	    if ((current != null) && (field == current.field))
	      current.size++;
	    else
	      {
		current = new CompiledField(field, 1, thisChar);
		tokens.add(current);
	      }
	  }
      }
  }

  /**
   * Returns a string representation of this
   * class.
   *
   * @return a string representation of the <code>SimpleDateFormat</code>
   *         instance.
   */
  public String toString() 
  {
    CPStringBuilder output = new CPStringBuilder(getClass().getName());
    output.append("[tokens=");
    output.append(tokens);
    output.append(", formatData=");
    output.append(formatData);
    output.append(", defaultCenturyStart=");
    output.append(defaultCenturyStart);
    output.append(", defaultCentury=");
    output.append(defaultCentury);
    output.append(", pattern=");
    output.append(pattern);
    output.append(", serialVersionOnStream=");
    output.append(serialVersionOnStream);
    output.append(", standardChars=");
    output.append(standardChars);
    output.append("]");
    return output.toString();
  }

  /**
   * Constructs a SimpleDateFormat using the default pattern for
   * the default locale.
   */
  public SimpleDateFormat() 
  {
    /*
     * There does not appear to be a standard API for determining 
     * what the default pattern for a locale is, so use package-scope
     * variables in DateFormatSymbols to encapsulate this.
     */
    super();
    Locale locale = Locale.getDefault();
    calendar = new GregorianCalendar(locale);
    computeCenturyStart();
    tokens = new ArrayList<Object>();
    formatData = new DateFormatSymbols(locale);
    pattern = (formatData.dateFormats[DEFAULT] + ' '
	       + formatData.timeFormats[DEFAULT]);
    compileFormat(pattern);
    numberFormat = NumberFormat.getInstance(locale);
    numberFormat.setGroupingUsed (false);
    numberFormat.setParseIntegerOnly (true);
    numberFormat.setMaximumFractionDigits (0);
  }
  
  /**
   * Creates a date formatter using the specified non-localized pattern,
   * with the default DateFormatSymbols for the default locale.
   *
   * @param pattern the pattern to use.
   * @throws NullPointerException if the pattern is null.
   * @throws IllegalArgumentException if the pattern is invalid.
   */
  public SimpleDateFormat(String pattern) 
  {
    this(pattern, Locale.getDefault());
  }

  /**
   * Creates a date formatter using the specified non-localized pattern,
   * with the default DateFormatSymbols for the given locale.
   *
   * @param pattern the non-localized pattern to use.
   * @param locale the locale to use for the formatting symbols.
   * @throws NullPointerException if the pattern is null.
   * @throws IllegalArgumentException if the pattern is invalid.
   */
  public SimpleDateFormat(String pattern, Locale locale) 
  {
    super();
    calendar = new GregorianCalendar(locale);
    computeCenturyStart();
    tokens = new ArrayList<Object>();
    formatData = new DateFormatSymbols(locale);
    compileFormat(pattern);
    this.pattern = pattern;
    numberFormat = NumberFormat.getInstance(locale);
    numberFormat.setGroupingUsed (false);
    numberFormat.setParseIntegerOnly (true);
    numberFormat.setMaximumFractionDigits (0);
  }

  /**
   * Creates a date formatter using the specified non-localized
   * pattern. The specified DateFormatSymbols will be used when
   * formatting.
   *
   * @param pattern the non-localized pattern to use.
   * @param formatData the formatting symbols to use.
   * @throws NullPointerException if the pattern or formatData is null.
   * @throws IllegalArgumentException if the pattern is invalid.
   */
  public SimpleDateFormat(String pattern, DateFormatSymbols formatData)
  {
    super();
    calendar = new GregorianCalendar();
    computeCenturyStart ();
    tokens = new ArrayList<Object>();
    if (formatData == null)
      throw new NullPointerException("formatData");
    this.formatData = formatData;
    compileFormat(pattern);
    this.pattern = pattern;
    numberFormat = NumberFormat.getInstance();
    numberFormat.setGroupingUsed (false);
    numberFormat.setParseIntegerOnly (true);
    numberFormat.setMaximumFractionDigits (0);
  }

  /**
   * This method returns a string with the formatting pattern being used
   * by this object.  This string is unlocalized.
   *
   * @return The format string.
   */
  public String toPattern()
  {
    return pattern;
  }

  /**
   * This method returns a string with the formatting pattern being used
   * by this object.  This string is localized.
   *
   * @return The format string.
   */
  public String toLocalizedPattern()
  {
    String localChars = formatData.getLocalPatternChars();
    return translateLocalizedPattern(pattern, standardChars, localChars);
  }

  /**
   * This method sets the formatting pattern that should be used by this
   * object.  This string is not localized.
   *
   * @param pattern The new format pattern.
   * @throws NullPointerException if the pattern is null.
   * @throws IllegalArgumentException if the pattern is invalid.
   */
  public void applyPattern(String pattern)
  {
    tokens.clear();
    compileFormat(pattern);
    this.pattern = pattern;
  }

  /**
   * This method sets the formatting pattern that should be used by this
   * object.  This string is localized.
   *
   * @param pattern The new format pattern.
   * @throws NullPointerException if the pattern is null.
   * @throws IllegalArgumentException if the pattern is invalid.
   */
  public void applyLocalizedPattern(String pattern)
  {
    String localChars = formatData.getLocalPatternChars();
    pattern = translateLocalizedPattern(pattern, localChars, standardChars);
    applyPattern(pattern);
  }

  /**
   * Translates either from or to a localized variant of the pattern
   * string.  For example, in the German locale, 't' (for 'tag') is
   * used instead of 'd' (for 'date').  This method translates
   * a localized pattern (such as 'ttt') to a non-localized pattern
   * (such as 'ddd'), or vice versa.  Non-localized patterns use
   * a standard set of characters, which match those of the U.S. English
   * locale.
   *
   * @param pattern the pattern to translate.
   * @param oldChars the old set of characters (used in the pattern).
   * @param newChars the new set of characters (which will be used in the
   *                 pattern).
   * @return a version of the pattern using the characters in
   *         <code>newChars</code>.
   */
  private String translateLocalizedPattern(String pattern,
					   String oldChars, String newChars)
  {
    int len = pattern.length();
    CPStringBuilder buf = new CPStringBuilder(len);
    boolean quoted = false;
    for (int i = 0;  i < len;  i++)
      {
	char ch = pattern.charAt(i);
	if (ch == '\'')
	  quoted = ! quoted;
	if (! quoted)
	  {
	    int j = oldChars.indexOf(ch);
	    if (j >= 0)
	      ch = newChars.charAt(j);
	  }
	buf.append(ch);
      }
    return buf.toString();
  }

  /** 
   * Returns the start of the century used for two digit years.
   *
   * @return A <code>Date</code> representing the start of the century
   * for two digit years.
   */
  public Date get2DigitYearStart()
  {
    return defaultCenturyStart;
  }

  /**
   * Sets the start of the century used for two digit years.
   *
   * @param date A <code>Date</code> representing the start of the century for
   * two digit years.
   */
  public void set2DigitYearStart(Date date)
  {
    defaultCenturyStart = date;
    calendar.clear();
    calendar.setTime(date);
    int year = calendar.get(Calendar.YEAR);
    defaultCentury = year - (year % 100);
  }

  /**
   * This method returns a copy of the format symbol information used
   * for parsing and formatting dates.
   *
   * @return a copy of the date format symbols.
   */
  public DateFormatSymbols getDateFormatSymbols()
  {
    return (DateFormatSymbols) formatData.clone();
  }

  /**
   * This method sets the format symbols information used for parsing
   * and formatting dates.
   *
   * @param formatData The date format symbols.
   * @throws NullPointerException if <code>formatData</code> is null.
   */
   public void setDateFormatSymbols(DateFormatSymbols formatData)
   {
     if (formatData == null)
       {
	 throw new
	   NullPointerException("The supplied format data was null.");
       }
     this.formatData = formatData;
   }

  /**
   * This methods tests whether the specified object is equal to this
   * object.  This will be true if and only if the specified object:
   * <p>
   * <ul>
   * <li>Is not <code>null</code>.</li>
   * <li>Is an instance of <code>SimpleDateFormat</code>.</li>
   * <li>Is equal to this object at the superclass (i.e., <code>DateFormat</code>)
   *     level.</li>
   * <li>Has the same formatting pattern.</li>
   * <li>Is using the same formatting symbols.</li>
   * <li>Is using the same century for two digit years.</li>
   * </ul>
   *
   * @param o The object to compare for equality against.
   *
   * @return <code>true</code> if the specified object is equal to this object,
   * <code>false</code> otherwise.
   */
  public boolean equals(Object o)
  {
    if (!super.equals(o))
      return false;

    if (!(o instanceof SimpleDateFormat))
      return false;

    SimpleDateFormat sdf = (SimpleDateFormat)o;

    if (defaultCentury != sdf.defaultCentury)
      return false;

    if (!toPattern().equals(sdf.toPattern()))
      return false;

    if (!getDateFormatSymbols().equals(sdf.getDateFormatSymbols()))
      return false;

    return true;
  }

  /**
   * This method returns a hash value for this object.
   *
   * @return A hash value for this object.
   */
  public int hashCode()
  {
    return super.hashCode() ^ toPattern().hashCode() ^ defaultCentury ^
      getDateFormatSymbols().hashCode();
  }


  /**
   * Formats the date input according to the format string in use,
   * appending to the specified StringBuffer.  The input StringBuffer
   * is returned as output for convenience.
   */
  private void formatWithAttribute(Date date, FormatBuffer buffer, FieldPosition pos)
  {
    String temp;
    calendar.setTime(date);

    // go through vector, filling in fields where applicable, else toString
    Iterator<Object> iter = tokens.iterator();
    while (iter.hasNext())
      {
	Object o = iter.next();
	if (o instanceof CompiledField)
	  {
	    CompiledField cf = (CompiledField) o;
	    int beginIndex = buffer.length();
	    
	    switch (cf.getField())
	      {
	      case ERA_FIELD:
		buffer.append (formatData.eras[calendar.get (Calendar.ERA)], DateFormat.Field.ERA);
		break;
	      case YEAR_FIELD:
		// If we have two digits, then we truncate.  Otherwise, we
		// use the size of the pattern, and zero pad.
		buffer.setDefaultAttribute (DateFormat.Field.YEAR);
		if (cf.getSize() == 2)
		  {
		    temp = "00"+String.valueOf (calendar.get (Calendar.YEAR));
		    buffer.append (temp.substring (temp.length() - 2));
		  }
		else
		  withLeadingZeros (calendar.get (Calendar.YEAR), cf.getSize(), buffer);
		break;
	      case MONTH_FIELD:
		buffer.setDefaultAttribute (DateFormat.Field.MONTH);
		if (cf.getSize() < 3)
		  withLeadingZeros (calendar.get (Calendar.MONTH) + 1, cf.getSize(), buffer);
		else if (cf.getSize() < 4)
		  buffer.append (formatData.shortMonths[calendar.get (Calendar.MONTH)]);
		else
		  buffer.append (formatData.months[calendar.get (Calendar.MONTH)]);
		break;
	      case DATE_FIELD:
		buffer.setDefaultAttribute (DateFormat.Field.DAY_OF_MONTH);
		withLeadingZeros (calendar.get (Calendar.DATE), cf.getSize(), buffer);
		break;
	      case HOUR_OF_DAY1_FIELD: // 1-24
		buffer.setDefaultAttribute(DateFormat.Field.HOUR_OF_DAY1);
		withLeadingZeros ( ((calendar.get (Calendar.HOUR_OF_DAY) + 23) % 24) + 1, 
				   cf.getSize(), buffer);
		break;
	      case HOUR_OF_DAY0_FIELD: // 0-23
		buffer.setDefaultAttribute (DateFormat.Field.HOUR_OF_DAY0);
		withLeadingZeros (calendar.get (Calendar.HOUR_OF_DAY), cf.getSize(), buffer);
		break;
	      case MINUTE_FIELD:
		buffer.setDefaultAttribute (DateFormat.Field.MINUTE);
		withLeadingZeros (calendar.get (Calendar.MINUTE),
				  cf.getSize(), buffer);
		break;
	      case SECOND_FIELD:
		buffer.setDefaultAttribute (DateFormat.Field.SECOND);
		withLeadingZeros(calendar.get (Calendar.SECOND), 
				 cf.getSize(), buffer);
		break;
	      case MILLISECOND_FIELD:
		buffer.setDefaultAttribute (DateFormat.Field.MILLISECOND);
		withLeadingZeros (calendar.get (Calendar.MILLISECOND), cf.getSize(), buffer);
		break;
	      case DAY_OF_WEEK_FIELD:
		buffer.setDefaultAttribute (DateFormat.Field.DAY_OF_WEEK);
		if (cf.getSize() < 4)
		  buffer.append (formatData.shortWeekdays[calendar.get (Calendar.DAY_OF_WEEK)]);
		else
		  buffer.append (formatData.weekdays[calendar.get (Calendar.DAY_OF_WEEK)]);
		break;
	      case DAY_OF_YEAR_FIELD:
		buffer.setDefaultAttribute (DateFormat.Field.DAY_OF_YEAR);
		withLeadingZeros (calendar.get (Calendar.DAY_OF_YEAR), cf.getSize(), buffer);
		break;
	      case DAY_OF_WEEK_IN_MONTH_FIELD:
		buffer.setDefaultAttribute (DateFormat.Field.DAY_OF_WEEK_IN_MONTH);
		withLeadingZeros (calendar.get (Calendar.DAY_OF_WEEK_IN_MONTH), 
				 cf.getSize(), buffer);
		break;
	      case WEEK_OF_YEAR_FIELD:
		buffer.setDefaultAttribute (DateFormat.Field.WEEK_OF_YEAR);
		withLeadingZeros (calendar.get (Calendar.WEEK_OF_YEAR),
				  cf.getSize(), buffer);
		break;
	      case WEEK_OF_MONTH_FIELD:
		buffer.setDefaultAttribute (DateFormat.Field.WEEK_OF_MONTH);
		withLeadingZeros (calendar.get (Calendar.WEEK_OF_MONTH),
				  cf.getSize(), buffer);
		break;
	      case AM_PM_FIELD:
		buffer.setDefaultAttribute (DateFormat.Field.AM_PM);
		buffer.append (formatData.ampms[calendar.get (Calendar.AM_PM)]);
		break;
	      case HOUR1_FIELD: // 1-12
		buffer.setDefaultAttribute (DateFormat.Field.HOUR1);
		withLeadingZeros (((calendar.get (Calendar.HOUR) + 11) % 12) + 1,
				  cf.getSize(), buffer);
		break;
	      case HOUR0_FIELD: // 0-11
		buffer.setDefaultAttribute (DateFormat.Field.HOUR0);
		withLeadingZeros (calendar.get (Calendar.HOUR), cf.getSize(), buffer);
		break;
	      case TIMEZONE_FIELD:
		buffer.setDefaultAttribute (DateFormat.Field.TIME_ZONE);
		TimeZone zone = calendar.getTimeZone();
		boolean isDST = calendar.get (Calendar.DST_OFFSET) != 0;
		// FIXME: XXX: This should be a localized time zone.
		String zoneID = zone.getDisplayName
		  (isDST, cf.getSize() > 3 ? TimeZone.LONG : TimeZone.SHORT);
		buffer.append (zoneID);
		break;
	      case RFC822_TIMEZONE_FIELD:
		buffer.setDefaultAttribute(DateFormat.Field.TIME_ZONE);
		int pureMinutes = (calendar.get(Calendar.ZONE_OFFSET) +
				   calendar.get(Calendar.DST_OFFSET)) / (1000 * 60);
		String sign = (pureMinutes < 0) ? "-" : "+";
                pureMinutes = Math.abs(pureMinutes);
		int hours = pureMinutes / 60;
		int minutes = pureMinutes % 60;
		buffer.append(sign);
		withLeadingZeros(hours, 2, buffer);
		withLeadingZeros(minutes, 2, buffer);
		break;
	      default:
		throw new IllegalArgumentException ("Illegal pattern character " +
						    cf.getCharacter());
	      }
	    if (pos != null && (buffer.getDefaultAttribute() == pos.getFieldAttribute()
				|| cf.getField() == pos.getField()))
	      {
		pos.setBeginIndex(beginIndex);
		pos.setEndIndex(buffer.length());
	      }
	  } 
      else
	{  
	  buffer.append(o.toString(), null);
	}
      }
  }
  
  public StringBuffer format(Date date, StringBuffer buffer, FieldPosition pos)
  {
    formatWithAttribute(date, new StringFormatBuffer (buffer), pos);

    return buffer;
  }

  public AttributedCharacterIterator formatToCharacterIterator(Object date)
    throws IllegalArgumentException
  {
    if (date == null)
      throw new NullPointerException("null argument");
    if (!(date instanceof Date))
      throw new IllegalArgumentException("argument should be an instance of java.util.Date");

    AttributedFormatBuffer buf = new AttributedFormatBuffer();
    formatWithAttribute((Date)date, buf,
			null);
    buf.sync();
        
    return new FormatCharacterIterator(buf.getBuffer().toString(),
				       buf.getRanges(),
				       buf.getAttributes());
  }

  private void withLeadingZeros(int value, int length, FormatBuffer buffer) 
  {
    String valStr = String.valueOf(value);
    for (length -= valStr.length(); length > 0; length--)
      buffer.append('0');
    buffer.append(valStr);
  }

  private boolean expect(String source, ParsePosition pos, char ch)
  {
    int x = pos.getIndex();
    boolean r = x < source.length() && source.charAt(x) == ch;
    if (r)
      pos.setIndex(x + 1);
    else
      pos.setErrorIndex(x);
    return r;
  }

  /**
   * This method parses the specified string into a date.
   * 
   * @param dateStr The date string to parse.
   * @param pos The input and output parse position
   *
   * @return The parsed date, or <code>null</code> if the string cannot be
   * parsed.
   */
  public Date parse (String dateStr, ParsePosition pos)
  {
    int fmt_index = 0;
    int fmt_max = pattern.length();

    calendar.clear();
    boolean saw_timezone = false;
    int quote_start = -1;
    boolean is2DigitYear = false;
    try
      {
	for (; fmt_index < fmt_max; ++fmt_index)
	  {
	    char ch = pattern.charAt(fmt_index);
	    if (ch == '\'')
	      {
		if (fmt_index < fmt_max - 1
		    && pattern.charAt(fmt_index + 1) == '\'')
		  {
		    if (! expect (dateStr, pos, ch))
		      return null;
		    ++fmt_index;
		  }
		else
		  quote_start = quote_start < 0 ? fmt_index : -1;
		continue;
	      }
	    
	    if (quote_start != -1
		|| ((ch < 'a' || ch > 'z')
		    && (ch < 'A' || ch > 'Z')))
	      {
                if (quote_start == -1 && ch == ' ')
                  {
                    // A single unquoted space in the pattern may match
                    // any number of spaces in the input.
                    int index = pos.getIndex();
                    int save = index;
                    while (index < dateStr.length()
                           && Character.isWhitespace(dateStr.charAt(index)))
                      ++index;
                    if (index > save)
                      pos.setIndex(index);
                    else
                      {
                        // Didn't see any whitespace.
                        pos.setErrorIndex(index);
                        return null;
                      }
                  }
                else if (! expect (dateStr, pos, ch))
		  return null;
		continue;
	      }
	    
	    // We've arrived at a potential pattern character in the
	    // pattern.
	    int fmt_count = 1;
	    while (++fmt_index < fmt_max && pattern.charAt(fmt_index) == ch)
	      {
		++fmt_count;
	      }
	    
	    // We might need to limit the number of digits to parse in
	    // some cases.  We look to the next pattern character to
	    // decide.
	    boolean limit_digits = false;
	    if (fmt_index < fmt_max
		&& standardChars.indexOf(pattern.charAt(fmt_index)) >= 0)
	      limit_digits = true;
	    --fmt_index;
	    
	    // We can handle most fields automatically: most either are
	    // numeric or are looked up in a string vector.  In some cases
	    // we need an offset.  When numeric, `offset' is added to the
	    // resulting value.  When doing a string lookup, offset is the
	    // initial index into the string array.
	    int calendar_field;
	    boolean is_numeric = true;
	    int offset = 0;
	    boolean maybe2DigitYear = false;
	    boolean oneBasedHour = false;
	    boolean oneBasedHourOfDay = false;
	    Integer simpleOffset;
	    String[] set1 = null;
	    String[] set2 = null;
	    switch (ch)
	      {
	      case 'd':
		calendar_field = Calendar.DATE;
		break;
	      case 'D':
		calendar_field = Calendar.DAY_OF_YEAR;
		break;
	      case 'F':
		calendar_field = Calendar.DAY_OF_WEEK_IN_MONTH;
		break;
	      case 'E':
		is_numeric = false;
		offset = 1;
		calendar_field = Calendar.DAY_OF_WEEK;
		set1 = formatData.getWeekdays();
		set2 = formatData.getShortWeekdays();
		break;
	      case 'w':
		calendar_field = Calendar.WEEK_OF_YEAR;
		break;
	      case 'W':
		calendar_field = Calendar.WEEK_OF_MONTH;
		break;
	      case 'M':
		calendar_field = Calendar.MONTH;
		if (fmt_count <= 2)
		  offset = -1;
		else
		  {
		    is_numeric = false;
		    set1 = formatData.getMonths();
		    set2 = formatData.getShortMonths();
		  }
		break;
	      case 'y':
		calendar_field = Calendar.YEAR;
		if (fmt_count <= 2)
		  maybe2DigitYear = true;
		break;
	      case 'K':
		calendar_field = Calendar.HOUR;
		break;
	      case 'h':
		calendar_field = Calendar.HOUR;
		oneBasedHour = true;
		break;
	      case 'H':
		calendar_field = Calendar.HOUR_OF_DAY;
		break;
	      case 'k':
		calendar_field = Calendar.HOUR_OF_DAY;
		oneBasedHourOfDay = true;
		break;
	      case 'm':
		calendar_field = Calendar.MINUTE;
		break;
	      case 's':
		calendar_field = Calendar.SECOND;
		break;
	      case 'S':
		calendar_field = Calendar.MILLISECOND;
		break;
	      case 'a':
		is_numeric = false;
		calendar_field = Calendar.AM_PM;
		set1 = formatData.getAmPmStrings();
		break;
	      case 'z':
	      case 'Z':
		// We need a special case for the timezone, because it
		// uses a different data structure than the other cases.
		is_numeric = false;
		calendar_field = Calendar.ZONE_OFFSET;
		String[][] zoneStrings = formatData.getZoneStrings();
		int zoneCount = zoneStrings.length;
		int index = pos.getIndex();
		boolean found_zone = false;
		simpleOffset = computeOffset(dateStr.substring(index), pos);
		if (simpleOffset != null)
		  {
		    found_zone = true;
		    saw_timezone = true;
		    calendar.set(Calendar.DST_OFFSET, 0);
		    offset = simpleOffset.intValue();
		  }
		else
		  {
		    for (int j = 0;  j < zoneCount;  j++)
		      {
			String[] strings = zoneStrings[j];
			int k;
			for (k = 0; k < strings.length; ++k)
			  {
			    if (dateStr.startsWith(strings[k], index))
			      break;
			  }
			if (k != strings.length)
			  {
			    found_zone = true;
			    saw_timezone = true;
			    TimeZone tz = TimeZone.getTimeZone (strings[0]);
			    // Check if it's a DST zone or ordinary 
			    if(k == 3 || k == 4)
			      calendar.set (Calendar.DST_OFFSET, tz.getDSTSavings());
			    else
			      calendar.set (Calendar.DST_OFFSET, 0);
                            offset = tz.getRawOffset ();
			    pos.setIndex(index + strings[k].length());
			    break;
			  }
		      }
		  }
		if (! found_zone)
		  {
			pos.setErrorIndex(pos.getIndex());
			return null;
		  }
		break;
	      default:
		pos.setErrorIndex(pos.getIndex());
		return null;
	      }
      
	    // Compute the value we should assign to the field.
	    int value;
	    int index = -1;
	    if (is_numeric)
	      {
		numberFormat.setMinimumIntegerDigits(fmt_count);
		if (maybe2DigitYear)
		  index = pos.getIndex();
		Number n = null;
		if (limit_digits)
		  {
		    // numberFormat.setMaximumIntegerDigits(fmt_count) may
		    // not work as expected. So we explicitly use substring
		    // of dateStr.
		    int origPos = pos.getIndex();
		    pos.setIndex(0);
		    n = numberFormat.parse(dateStr.substring(origPos, origPos + fmt_count), pos);
		    pos.setIndex(origPos + pos.getIndex());
		  }
		else
		  n = numberFormat.parse(dateStr, pos);
		if (pos == null || ! (n instanceof Long))
		  return null;
		value = n.intValue() + offset;
	      }
	    else if (set1 != null)
	      {
		index = pos.getIndex();
		int i;
		boolean found = false;
		for (i = offset; i < set1.length; ++i)
		  {
		    if (set1[i] != null)
		      if (dateStr.toUpperCase().startsWith(set1[i].toUpperCase(),
							   index))
			{
			  found = true;
			  pos.setIndex(index + set1[i].length());
			  break;
			}
		  }
		if (!found && set2 != null)
		  {
		    for (i = offset; i < set2.length; ++i)
		      {
			if (set2[i] != null)
			  if (dateStr.toUpperCase().startsWith(set2[i].toUpperCase(),
							       index))
			    {
			      found = true;
			      pos.setIndex(index + set2[i].length());
			      break;
			    }
		      }
		  }
		if (!found)
		  {
		    pos.setErrorIndex(index);
		    return null;
		  }
		value = i;
	      }
	    else
	      value = offset;
	  
	    if (maybe2DigitYear)
	      {
		// Parse into default century if the numeric year string has 
		// exactly 2 digits.
		int digit_count = pos.getIndex() - index;
		if (digit_count == 2)
		  {
		    is2DigitYear = true;
		    value += defaultCentury;
		  }
	      }
	    
	    // Calendar uses 0-based hours. 
	    // I.e. 00:00 AM is midnight, not 12 AM or 24:00
	    if (oneBasedHour && value == 12)
	      value = 0;

	    if (oneBasedHourOfDay && value == 24)
	      value = 0;
	    
	    // Assign the value and move on.
	    calendar.set(calendar_field, value);
	  }
    
	if (is2DigitYear)
	  {
	    // Apply the 80-20 heuristic to dermine the full year based on 
	    // defaultCenturyStart. 
	    int year = calendar.get(Calendar.YEAR);
	    if (calendar.getTime().compareTo(defaultCenturyStart) < 0)
	      calendar.set(Calendar.YEAR, year + 100);      
	  }
	if (! saw_timezone)
	  {
	    // Use the real rules to determine whether or not this
	    // particular time is in daylight savings.
	    calendar.clear (Calendar.DST_OFFSET);
	    calendar.clear (Calendar.ZONE_OFFSET);
	  }
        return calendar.getTime();
      }
    catch (IllegalArgumentException x)
      {
        pos.setErrorIndex(pos.getIndex());
	return null;
      }
      }

  /**
   * <p>
   * Computes the time zone offset in milliseconds
   * relative to GMT, based on the supplied
   * <code>String</code> representation.
   * </p>
   * <p>
   * The supplied <code>String</code> must be a three
   * or four digit signed number, with an optional 'GMT'
   * prefix.  The first one or two digits represents the hours,
   * while the last two represent the minutes.  The
   * two sets of digits can optionally be separated by
   * ':'.  The mandatory sign prefix (either '+' or '-')
   * indicates the direction of the offset from GMT.
   * </p>
   * <p>
   * For example, 'GMT+0200' specifies 2 hours after
   * GMT, while '-05:00' specifies 5 hours prior to
   * GMT.  The special case of 'GMT' alone can be used
   * to represent the offset, 0.
   * </p>
   * <p>
   * If the <code>String</code> can not be parsed,
   * the result will be null.  The resulting offset
   * is wrapped in an <code>Integer</code> object, in
   * order to allow such failure to be represented.
   * </p>
   *
   * @param zoneString a string in the form 
   *        (GMT)? sign hours : minutes
   *        where sign = '+' or '-', hours
   *        is a one or two digits representing
   *        a number between 0 and 23, and
   *        minutes is two digits representing
   *        a number between 0 and 59.
   * @return the parsed offset, or null if parsing
   *         failed.
   */
  private Integer computeOffset(String zoneString, ParsePosition pos)
  {
    Pattern pattern = 
      Pattern.compile("(GMT)?([+-])([012])?([0-9]):?([0-9]{2})");
    Matcher matcher = pattern.matcher(zoneString);

    // Match from start, but ignore trailing parts
    boolean hasAll = matcher.lookingAt();
    try
      {
	// Do we have at least the sign, hour and minute?
	matcher.group(2);
	matcher.group(4);
	matcher.group(5);
      }
    catch (IllegalStateException ise)
      {
	hasAll = false;
      }
    if (hasAll)
      {
	int sign = matcher.group(2).equals("+") ? 1 : -1;
	int hour = Integer.parseInt(matcher.group(4));
	if (!matcher.group(3).equals(""))
	  hour += (Integer.parseInt(matcher.group(3)) * 10);
	int minutes = Integer.parseInt(matcher.group(5));

	if (hour > 23)
	  return null;
	int offset = sign * ((hour * 60) + minutes) * 60000;

	// advance the index
	pos.setIndex(pos.getIndex() + matcher.end());
	return Integer.valueOf(offset);
      }
    else if (zoneString.startsWith("GMT"))
      {
	pos.setIndex(pos.getIndex() + 3);
	return Integer.valueOf(0);
      }
    return null;
  }

  // Compute the start of the current century as defined by
  // get2DigitYearStart.
  private void computeCenturyStart()
  {
    int year = calendar.get(Calendar.YEAR);
    calendar.set(Calendar.YEAR, year - 80);
    set2DigitYearStart(calendar.getTime());
  }

  /**
   * Returns a copy of this instance of
   * <code>SimpleDateFormat</code>.  The copy contains
   * clones of the formatting symbols and the 2-digit
   * year century start date.
   */
  public Object clone()
  {
    SimpleDateFormat clone = (SimpleDateFormat) super.clone();
    clone.setDateFormatSymbols((DateFormatSymbols) formatData.clone());
    clone.set2DigitYearStart((Date) defaultCenturyStart.clone());
    return clone;
  }

}
