/* SimpleDateFormat.java -- A class for parsing/formating simple 
   date constructs
   Copyright (C) 1998, 1999, 2000, 2001 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., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

As a special exception, if you link this library with other files to
produce an executable, this library does not by itself cause the
resulting executable to be covered by the GNU General Public License.
This exception does not however invalidate any other reasons why the
executable file might be covered by the GNU General Public License. */


package java.text;

import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
import java.util.SimpleTimeZone;
import java.util.Vector;
import java.io.ObjectInputStream;
import java.io.IOException;

/**
 * SimpleDateFormat provides convenient methods for parsing and formatting
 * dates using Gregorian calendars (see java.util.GregorianCalendar). 
 */
public class SimpleDateFormat extends DateFormat 
{
  /** A pair class used by SimpleDateFormat as a compiled representation
   *  of a format string.
   */
  private class FieldSizePair 
  {
    public int field;
    public int size;

    /** Constructs a pair with the given field and size values */
    public FieldSizePair(int f, int s) {
      field = f;
      size = s;
    }
  }

  private transient Vector tokens;
  private DateFormatSymbols formatData;  // formatData
  private Date defaultCenturyStart;
  private transient int defaultCentury;
  private String pattern;
  private int serialVersionOnStream = 1; // 0 indicates JDK1.1.3 or earlier
  private static final long serialVersionUID = 4774881970558875024L;

  // This string is specified in the JCL.  We set it here rather than
  // do a DateFormatSymbols(Locale.US).getLocalPatternChars() since
  // someone could theoretically change those values (though unlikely).
  private static final String standardChars = "GyMdkHmsSEDFwWahKz";

  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 Vector();
    compileFormat(pattern);
  }

  private void compileFormat(String pattern) 
  {
    // Any alphabetical characters are treated as pattern characters
    // unless enclosed in single quotes.

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

    for (int i=0; i<pattern.length(); i++) {
      thisChar = pattern.charAt(i);
      field = formatData.getLocalPatternChars().indexOf(thisChar);
      if (field == -1) {
	current = null;
	if (Character.isLetter(thisChar)) {
	  // Not a valid letter
	  tokens.addElement(new FieldSizePair(-1,0));
	} else if (thisChar == '\'') {
	  // Quoted text section; skip to next single quote
	  pos = pattern.indexOf('\'',i+1);
	  if (pos == -1) {
	    // This ought to be an exception, but spec does not
	    // let us throw one.
	    tokens.addElement(new FieldSizePair(-1,0));
	  }
	  if ((pos+1 < pattern.length()) && (pattern.charAt(pos+1) == '\'')) {
	    tokens.addElement(pattern.substring(i+1,pos+1));
	  } else {
	    tokens.addElement(pattern.substring(i+1,pos));
	  }
	  i = pos;
	} else {
	  // A special character
	  tokens.addElement(new Character(thisChar));
	}
      } else {
	// A valid field
	if ((current != null) && (field == current.field)) {
	  current.size++;
	} else {
	  current = new FieldSizePair(field,1);
	  tokens.addElement(current);
	}
      }
    }
  }
    
  public String toString() 
  {
    StringBuffer output = new StringBuffer();
    Enumeration e = tokens.elements();
    while (e.hasMoreElements()) {
      output.append(e.nextElement().toString());
    }
    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 Vector();
    formatData = new DateFormatSymbols(locale);
    pattern = (formatData.dateFormats[DEFAULT] + ' '
	       + formatData.timeFormats[DEFAULT]);
    compileFormat(pattern);
    numberFormat = NumberFormat.getInstance(locale);
    numberFormat.setGroupingUsed (false);
  }
  
  /**
   * Creates a date formatter using the specified pattern, with the default
   * DateFormatSymbols for the default locale.
   */
  public SimpleDateFormat(String pattern) 
  {
    this(pattern, Locale.getDefault());
  }

  /**
   * Creates a date formatter using the specified pattern, with the default
   * DateFormatSymbols for the given locale.
   */
  public SimpleDateFormat(String pattern, Locale locale) 
  {
    super();
    calendar = new GregorianCalendar(locale);
    computeCenturyStart();
    tokens = new Vector();
    formatData = new DateFormatSymbols(locale);
    compileFormat(pattern);
    this.pattern = pattern;
    numberFormat = NumberFormat.getInstance(locale);
    numberFormat.setGroupingUsed (false);
  }

  /**
   * Creates a date formatter using the specified pattern. The
   * specified DateFormatSymbols will be used when formatting.
   */
  public SimpleDateFormat(String pattern, DateFormatSymbols formatData)
  {
    super();
    calendar = new GregorianCalendar();
    computeCenturyStart ();
    tokens = new Vector();
    this.formatData = formatData;
    compileFormat(pattern);
    this.pattern = pattern;
    numberFormat = NumberFormat.getInstance();
    numberFormat.setGroupingUsed (false);
  }

  // What is the difference between localized and unlocalized?  The
  // docs don't say.

  /**
   * 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 applyLocalizedPattern (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.
   */
  public void applyPattern(String pattern)
  {
    tokens = new Vector();
    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.
   */
  public void applyLocalizedPattern(String pattern)
  {
    String localChars = formatData.getLocalPatternChars();
    pattern = applyLocalizedPattern (pattern, localChars, standardChars);
    applyPattern(pattern);
  }

  private String applyLocalizedPattern(String pattern,
				       String oldChars, String newChars)
  {
    int len = pattern.length();
    StringBuffer buf = new StringBuffer(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 the format symbol information used for parsing
   * and formatting dates.
   *
   * @return The date format symbols.
   */
  public DateFormatSymbols getDateFormatSymbols()
  {
    return formatData;
  }

  /**
   * This method sets the format symbols information used for parsing
   * and formatting dates.
   *
   * @param formatData The date format symbols.
   */
   public void setDateFormatSymbols(DateFormatSymbols formatData)
   {
     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>Is an instance of <code>SimpleDateFormat</code>.
   * <li>Is equal to this object at the superclass (i.e., <code>DateFormat</code>)
   *     level.
   * <li>Has the same formatting pattern.
   * <li>Is using the same formatting symbols.
   * <li>Is using the same century for two digit years.
   * </ul>
   *
   * @param obj 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 (o == null)
      return false;

    if (!super.equals(o))
      return false;

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

    SimpleDateFormat sdf = (SimpleDateFormat)o;

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

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

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

    return true;
  }


  /**
   * 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.
   */
  public StringBuffer format(Date date, StringBuffer buffer, FieldPosition pos)
  {
    String temp;
    calendar.setTime(date);
    
    // go through vector, filling in fields where applicable, else toString
    Enumeration e = tokens.elements();
    while (e.hasMoreElements()) {
      Object o = e.nextElement();
      if (o instanceof FieldSizePair) {
	FieldSizePair p = (FieldSizePair) o;
	int beginIndex = buffer.length();
	switch (p.field) {
	case ERA_FIELD:
	  buffer.append(formatData.eras[calendar.get(Calendar.ERA)]);
	  break;
	case YEAR_FIELD:
	  temp = String.valueOf(calendar.get(Calendar.YEAR));
	  if (p.size < 4)
	    buffer.append(temp.substring(temp.length()-2));
	  else
	    buffer.append(temp);
	  break;
	case MONTH_FIELD:
	  if (p.size < 3)
	    withLeadingZeros(calendar.get(Calendar.MONTH)+1,p.size,buffer);
	  else if (p.size < 4)
	    buffer.append(formatData.shortMonths[calendar.get(Calendar.MONTH)]);
	  else
	    buffer.append(formatData.months[calendar.get(Calendar.MONTH)]);
	  break;
	case DATE_FIELD:
	  withLeadingZeros(calendar.get(Calendar.DATE),p.size,buffer);
	  break;
	case HOUR_OF_DAY1_FIELD: // 1-24
	  withLeadingZeros(((calendar.get(Calendar.HOUR_OF_DAY)+23)%24)+1,p.size,buffer);
	  break;
	case HOUR_OF_DAY0_FIELD: // 0-23
	  withLeadingZeros(calendar.get(Calendar.HOUR_OF_DAY),p.size,buffer);
	  break;
	case MINUTE_FIELD:
	  withLeadingZeros(calendar.get(Calendar.MINUTE),p.size,buffer);
	  break;
	case SECOND_FIELD:
	  withLeadingZeros(calendar.get(Calendar.SECOND),p.size,buffer);
	  break;
	case MILLISECOND_FIELD:
	  withLeadingZeros(calendar.get(Calendar.MILLISECOND),p.size,buffer);
	  break;
	case DAY_OF_WEEK_FIELD:
	  if (p.size < 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:
	  withLeadingZeros(calendar.get(Calendar.DAY_OF_YEAR),p.size,buffer);
	  break;
	case DAY_OF_WEEK_IN_MONTH_FIELD:
	  withLeadingZeros(calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH),p.size,buffer);
	  break;
	case WEEK_OF_YEAR_FIELD:
	  withLeadingZeros(calendar.get(Calendar.WEEK_OF_YEAR),p.size,buffer);
	  break;
	case WEEK_OF_MONTH_FIELD:
	  withLeadingZeros(calendar.get(Calendar.WEEK_OF_MONTH),p.size,buffer);
	  break;
	case AM_PM_FIELD:
	  buffer.append(formatData.ampms[calendar.get(Calendar.AM_PM)]);
	  break;
	case HOUR1_FIELD: // 1-12
	  withLeadingZeros(((calendar.get(Calendar.HOUR)+11)%12)+1,p.size,buffer);
	  break;
	case HOUR0_FIELD: // 0-11
	  withLeadingZeros(calendar.get(Calendar.HOUR),p.size,buffer);
	  break;
	case TIMEZONE_FIELD:
	  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, p.size > 3 ? TimeZone.LONG : TimeZone.SHORT);
	  buffer.append(zoneID);
	  break;
	default:
	  throw new IllegalArgumentException("Illegal pattern character");
	}
	if (pos != null && p.field == pos.getField())
	  {
	    pos.setBeginIndex(beginIndex);
	    pos.setEndIndex(buffer.length());
	  }
      } else {
	buffer.append(o.toString());
      }
    }
    return buffer;
  }

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

  private final 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;
    for (; fmt_index < fmt_max; ++fmt_index)
      {
	char ch = pattern.charAt(fmt_index);
	if (ch == '\'')
	  {
	    int index = pos.getIndex();
	    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 (! expect (dateStr, pos, ch))
	      return null;
	    continue;
	  }

	// We've arrived at a potential pattern character in the
	// pattern.
	int first = fmt_index;
	while (++fmt_index < fmt_max && pattern.charAt(fmt_index) == ch)
	  ;
	int fmt_count = fmt_index - first;
	--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;
	String[] match = null;
	int offset = 0;
	boolean maybe2DigitYear = false;
	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;
	    match = (fmt_count <= 3
		     ? formatData.getShortWeekdays()
		     : formatData.getWeekdays());
	    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;
		match = (fmt_count <= 3
			 ? formatData.getShortMonths()
			 : formatData.getMonths());
	      }
	    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;
	    break;
	  case 'H':
	    calendar_field = Calendar.HOUR_OF_DAY;
	    break;
	  case 'k':
	    calendar_field = Calendar.HOUR_OF_DAY;
	    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;
	    match = formatData.getAmPmStrings();
	    break;
	  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.DST_OFFSET;
	    String[][] zoneStrings = formatData.getZoneStrings();
	    int zoneCount = zoneStrings.length;
	    int index = pos.getIndex();
	    boolean found_zone = false;
	    for (int j = 0;  j < zoneCount;  j++)
	      {
		String[] strings = zoneStrings[j];
		int k;
		for (k = 1; 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]);
		    calendar.setTimeZone (tz);
		    calendar.set (Calendar.ZONE_OFFSET, tz.getRawOffset ());
		    offset = 0;
		    if (k > 2 && tz instanceof SimpleTimeZone)
		      {
			SimpleTimeZone stz = (SimpleTimeZone) tz;
			offset = stz.getDSTSavings ();
		      }
		    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 = numberFormat.parse(dateStr, pos);
	    if (pos == null || ! (n instanceof Long))
	      return null;
	    value = n.intValue() + offset;
	  }
	else if (match != null)
	  {
	    index = pos.getIndex();
	    int i;
	    for (i = offset; i < match.length; ++i)
	      {
		if (dateStr.startsWith(match[i], index))
		  break;
	      }
	    if (i == match.length)
	      {
		pos.setErrorIndex(index);
		return null;
	      }
	    pos.setIndex(index + match[i].length());
	    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;
	  }

	// 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 = defaultCentury + calendar.get(Calendar.YEAR);
	calendar.set(Calendar.YEAR, year);
	if (calendar.getTime().compareTo(defaultCenturyStart) < 0)
	  calendar.set(Calendar.YEAR, year + 100);      
      }

    try
      {
	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;
      }
  }

  // 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());
  }
}
