This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Patch: changes to Calendar and friends


I'm checking this in.  This patch includes Jeff Sturm's Calendar
patch, plus a new version of GregorianCalendar from Classpath, plus
some patches of mine to clean up some bugs I found.

I decided to use the Classpath GregorianCalendar implementation
because, after doing a lot of work on it last week, I decided that it
was simply too broken to try to maintain.

With this patch we pass all the calendar-related tests in Mauve (I
added a few while working on this, too).

I'm checking this in on the trunk.

2001-05-10  Tom Tromey  <tromey@redhat.com>

	* java/util/GregorianCalendar.java: Imported from Classpath.
	* gnu/java/locale/LocaleInformation_nl.java: New file from
	Classpath.
	* gnu/java/locale/LocaleInformation_en.java: Likewise.
	* gnu/java/locale/LocaleInformation_de.java: Likewise.
	* gnu/java/locale/LocaleInformation.java: Likewise.
	* natGregorianCalendar.cc: Removed.
	* Makefile.in: Rebuilt.
	* Makefile.am (nat_source_files): Removed
	natGregorianCalendar.cc.

2001-05-10  Tom Tromey  <tromey@redhat.com>

	* java/text/SimpleDateFormat.java (computeCenturyStart): New
	method.
	(defaultCenturyStart): Use it.
	(readObject): Likewise.
	(SimpleDateFormat): Clear the calendar.  Set the grouping on the
	number format.
	(parse): Copy the calendar before modifying it.  Correctly handle
	the time zone.

	* java/util/Calendar.java (clear): Set field value(s) to 0.

2001-05-10  Jeff Sturm  <jsturm@one-point.com>

	* Calendar.java (get): Clear areFieldsSet if requested field
	is not set.
	(set): Unset fields that depend on new value.

Tom

Index: Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libjava/Makefile.am,v
retrieving revision 1.140
diff -u -r1.140 Makefile.am
--- Makefile.am	2001/04/25 15:45:10	1.140
+++ Makefile.am	2001/05/10 16:29:00
@@ -1335,7 +1335,6 @@
 java/net/natPlainDatagramSocketImpl.cc \
 java/net/natPlainSocketImpl.cc \
 java/text/natCollator.cc \
-java/util/natGregorianCalendar.cc \
 java/util/zip/natDeflater.cc \
 java/util/zip/natInflater.cc
 
Index: java/text/SimpleDateFormat.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/text/SimpleDateFormat.java,v
retrieving revision 1.9
diff -u -r1.9 SimpleDateFormat.java
--- SimpleDateFormat.java	2001/04/20 09:43:51	1.9
+++ SimpleDateFormat.java	2001/05/10 16:29:01
@@ -62,8 +62,7 @@
 
   private transient Vector tokens;
   private DateFormatSymbols formatData;  // formatData
-  private Date defaultCenturyStart = 
-    new Date(System.currentTimeMillis() - (80*365*24*60*60*1000));
+  private Date defaultCenturyStart = computeCenturyStart ();
   private String pattern;
   private int serialVersionOnStream = 1; // 0 indicates JDK1.1.3 or earlier
   private static final long serialVersionUID = 4774881970558875024L;
@@ -79,8 +78,7 @@
     stream.defaultReadObject();
     if (serialVersionOnStream < 1)
       {
-        defaultCenturyStart =
-	  new Date(System.currentTimeMillis() - (80*365*24*60*60*1000));
+        defaultCenturyStart = computeCenturyStart ();
 	serialVersionOnStream = 1;
       }
 
@@ -161,11 +159,14 @@
     super();
     Locale locale = Locale.getDefault();
     calendar = new GregorianCalendar(locale);
+    calendar.clear ();
     tokens = new Vector();
     formatData = new DateFormatSymbols(locale);
-    pattern = formatData.dateFormats[DEFAULT]+' '+formatData.timeFormats[DEFAULT];
+    pattern = (formatData.dateFormats[DEFAULT] + ' '
+	       + formatData.timeFormats[DEFAULT]);
     compileFormat(pattern);
     numberFormat = NumberFormat.getInstance(locale);
+    numberFormat.setGroupingUsed (false);
   }
   
   /**
@@ -185,20 +186,24 @@
   {
     super();
     calendar = new GregorianCalendar(locale);
+    calendar.clear ();
     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) {
+  public SimpleDateFormat(String pattern, DateFormatSymbols formatData)
+  {
     super();
     calendar = new GregorianCalendar();
+    calendar.clear ();
     // FIXME: XXX: Is it really necessary to set the timezone?
     // The Calendar constructor is supposed to take care of this.
     calendar.setTimeZone(TimeZone.getDefault());
@@ -207,6 +212,7 @@
     compileFormat(pattern);
     this.pattern = pattern;
     numberFormat = NumberFormat.getInstance();
+    numberFormat.setGroupingUsed (false);
   }
 
   // What is the difference between localized and unlocalized?  The
@@ -377,7 +383,8 @@
    * appending to the specified StringBuffer.  The input StringBuffer
    * is returned as output for convenience.
    */
-  public StringBuffer format(Date date, StringBuffer buffer, FieldPosition pos) {
+  public StringBuffer format(Date date, StringBuffer buffer, FieldPosition pos)
+  {
     String temp;
     Calendar theCalendar = (Calendar) calendar.clone();
     theCalendar.setTime(date);
@@ -507,7 +514,10 @@
     int fmt_index = 0;
     int fmt_max = pattern.length();
 
-    calendar.clear();
+    // We copy the Calendar because if we don't we will modify it and
+    // then this.equals() will no longer have the desired result.
+    Calendar theCalendar = (Calendar) calendar.clone ();
+    theCalendar.clear();
     int quote_start = -1;
     for (; fmt_index < fmt_max; ++fmt_index)
       {
@@ -553,7 +563,6 @@
 	boolean is_numeric = true;
 	String[] match = null;
 	int offset = 0;
-	int zone_number = 0;
 	switch (ch)
 	  {
 	  case 'd':
@@ -626,6 +635,7 @@
 	    // We need a special case for the timezone, because it
 	    // uses a different data structure than the other cases.
 	    is_numeric = false;
+	    // We don't actually use this; see below.
 	    calendar_field = Calendar.DST_OFFSET;
 	    String[][] zoneStrings = formatData.getZoneStrings();
 	    int zoneCount = zoneStrings.length;
@@ -642,11 +652,11 @@
 		  }
 		if (k != strings.length)
 		  {
-		    if (k > 2)
-		      ;		// FIXME: dst.
-		    zone_number = 0; // FIXME: dst.
-		    // FIXME: raw offset to SimpleTimeZone const.
-		    calendar.setTimeZone(new SimpleTimeZone (1, strings[0]));
+		    found_zone = true;
+		    TimeZone tz = TimeZone.getTimeZone (strings[0]);
+		    theCalendar.setTimeZone (tz);
+		    theCalendar.clear (Calendar.DST_OFFSET);
+		    theCalendar.clear (Calendar.ZONE_OFFSET);
 		    pos.setIndex(index + strings[k].length());
 		    break;
 		  }
@@ -690,20 +700,38 @@
 	    value = i;
 	  }
 	else
-	  value = zone_number;
+	  value = 0;
 
 	// Assign the value and move on.
-	calendar.set(calendar_field, value);
+	if (calendar_field != Calendar.DST_OFFSET)
+	  theCalendar.set(calendar_field, value);
       }
 
     try
       {
-        return calendar.getTime();
+        return theCalendar.getTime();
       }
     catch (IllegalArgumentException x)
       {
         pos.setErrorIndex(pos.getIndex());
 	return null;
       }
+  }
+
+  // Compute the start of the current century as defined by
+  // get2DigitYearStart.
+  private Date computeCenturyStart ()
+  {
+    // Compute the current year.  We assume a year has 365 days.  Then
+    // compute 80 years ago, and finally reconstruct the number of
+    // milliseconds.  We do this computation in this strange way
+    // because it lets us easily truncate the milliseconds, seconds,
+    // etc, which don't matter and which confuse
+    // SimpleDateFormat.equals().
+    long now = System.currentTimeMillis ();
+    now /= 365L * 24L * 60L * 60L * 1000L;
+    now -= 80;
+    now *= 365L * 24L * 60L * 60L * 1000L;
+    return new Date (now);
   }
 }
Index: java/util/Calendar.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/util/Calendar.java,v
retrieving revision 1.8
diff -u -r1.8 Calendar.java
--- Calendar.java	2000/12/28 05:55:56	1.8
+++ Calendar.java	2001/05/10 16:29:02
@@ -1,5 +1,5 @@
 /* java.util.Calendar
-   Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
+   Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -54,7 +54,7 @@
  *
  * When computing the date from time fields, it may happen, that there
  * are either two few fields set, or some fields are inconsistent.  This
- * cases will handled in a calender specific way.  Missing fields are
+ * cases will handled in a calendar specific way.  Missing fields are
  * replaced by the fields of the epoch: 1970 January 1 00:00. <br>
  *
  * To understand, how the day of year is computed out of the fields
@@ -356,7 +356,7 @@
   private static final String bundleName = "gnu.java.locale.Calendar";
 
   /**
-   * Constructs a new Calender with the default time zone and the default
+   * Constructs a new Calendar with the default time zone and the default
    * locale.
    */
   protected Calendar()
@@ -365,7 +365,7 @@
   }
 
   /**
-   * Constructs a new Calender with the given time zone and the given
+   * Constructs a new Calendar with the given time zone and the given
    * locale.
    * @param zone a time zone.
    * @param locale a locale.
@@ -483,7 +483,7 @@
   }
 
   /**
-   * Sets this Calender's time to the given Date.  All time fields
+   * Sets this Calendar's time to the given Date.  All time fields
    * are invalidated by this method.
    */
   public final void setTime(Date date)
@@ -503,7 +503,7 @@
   }
 
   /**
-   * Sets this Calender's time to the given Time.  All time fields
+   * Sets this Calendar's time to the given Time.  All time fields
    * are invalidated by this method.
    * @param time the time in milliseconds since the epoch
    */
@@ -522,6 +522,9 @@
    */
   public final int get(int field)
   {
+    // If the requested field is invalid, force all fields to be recomputed.
+    if (!isSet[field])
+      areFieldsSet = false;
     complete();
     return fields[field];
   }
@@ -551,6 +554,29 @@
     isTimeSet = false;
     fields[field] = value;
     isSet[field] = true;
+    switch (field)
+      {
+      case YEAR:
+      case MONTH:
+      case DATE:
+	isSet[WEEK_OF_YEAR] = false;
+	isSet[DAY_OF_YEAR] = false;
+	isSet[WEEK_OF_MONTH] = false;
+	isSet[DAY_OF_WEEK] = false;
+	isSet[DAY_OF_WEEK_IN_MONTH] = false;
+	break;
+      case AM_PM:
+	isSet[HOUR_OF_DAY] = false;
+	break;
+      case HOUR_OF_DAY:
+	isSet[AM_PM] = false;
+	isSet[HOUR] = false;
+	break;
+      case HOUR:
+	isSet[AM_PM] = false;
+	isSet[HOUR_OF_DAY] = false;
+	break;
+      }
   }
 
   /**
@@ -568,6 +594,11 @@
     fields[MONTH] = month;
     fields[DATE] = date;
     isSet[YEAR] = isSet[MONTH] = isSet[DATE] = true;
+    isSet[WEEK_OF_YEAR] = false;
+    isSet[DAY_OF_YEAR] = false;
+    isSet[WEEK_OF_MONTH] = false;
+    isSet[DAY_OF_WEEK] = false;
+    isSet[DAY_OF_WEEK_IN_MONTH] = false;
   }
 
   /**
@@ -584,6 +615,8 @@
     fields[HOUR_OF_DAY] = hour;
     fields[MINUTE] = minute;
     isSet[HOUR_OF_DAY] = isSet[MINUTE] = true;
+    isSet[AM_PM] = false;
+    isSet[HOUR] = false;
   }
 
   /**
@@ -611,7 +644,10 @@
     isTimeSet = false;
     areFieldsSet = false;
     for (int i = 0; i < FIELD_COUNT; i++)
-      isSet[i] = false;
+      {
+	isSet[i] = false;
+	fields[i] = 0;
+      }
   }
 
   /**
@@ -623,6 +659,7 @@
     isTimeSet = false;
     areFieldsSet = false;
     isSet[field] = false;
+    fields[field] = 0;
   }
 
   /**
@@ -647,7 +684,7 @@
   }
 
   /**
-   * Compares the given calender with this.  
+   * Compares the given calendar with this.  
    * @param o the object to that we should compare.
    * @return true, if the given object is a calendar, that represents
    * the same time (but doesn't neccessary have the same fields).
@@ -670,10 +707,10 @@
   }
 
   /**
-   * Compares the given calender with this.  
+   * Compares the given calendar with this.  
    * @param o the object to that we should compare.
    * @return true, if the given object is a calendar, and this calendar
-   * represents a smaller time than the calender o.
+   * represents a smaller time than the calendar o.
    * @exception ClassCastException if o is not an calendar.
    * @since JDK1.2 you don't need to override this method
    */
@@ -683,10 +720,10 @@
   }
 
   /**
-   * Compares the given calender with this.  
+   * Compares the given calendar with this.  
    * @param o the object to that we should compare.
    * @return true, if the given object is a calendar, and this calendar
-   * represents a bigger time than the calender o.
+   * represents a bigger time than the calendar o.
    * @exception ClassCastException if o is not an calendar.
    * @since JDK1.2 you don't need to override this method
    */
@@ -866,7 +903,7 @@
    * @since jdk1.2
    */
   // FIXME: XXX: Not abstract in JDK 1.2.
-  // public abstract int getActualMinimum(int field);
+  public abstract int getActualMinimum(int field);
 
   /**
    * Gets the actual maximum value that is allowed for the specified field.
@@ -876,7 +913,7 @@
    * @since jdk1.2
    */
   // FIXME: XXX: Not abstract in JDK 1.2.
-  // public abstract int getActualMaximum(int field);
+  public abstract int getActualMaximum(int field);
 
   /**
    * Return a clone of this object.
Index: java/util/GregorianCalendar.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/util/GregorianCalendar.java,v
retrieving revision 1.8
diff -u -r1.8 GregorianCalendar.java
--- GregorianCalendar.java	2000/12/28 05:55:56	1.8
+++ GregorianCalendar.java	2001/05/10 16:29:02
@@ -1,265 +1,1071 @@
-/* Copyright (C) 1998, 1999, 2000  Free Software Foundation
+/* java.util.GregorianCalendar
+   Copyright (C) 1998, 1999, 2001 Free Software Foundation, Inc.
 
-   This file is part of libgcj.
+This file is part of GNU Classpath.
 
-This software is copyrighted work licensed under the terms of the
-Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
-details.  */
+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.util;
 
 /**
- * @author Per Bothner <bothner@cygnus.com>
- * @date October 24, 1998.
- */
-
-/* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3,
- * and "The Java Language Specification", ISBN 0-201-63451-1.
- * Status:  "leniency" is not handled, and neither is roll-over in
- *   add and roll.  This is partly because of unclear specification.
- *   hashCode has no spec.
+ * This class represents the Gregorian calendar, that is used in most
+ * countries all over the world.  It does also handle the Julian calendar
+ * for dates smaller than the date of the change to the Gregorian calendar.
+ * This change date is different from country to country, you can set it with
+ * <code>setGregorianChange</code>
+ *
+ * The Gregorian calendar differs from the Julian calendar by a different
+ * leap year rule (no leap year every 100 years, except if year is divisible
+ * by 400).  The non existing days that were omited when the change took
+ * place are interpreted as gregorian date
+ *
+ * There are to eras available for the Gregorian calendar, namely BC and AD.
+ *
+ * @see Calendar
+ * @see TimeZone
  */
-
-public class GregorianCalendar extends Calendar {
+public class GregorianCalendar extends Calendar
+{
+  /**
+   * Constant representing the era BC (before Christ).
+   */
   public static final int BC = 0;
+  
+  /**
+   * Constant representing the era AD (Anno Domini).
+   */
   public static final int AD = 1;
-
-  // The fields are as specified in Sun's "Serialized Form"
-  // in the JDK 1.2 beta 4 API specification.
-  // Value from a simple test program (getGregorianChange.getTime()).
-  long gregorianCutover = -12219292800000L;
 
-  private final static int[] mins = {
-    0 /* ERA */,
-    1 /* YEAR */,
-    0 /* MONTH */,
-    0 /* WEEK_OF_YEAR */,
-    0 /* WEEK_OF_MONTH */,
-    1 /* DATE */,
-    1 /* DAY_OF_YEAR */,
-    1 /* DAY_OF_WEEK */,
-    -1 /* DAY_OF_WEEK_IN_MONTH */,
-    0 /* AM_PM */,
-    0 /* HOUR */,
-    0 /* HOUR_OF_DAY */,
-    0 /* MINUTE */,
-    0 /* SECOND */,
-    0 /* MILLISECOND */,
-    -43200000 /* ZONE_OFFSET */,
-    0 /* DST_OFFSET */
-  };
+  /**
+   * The point at which the Gregorian calendar rules were used.
+   * This is locale dependent; the default for most catholic
+   * countries is midnight (UTC) on October 5, 1582 (Julian),
+   * or October 15, 1582 (Gregorian).
+   */
+  private long gregorianCutover;
+
+  static final long serialVersionUID = -8125100834729963327L;
+
+  /**
+   * The name of the resource bundle.
+   */
+  private static final String bundleName = "gnu.java.locale.Calendar";
+
+  /**
+   * Constructs a new GregorianCalender representing the current
+   * time, using the default time zone and the default locale.  
+   */
+  public GregorianCalendar()
+  {
+    this(TimeZone.getDefault(), Locale.getDefault());
+  }
+  
+  /**
+   * Constructs a new GregorianCalender representing the current
+   * time, using the specified time zone and the default locale.  
+   * @param zone a time zone.
+   */
+  public GregorianCalendar(TimeZone zone)
+  {
+    this(zone, Locale.getDefault());
+  }
+  
+  /**
+   * Constructs a new GregorianCalender representing the current
+   * time, using the default time zone and the specified locale.  
+   * @param locale a locale.
+   */
+  public GregorianCalendar(Locale locale)
+  {
+    this(TimeZone.getDefault(), locale);
+  }
 
-  private final static int[] maxs = {
-    1 /* ERA */,
-    5000000 /* YEAR */,
-    11 /* MONTH */,
-    54 /* WEEK_OF_YEAR */,
-    6 /* WEEK_OF_MONTH */,
-    31 /* DATE */,
-    366 /* DAY_OF_YEAR */,
-    7 /* DAY_OF_WEEK */,
-    6 /* DAY_OF_WEEK_IN_MONTH */,
-    1 /* AM_PM */,
-    12 /* HOUR */,
-    23 /* HOUR_OF_DAY */,
-    59 /* MINUTE */,
-    59 /* SECOND */,
-    999 /* MILLISECOND */,
-    43200000 /* ZONE_OFFSET */,
-    3600000 /* DST_OFFSET */
-  };
+  /**
+   * Constructs a new GregorianCalender representing the current
+   * time with the given time zone and the given locale.
+   * @param zone a time zone.  
+   * @param locale a locale.  
+   */
+  public GregorianCalendar(TimeZone zone, Locale locale)
+  {
+    super(zone, locale);
+    ResourceBundle rb = ResourceBundle.getBundle(bundleName, locale);
+    gregorianCutover = ((Date) rb.getObject("gregorianCutOver")).getTime();
+    time = System.currentTimeMillis();
+    isTimeSet = true;
+    areFieldsSet = false;
+  }
 
-  private final static int[] leastMaximums = {
-    1 /* ERA */,
-    5000000 /* YEAR */,
-    11 /* MONTH */,
-    53 /* WEEK_OF_YEAR */,
-    6 /* WEEK_OF_MONTH */,
-    28 /* DATE */,
-    365 /* DAY_OF_YEAR */,
-    7 /* DAY_OF_WEEK */,
-    4 /* DAY_OF_WEEK_IN_MONTH */,
-    1 /* AM_PM */,
-    11 /* HOUR */,
-    23 /* HOUR_OF_DAY */,
-    59 /* MINUTE */,
-    59 /* SECOND */,
-    999 /* MILLISECOND */,
-    43200000 /* ZONE_OFFSET */,
-    3600000 /* DST_OFFSET */
-  };
+  /**
+   * Constructs a new GregorianCalendar representing midnight on the
+   * given date with the default time zone and locale.
+   * @param year corresponds to the YEAR time field.
+   * @param month corresponds to the MONTH time field.
+   * @param day corresponds to the DAY time field.
+   */
+  public GregorianCalendar(int year, int month, int day)
+  {
+    super();
+    set(year, month, day);
+  }
 
-  private static final long serialVersionUID = -8125100834729963327L;
+  /**
+   * Constructs a new GregorianCalendar representing midnight on the
+   * given date with the default time zone and locale.
+   * @param year corresponds to the YEAR time field.
+   * @param month corresponds to the MONTH time field.
+   * @param day corresponds to the DAY time field.
+   * @param hour corresponds to the HOUR_OF_DAY time field.
+   * @param minute corresponds to the MINUTE time field.
+   */
+  public GregorianCalendar(int year, int month, int day, int hour, int minute)
+  {
+    super();
+    set(year, month, day, hour, minute);
+  }
 
-  public GregorianCalendar ()
+  /**
+   * Constructs a new GregorianCalendar representing midnight on the
+   * given date with the default time zone and locale.
+   * @param year corresponds to the YEAR time field.
+   * @param month corresponds to the MONTH time field.
+   * @param day corresponds to the DAY time field.
+   * @param hour corresponds to the HOUR_OF_DAY time field.
+   * @param minute corresponds to the MINUTE time field.
+   * @param second corresponds to the SECOND time field.
+   */
+  public GregorianCalendar(int year, int month, int day,
+			   int hour, int minute, int second)
   {
-    this(TimeZone.getDefault (), Locale.getDefault ());
+    super();
+    set(year, month, day, hour, minute, second);
   }
 
-  public GregorianCalendar (TimeZone zone)
+  /**
+   * Sets the date of the switch from Julian dates to Gregorian dates.
+   * You can use <code>new Date(Long.MAX_VALUE)</code> to use a pure
+   * Julian calendar, or <code>Long.MIN_VALUE</code> for a pure Gregorian
+   * calendar.
+   * @param date the date of the change.
+   */
+  public void setGregorianChange(Date date)
   {
-    this (zone, Locale.getDefault ());
+    gregorianCutover = date.getTime();
   }
 
-  public GregorianCalendar (Locale locale)
+  /**
+   * Gets the date of the switch from Julian dates to Gregorian dates.
+   * @return the date of the change.
+   */
+  public final Date getGregorianChange(Date date)
   {
-    this (TimeZone.getDefault (), locale);
+    return new Date(gregorianCutover);
   }
 
-  public GregorianCalendar (TimeZone zone, Locale locale)
+  /**
+   * Determines if the given year is a leap year.  The result is
+   * undefined if the gregorian change took place in 1800, so that
+   * the end of february is skiped and you give that year
+   * (well...).<br>
+   *
+   * The year should be positive and you can't give an ERA.  But
+   * remember that before 4 BC there wasn't a consistent leap year
+   * rule, so who cares.
+   *
+   * @param year a year use nonnegative value for BC.
+   * @return true, if the given year is a leap year, false otherwise.  */
+  public boolean isLeapYear(int year)
   {
-    super (zone, locale);
-    setDefaultTime ();
+    if ((year & 3) != 0)
+      // Only years divisible by 4 can be leap years
+      return false;
+
+    // compute the linear day of the 29. February of that year.
+    // The 13 is the number of days, that were omitted in the Gregorian
+    // Calender until the epoch.
+    int julianDay = (((year-1) * (365*4+1)) >> 2) + (31+29 - 
+        (((1970-1) * (365*4+1)) / 4 + 1 - 13));
+    
+    // If that day is smaller than the gregorianChange the julian
+    // rule applies:  This is a leap year since it is divisible by 4.
+    if (julianDay * (24 * 60 * 60 * 1000L) < gregorianCutover)
+      return true;
+
+    return ((year % 100) != 0 || (year % 400) == 0);
   }
 
-  public GregorianCalendar (int year, int month, int date)
+  /**
+   * Get the linear time in milliseconds since the epoch.  If you
+   * specify a nonpositive year it is interpreted as BC as
+   * following: 0 is 1 BC, -1 is 2 BC and so on.  The date is
+   * interpreted as gregorian if the change occured before that date.
+   *
+   * @param year the year of the date.
+   * @param dayOfYear the day of year of the date; 1 based.
+   * @param millis the millisecond in that day.
+   * @return the days since the epoch, may be negative.  */
+  private long getLinearTime(int year, int dayOfYear, int millis)
   {
-    this();
-    set (year, month, date, 0, 0, 0);
+    // The 13 is the number of days, that were omitted in the Gregorian
+    // Calender until the epoch.
+    // We shift right by 2 instead of dividing by 4, to get correct
+    // results for negative years (and this is even more efficient).
+    int julianDay = ((year * (365 * 4 + 1)) >> 2) + dayOfYear -
+      ((1970 * (365 * 4 + 1)) / 4 + 1 - 13);
+    long time = julianDay * (24 * 60 * 60 * 1000L) + millis;
+
+    if (time >= gregorianCutover)
+      {
+	// subtract the days that are missing in gregorian calendar
+	// with respect to julian calendar.
+	//
+	// Okay, here we rely on the fact that the gregorian
+	// calendar was introduced in the AD era.  This doesn't work
+	// with negative years.
+	//
+	// The additional leap year factor accounts for the fact that
+	// a leap day is not seen on Jan 1 of the leap year.
+	int gregOffset = (year / 400) - (year / 100) + 2;
+	if (isLeapYear (year, true) && dayOfYear < 31 + 29)
+	  --gregOffset;
+	time += gregOffset * (24 * 60 * 60 * 1000L);
+      }
+    return time;
   }
 
-  public GregorianCalendar (int year, int month, int date,
-			    int hour, int minute)
+  private int getWeekDay(int year, int dayOfYear)
   {
-    this();
-    set (year, month, date, hour, minute, 0);
+    int day =
+      (int) (getLinearTime(year, dayOfYear, 0) / (24 * 60 * 60 * 1000L));
+
+    // The epoch was a thursday.
+    int weekday = (day + THURSDAY) % 7;
+    if (weekday <= 0)
+      weekday += 7;
+    return weekday;
   }
 
-  public GregorianCalendar (int year, int month, int date,
-			    int hour, int minute, int second)
+  /**
+   * Calculate the dayOfYear from the fields array.  
+   * The relativeDays is used, to account for weeks that begin before
+   * the gregorian change and end after it.<br>
+   *
+   * We return two values, the first is used to determine, if we
+   * should use Gregorian calendar or Julian calendar, in case of
+   * the change year, the second is a relative day after the given
+   * day.  This is necessary for week calculation in the year in
+   * which gregorian change occurs. <br>
+   *
+   * @param year the year, negative for BC.
+   * @return an array of two int values, the first containing a reference
+   * day of current year, the second a relative count since this reference
+   * day.  */
+  private int[] getDayOfYear(int year)
   {
-    this();
-    set (year, month, date, hour, minute, second);
+    if (isSet[MONTH])
+      {
+	int dayOfYear;
+	if (fields[MONTH] > FEBRUARY)
+	  {
+
+	    // The months after February are regular:
+	    // 9 is an offset found by try and error.
+	    dayOfYear = (fields[MONTH] * (31 + 30 + 31 + 30 + 31) - 9) / 5;
+	    if (isLeapYear(year))
+	      dayOfYear++;
+	  }
+	else
+	    dayOfYear = 31 * fields[MONTH];
+
+	if (isSet[DAY_OF_MONTH])
+	  {
+	    return new int[]
+	    {
+	    dayOfYear + fields[DAY_OF_MONTH], 0};
+	  }
+	if (isSet[WEEK_OF_MONTH] && isSet[DAY_OF_WEEK])
+	  {
+	    // the weekday of the first day in that month is:
+	    int weekday = getWeekDay(year, ++dayOfYear);
+
+	    return new int[]
+	    {
+	      dayOfYear,
+		// the day of week in the first week
+		// (weeks starting on sunday) is:
+	      fields[DAY_OF_WEEK] - weekday +
+		// Now jump to the right week and correct the possible
+		// error made by assuming sunday is the first week day.
+	      7 * (fields[WEEK_OF_MONTH]
+		   + (fields[DAY_OF_WEEK] < getFirstDayOfWeek()? 0 : -1)
+		   + (weekday < getFirstDayOfWeek()? -1 : 0))};
+	  }
+	if (isSet[DAY_OF_WEEK] && isSet[DAY_OF_WEEK_IN_MONTH])
+	  {
+	    // the weekday of the first day in that month is:
+	    int weekday = getWeekDay(year, ++dayOfYear);
+	    return new int[] { 
+		  dayOfYear,
+		  fields[DAY_OF_WEEK] - weekday +
+		  7 * (fields[DAY_OF_WEEK_IN_MONTH]
+		       + (fields[DAY_OF_WEEK] < weekday ? 0 : -1))};
+	  }
+      }
+
+    // MONTH + something did not succeed.
+    if (isSet[DAY_OF_YEAR])
+      {
+	return new int[] {0, fields[DAY_OF_YEAR]};
+      }
+      
+    if (isSet[DAY_OF_WEEK] && isSet[WEEK_OF_YEAR])
+      {
+	int dayOfYear = getMinimalDaysInFirstWeek();
+	// the weekday of the day, that begins the first week 
+	// in that year is:
+	int weekday = getWeekDay(year, dayOfYear);
+
+	return new int[] { 
+	    dayOfYear,
+	      // the day of week in the first week
+	      // (weeks starting on sunday) is:
+	    fields[DAY_OF_WEEK] - weekday
+	      // Now jump to the right week and correct the possible
+	      // error made by assuming sunday is the first week day.
+	    + 7 * (fields[WEEK_OF_YEAR]
+		   + (fields[DAY_OF_WEEK] < getFirstDayOfWeek()? 0 : -1)
+		   + (weekday < getFirstDayOfWeek()? -1 : 0))};
+      }
+
+    // As last resort return Jan, 1st.
+    return new int[] {1, 0};
   }
 
-  private final void setDefaultTime ()
+  /**
+   * Converts the time field values (<code>fields</code>) to
+   * milliseconds since the epoch UTC (<code>time</code>). 
+   */
+  protected synchronized void computeTime()
   {
-    setTimeInMillis (System.currentTimeMillis());
+    int era = isSet[ERA] ? fields[ERA] : AD;
+    int year = isSet[YEAR] ? fields[YEAR] : 1970;
+    if (era == BC)
+      year = 1 - year;
+
+    int[] daysOfYear = getDayOfYear(year);
+    int hour = isSet[HOUR_OF_DAY] ? fields[HOUR_OF_DAY]
+      : (isSet[HOUR] && isSet[AM_PM]
+	 ? fields[AM_PM] * 12 + (fields[HOUR] % 12) : 0);
+    int minute = isSet[MINUTE] ? fields[MINUTE] : 0;
+    int second = isSet[SECOND] ? fields[SECOND] : 0;
+    int millis = isSet[MILLISECOND] ? fields[MILLISECOND] : 0;
+    int millisInDay;
+
+    if (isLenient())
+      {
+	// prevent overflow
+	long allMillis = (((hour * 60L) + minute) * 60L + second) * 1000L
+	  + millis;
+	daysOfYear[1] += allMillis / (24 * 60 * 60 * 1000L);
+	millisInDay = (int) (allMillis % (24 * 60 * 60 * 1000L));
+      }
+    else
+      {
+	if (hour < 0 || hour >= 24 || minute < 0 || minute > 59
+	    || second < 0 || second > 59 || millis < 0 || millis >= 1000)
+	  throw new IllegalArgumentException();
+	millisInDay = (((hour * 60) + minute) * 60 + second) * 1000 + millis;
+      }
+    time = getLinearTime(year, daysOfYear[0], millisInDay);
+
+    // Add the relative days after calculating the linear time, to
+    // get right behaviour when jumping over the gregorianCutover.
+    time += daysOfYear[1] * (24 * 60 * 60 * 1000L);
+
+
+    TimeZone zone = getTimeZone();
+    int rawOffset = isSet[ZONE_OFFSET]
+      ? fields[ZONE_OFFSET] : getTimeZone().getRawOffset();
+
+    int dayOfYear = daysOfYear[0] + daysOfYear[1];
+    int month = (dayOfYear * 5 + 3) / (31 + 30 + 31 + 30 + 31);
+    int day = (6 + (dayOfYear * 5 + 3) % (31 + 30 + 31 + 30 + 31)) / 5;
+    int weekday = ((int) (time / (24 * 60 * 60 * 1000L)) + THURSDAY) % 7;
+    if (weekday <= 0)
+      weekday += 7;
+    int dstOffset = isSet[DST_OFFSET]
+      ? fields[DST_OFFSET] : (zone.getOffset((year < 0) ? BC : AD,
+					     (year < 0) ? 1 - year : year,
+					     month, day, weekday, millisInDay)
+			      - zone.getRawOffset());
+    time -= rawOffset + dstOffset;
+    isTimeSet = true;
   }
 
-  public int getMinimum(int calfield) { return mins[calfield]; }
-  public int getGreatestMinimum(int calfield) { return mins[calfield]; }
-  public int getMaximum(int calfield) { return maxs[calfield]; }
-  public int getLeastMaximum(int calfield) { return leastMaximums[calfield]; }
+  /**
+   * Determines if the given year is a leap year.  
+   *
+   * The year should be positive and you can't give an ERA.  But
+   * remember that before 4 BC there wasn't a consistent leap year
+   * rule, so who cares.
+   *
+   * @param year a year use nonnegative value for BC.
+   * @param gregorian if true, use gregorian leap year rule.
+   * @return true, if the given year is a leap year, false otherwise.  */
+  private boolean isLeapYear(int year, boolean gregorian)
+  {
+    if ((year & 3) != 0)
+      // Only years divisible by 4 can be leap years
+      return false;
 
-  protected native void computeFields();
+    if (!gregorian)
+      return true;
 
-  protected native void computeTime();
+    // We rely on AD area here.
+    return ((year % 100) != 0 || (year % 400) == 0);
+  }
 
-  public void add (int fld, int amount)
+  /**
+   * Get the linear day in days since the epoch, using the
+   * Julian or Gregorian calendar as specified.  If you specify a
+   * nonpositive year it is interpreted as BC as following: 0 is 1
+   * BC, -1 is 2 BC and so on.  
+   *
+   * @param year the year of the date.
+   * @param dayOfYear the day of year of the date; 1 based.
+   * @param gregorian True, if we should use Gregorian rules.
+   * @return the days since the epoch, may be negative.  */
+  private int getLinearDay(int year, int dayOfYear, boolean gregorian)
   {
-    if (fld >= ZONE_OFFSET)
-      throw new IllegalArgumentException("bad field to add");
-    fields[fld] += amount;
-    adjust(fld);
+    // The 13 is the number of days, that were omitted in the Gregorian
+    // Calender until the epoch.
+    // We shift right by 2 instead of dividing by 4, to get correct
+    // results for negative years (and this is even more efficient).
+    int julianDay = ((year * (365 * 4 + 1)) >> 2) + dayOfYear -
+      ((1970 * (365 * 4 + 1)) / 4 + 1 - 13);
+
+    if (gregorian)
+      {
+	// subtract the days that are missing in gregorian calendar
+	// with respect to julian calendar.
+	//
+	// Okay, here we rely on the fact that the gregorian
+	// calendar was introduced in the AD era.  This doesn't work
+	// with negative years.
+	//
+	// The additional leap year factor accounts for the fact that
+	// a leap day is not seen on Jan 1 of the leap year.
+	int gregOffset = (year / 400) - (year / 100) + 2;
+	if (isLeapYear (year, true) && dayOfYear < 31 + 29)
+	  --gregOffset;
+	julianDay += gregOffset;
+      }
+    return julianDay;
   }
 
-  public void roll (int fld, boolean up)
+  /**
+   * Converts the given linear day into era, year, month,
+   * day_of_year, day_of_month, day_of_week, and writes the result
+   * into the fields array.
+   * @param day the linear day.  
+   */
+  private void calculateDay(int day, boolean gregorian)
   {
-    if (fld >= ZONE_OFFSET)
-      throw new IllegalArgumentException("bad field to roll");
+    // the epoch is a Thursday.
+    int weekday = (day + THURSDAY) % 7;
+    if (weekday <= 0)
+      weekday += 7;
+    fields[DAY_OF_WEEK] = weekday;
+
+    // get a first approximation of the year.  This may be one 
+    // year to big.
+    int year = 1970 + (gregorian
+		       ? ((day - 100) * 400) / (365 * 400 + 100 - 4 + 1)
+		       : ((day - 100) * 4) / (365 * 4 + 1));
+    if (day >= 0)
+      year++;
+
+    int firstDayOfYear = getLinearDay(year, 1, gregorian);
+
+    // Now look in which year day really lies.
+    if (day < firstDayOfYear)
+      {
+	year--;
+	firstDayOfYear = getLinearDay(year, 1, gregorian);
+      }
+
+    day -= firstDayOfYear - 1;	// day of year,  one based.
+
+    fields[DAY_OF_YEAR] = day;
+    if (year <= 0)
+      {
+	fields[ERA] = BC;
+	fields[YEAR] = 1 - year;
+      }
+    else
+      {
+	fields[ERA] = AD;
+	fields[YEAR] = year;
+      }
 
-    int old = fields[fld];
-    if (up)
+    int leapday = isLeapYear(year, gregorian) ? 1 : 0;
+    if (day <= 31 + 28 + leapday)
       {
-	fields[fld] = old == getMaximum(fld) ? getMinimum(fld)
-	  : old + 1;
+	fields[MONTH] = day / 32;	// 31->JANUARY, 32->FEBRUARY
+	fields[DAY_OF_MONTH] = day - 31 * fields[MONTH];
       }
     else
+      {
+	// A few more magic formulas
+	int scaledDay = (day - leapday) * 5 + 8;
+	fields[MONTH] = scaledDay / (31 + 30 + 31 + 30 + 31);
+	fields[DAY_OF_MONTH] = (scaledDay % (31 + 30 + 31 + 30 + 31)) / 5 + 1;
+      }
+  }
+
+  /**
+   * Converts the milliseconds since the epoch UTC
+   * (<code>time</code>) to time fields
+   * (<code>fields</code>). 
+   */
+  protected synchronized void computeFields()
+  {
+    boolean gregorian = (time >= gregorianCutover);
+
+    TimeZone zone = getTimeZone();
+    fields[ZONE_OFFSET] = zone.getRawOffset();
+    long localTime = time + fields[ZONE_OFFSET];
+
+    int day = (int) (localTime / (24 * 60 * 60 * 1000L));
+    int millisInDay = (int) (localTime % (24 * 60 * 60 * 1000L));
+    if (millisInDay < 0)
+      {
+	millisInDay += (24 * 60 * 60 * 1000);
+	day--;
+      }
+
+    calculateDay(day, gregorian);
+    fields[DST_OFFSET] =
+      zone.getOffset(fields[ERA], fields[YEAR], fields[MONTH],
+		     fields[DAY_OF_MONTH], fields[DAY_OF_WEEK],
+		     millisInDay) - fields[ZONE_OFFSET];
+
+    millisInDay += fields[DST_OFFSET];
+    if (millisInDay >= 24 * 60 * 60 * 1000)
       {
-	fields[fld] = old == getMinimum(fld) ? getMaximum(fld)
-	  : old - 1;
+	millisInDay -= 24 * 60 * 60 * 1000;
+	calculateDay(++day, gregorian);
       }
+
+    fields[DAY_OF_WEEK_IN_MONTH] = (fields[DAY_OF_MONTH] + 6) / 7;
+
+    // which day of the week are we (0..6), relative to getFirstDayOfWeek
+    int relativeWeekday = (7 + fields[DAY_OF_WEEK] - getFirstDayOfWeek()) % 7;
+
+    fields[WEEK_OF_MONTH] = (fields[DAY_OF_MONTH] - relativeWeekday + 6) / 7;
+
+    int weekOfYear = (fields[DAY_OF_YEAR] - relativeWeekday + 6) / 7;
+
+    // Do the Correction: getMinimalDaysInFirstWeek() is always in the 
+    // first week.
+    int minDays = getMinimalDaysInFirstWeek();
+    int firstWeekday =
+      (7 + getWeekDay(fields[YEAR], minDays) - getFirstDayOfWeek()) % 7;
+    if (minDays - firstWeekday < 1)
+      weekOfYear++;
+    fields[WEEK_OF_YEAR] = weekOfYear;
+
+
+    int hourOfDay = millisInDay / (60 * 60 * 1000);
+    fields[AM_PM] = (hourOfDay < 12) ? AM : PM;
+    int hour = hourOfDay % 12;
+    fields[HOUR] = (hour == 0) ? 12 : hour;
+    fields[HOUR_OF_DAY] = hourOfDay;
+    millisInDay %= (60 * 60 * 1000);
+    fields[MINUTE] = millisInDay / (60 * 1000);
+    millisInDay %= (60 * 1000);
+    fields[SECOND] = millisInDay / (1000);
+    fields[MILLISECOND] = millisInDay % 1000;
+
+
+    areFieldsSet = isSet[ERA] = isSet[YEAR] = isSet[MONTH] =
+      isSet[WEEK_OF_YEAR] = isSet[WEEK_OF_MONTH] =
+      isSet[DAY_OF_MONTH] = isSet[DAY_OF_YEAR] = isSet[DAY_OF_WEEK] =
+      isSet[DAY_OF_WEEK_IN_MONTH] = isSet[AM_PM] = isSet[HOUR] =
+      isSet[HOUR_OF_DAY] = isSet[MINUTE] = isSet[SECOND] =
+      isSet[MILLISECOND] = isSet[ZONE_OFFSET] = isSet[DST_OFFSET] = true;
+
   }
 
-  private void adjust (int fld)
+  /**
+   * Compares the given calender with this.  
+   * @param o the object to that we should compare.
+   * @return true, if the given object is a calendar, that represents
+   * the same time (but doesn't neccessary have the same fields).
+   * @XXX Should we check if time zones, locale, cutover etc. are equal?
+   */
+  public boolean equals(Object o)
   {
-    int value = fields[fld];
-    int radix = maxs[fld] + 1;
-    switch (fld)
+    if (!(o instanceof GregorianCalendar))
+      return false;
+
+    GregorianCalendar cal = (GregorianCalendar) o;
+    return (cal.getTimeInMillis() == getTimeInMillis());
+  }
+
+//     /**
+//      * Compares the given calender with this.  
+//      * @param o the object to that we should compare.
+//      * @return true, if the given object is a calendar, and this calendar
+//      * represents a smaller time than the calender o.
+//      */
+//     public boolean before(Object o) {
+//         if (!(o instanceof GregorianCalendar))
+//             return false;
+
+//         GregorianCalendar cal = (GregorianCalendar) o;
+//         return (cal.getTimeInMillis() < getTimeInMillis());
+//     }
+
+//     /**
+//      * Compares the given calender with this.  
+//      * @param o the object to that we should compare.
+//      * @return true, if the given object is a calendar, and this calendar
+//      * represents a bigger time than the calender o.
+//      */
+//     public boolean after(Object o) {
+//         if (!(o instanceof GregorianCalendar))
+//             return false;
+
+//         GregorianCalendar cal = (GregorianCalendar) o;
+//         return (cal.getTimeInMillis() > getTimeInMillis());
+//     }
+
+  /**
+   * Adds the specified amount of time to the given time field.  The
+   * amount may be negative to subtract the time.  If the field overflows
+   * it does what you expect: Jan, 25 + 10 Days is Feb, 4.
+   * @param field the time field. One of the time field constants.
+   * @param amount the amount of time.
+   */
+  public void add(int field, int amount)
+  {
+    switch (field)
       {
+      case YEAR:
+	complete();
+	fields[YEAR] += amount;
+	isTimeSet = false;
+	break;
       case MONTH:
-      case SECOND:
-      case MILLISECOND:
-	if (value >= radix)
+	complete();
+	int months = fields[MONTH] + amount;
+	fields[YEAR] += months / 12;
+	fields[MONTH] = months % 12;
+	if (fields[MONTH] < 0)
 	  {
-	    int next = value / radix;
-	    fields[fld] = value - radix * next;
-	    fields[fld - 1] += next;
-	    adjust(fld - 1);
+	    fields[MONTH] += 12;
+	    fields[YEAR]--;
 	  }
-	else if (value < 0) // min[fld]
+	isTimeSet = false;
+	int maxDay = getActualMaximum(DAY_OF_MONTH);
+	if (fields[DAY_OF_MONTH] > maxDay)
 	  {
-	    int next = (value - radix - 1) / radix;
-	    fields[fld] = value - radix * next;
-	    fields[fld - 1] += next;
-            adjust(fld - 1);
+	    fields[DAY_OF_MONTH] = maxDay;
+	    isTimeSet = false;
 	  }
 	break;
+      case DAY_OF_MONTH:
+      case DAY_OF_YEAR:
+      case DAY_OF_WEEK:
+	if (!isTimeSet)
+	  computeTime();
+	time += amount * (24 * 60 * 60 * 1000L);
+	areFieldsSet = false;
+	break;
+      case WEEK_OF_YEAR:
+      case WEEK_OF_MONTH:
+      case DAY_OF_WEEK_IN_MONTH:
+	if (!isTimeSet)
+	  computeTime();
+	time += amount * (7 * 24 * 60 * 60 * 1000L);
+	areFieldsSet = false;
+	break;
+      case AM_PM:
+	if (!isTimeSet)
+	  computeTime();
+	time += amount * (12 * 60 * 60 * 1000L);
+	areFieldsSet = false;
+	break;
+      case HOUR:
+      case HOUR_OF_DAY:
+	if (!isTimeSet)
+	  computeTime();
+	time += amount * (60 * 60 * 1000L);
+	areFieldsSet = false;
+	break;
+      case MINUTE:
+	if (!isTimeSet)
+	  computeTime();
+	time += amount * (60 * 1000L);
+	areFieldsSet = false;
+	break;
+      case SECOND:
+	if (!isTimeSet)
+	  computeTime();
+	time += amount * (1000L);
+	areFieldsSet = false;
+	break;
+      case MILLISECOND:
+	if (!isTimeSet)
+	  computeTime();
+	time += amount;
+	areFieldsSet = false;
+	break;
+      case ZONE_OFFSET:
+	complete();
+	fields[ZONE_OFFSET] += amount;
+	time -= amount;
+	break;
+      case DST_OFFSET:
+	complete();
+	fields[DST_OFFSET] += amount;
+	isTimeSet = false;
+	break;
+      default:
+	throw new IllegalArgumentException
+	  ("Unknown Calendar field: " + field);
       }
   }
 
-  public final Date getGregorianChange() { return new Date(gregorianCutover); }
-  public void setGregorianChange (Date date)
-  { gregorianCutover = date.getTime(); }
 
-  public boolean isLeapYear(int year)
+  /**
+   * Rolls the specified time field up or down.  This means add one
+   * to the specified field, but don't change the other fields.  If
+   * the maximum for this field is reached, start over with the 
+   * minimum value.  
+   *
+   * <strong>Note:</strong> There may be situation, where the other
+   * fields must be changed, e.g rolling the month on May, 31. 
+   * The date June, 31 is automatically converted to July, 1. 
+   * This requires lenient settings.
+   *
+   * @param field the time field. One of the time field constants.
+   * @param up the direction, true for up, false for down.
+   */
+  public void roll(int field, boolean up)
   {
-    if ((year % 4) != 0)
-      return false;
-    if ((year % 100) != 0 || (year % 400) == 0)
-      return true;
-    // year divisible by 100 but not 400.
-    GregorianCalendar date = new GregorianCalendar(year, FEBRUARY, 28);
-    return gregorianCutover < date.getTimeInMillis();
+    roll(field, up ? 1 : -1);
+  }
+
+  private void cleanUpAfterRoll(int field, int delta)
+  {
+    switch (field)
+      {
+      case ERA:
+      case YEAR:
+      case MONTH:
+	// check that day of month is still in correct range
+	if (fields[DAY_OF_MONTH] > getActualMaximum(DAY_OF_MONTH))
+	  fields[DAY_OF_MONTH] = getActualMaximum(DAY_OF_MONTH);
+	isTimeSet = false;
+	isSet[WEEK_OF_MONTH] = false;
+	isSet[DAY_OF_WEEK] = false;
+	isSet[DAY_OF_WEEK_IN_MONTH] = false;
+	isSet[DAY_OF_YEAR] = false;
+	isSet[WEEK_OF_YEAR] = false;
+	break;
+
+      case DAY_OF_MONTH:
+	isSet[WEEK_OF_MONTH] = false;
+	isSet[DAY_OF_WEEK] = false;
+	isSet[DAY_OF_WEEK_IN_MONTH] = false;
+	isSet[DAY_OF_YEAR] = false;
+	isSet[WEEK_OF_YEAR] = false;
+	time += delta * (24 * 60 * 60 * 1000L);
+	break;
+
+      case WEEK_OF_MONTH:
+	isSet[DAY_OF_MONTH] = false;
+	isSet[DAY_OF_WEEK_IN_MONTH] = false;
+	isSet[DAY_OF_YEAR] = false;
+	isSet[WEEK_OF_YEAR] = false;
+	time += delta * (7 * 24 * 60 * 60 * 1000L);
+	break;
+      case DAY_OF_WEEK_IN_MONTH:
+	isSet[DAY_OF_MONTH] = false;
+	isSet[WEEK_OF_MONTH] = false;
+	isSet[DAY_OF_YEAR] = false;
+	isSet[WEEK_OF_YEAR] = false;
+	time += delta * (7 * 24 * 60 * 60 * 1000L);
+	break;
+      case DAY_OF_YEAR:
+	isSet[MONTH] = false;
+	isSet[DAY_OF_MONTH] = false;
+	isSet[WEEK_OF_MONTH] = false;
+	isSet[DAY_OF_WEEK_IN_MONTH] = false;
+	isSet[DAY_OF_WEEK] = false;
+	isSet[WEEK_OF_YEAR] = false;
+	time += delta * (24 * 60 * 60 * 1000L);
+	break;
+      case WEEK_OF_YEAR:
+	isSet[MONTH] = false;
+	isSet[DAY_OF_MONTH] = false;
+	isSet[WEEK_OF_MONTH] = false;
+	isSet[DAY_OF_WEEK_IN_MONTH] = false;
+	isSet[DAY_OF_YEAR] = false;
+	time += delta * (7 * 24 * 60 * 60 * 1000L);
+	break;
+
+      case AM_PM:
+	isSet[HOUR_OF_DAY] = false;
+	time += delta * (12 * 60 * 60 * 1000L);
+	break;
+      case HOUR:
+	isSet[HOUR_OF_DAY] = false;
+	time += delta * (60 * 60 * 1000L);
+	break;
+      case HOUR_OF_DAY:
+	isSet[HOUR] = false;
+	isSet[AM_PM] = false;
+	time += delta * (60 * 60 * 1000L);
+	break;
+
+      case MINUTE:
+	time += delta * (60 * 1000L);
+	break;
+      case SECOND:
+	time += delta * (1000L);
+	break;
+      case MILLISECOND:
+	time += delta;
+	break;
+      }
   }
 
-  public boolean after (Object cal)
+  /**
+   * Rolls the specified time field by the given amount.  This means
+   * add amount to the specified field, but don't change the other
+   * fields.  If the maximum for this field is reached, start over
+   * with the minimum value and vice versa for negative amounts.
+   *
+   * <strong>Note:</strong> There may be situation, where the other
+   * fields must be changed, e.g rolling the month on May, 31. 
+   * The date June, 31 is automatically corrected to June, 30.
+   *
+   * @param field the time field. One of the time field constants.
+   * @param amount the amount by which we should roll.
+   */
+  public void roll(int field, int amount)
   {
-    return cal instanceof Calendar
-      && getTimeInMillis() > ((Calendar) cal).getTimeInMillis();
+    switch (field)
+      {
+      case DAY_OF_WEEK:
+	// day of week is special: it rolls automatically
+	add(field, amount);
+	return;
+      case ZONE_OFFSET:
+      case DST_OFFSET:
+	throw new IllegalArgumentException("Can't roll time zone");
+      }
+    complete();
+    int min = getActualMinimum(field);
+    int range = getActualMaximum(field) - min + 1;
+    int oldval = fields[field];
+    int newval = (oldval - min + range + amount) % range + min;
+    if (newval < min)
+      newval += range;
+    fields[field] = newval;
+    cleanUpAfterRoll(field, newval - oldval);
   }
 
-  public boolean before (Object cal)
+  private static final int[] minimums =
+      { BC,       1,  1,  0, 1,  1,   1,   SUNDAY, 1, 
+        AM,  1,  0,  1,  1,   1, -(12*60*60*1000),               0 };
+
+  private static final int[] maximums =
+      { AD, 5000000, 12, 53, 5, 31, 366, SATURDAY, 5, 
+        PM, 12, 23, 59, 59, 999, +(12*60*60*1000), (12*60*60*1000) };
+
+  /**
+   * Gets the smallest value that is allowed for the specified field.
+   * @param field the time field. One of the time field constants.
+   * @return the smallest value.
+   */
+  public int getMinimum(int field)
   {
-    return cal instanceof Calendar
-      && getTimeInMillis() < ((Calendar) cal).getTimeInMillis();
+    return minimums[field];
   }
 
-  public boolean equals (Object obj)
+  /**
+   * Gets the biggest value that is allowed for the specified field.
+   * @param field the time field. One of the time field constants.
+   * @return the biggest value.
+   */
+  public int getMaximum(int field)
   {
-    if (obj == null || ! (obj instanceof GregorianCalendar))
-      return false;
-    GregorianCalendar other = (GregorianCalendar) obj;
+    return maximums[field];
+  }
+
+
+  /**
+   * Gets the greatest minimum value that is allowed for the specified field.
+   * @param field the time field. One of the time field constants.
+   * @return the greatest minimum value.
+   */
+  public int getGreatestMinimum(int field)
+  {
+    if (field == WEEK_OF_YEAR)
+      return 1;
+    return minimums[field];
+  }
 
-    for (int i = FIELD_COUNT;  --i >= 0; )
+  /**
+   * Gets the smallest maximum value that is allowed for the
+   * specified field.  For example this is 28 for DAY_OF_MONTH.
+   * @param field the time field. One of the time field constants.
+   * @return the least maximum value.  
+   * @since jdk1.2
+   */
+  public int getLeastMaximum(int field)
+  {
+    switch (field)
       {
-	boolean set = isSet[i];
-	if (set != other.isSet[i]
-	    || (set && fields[i] != other.fields[i]))
-	  return false;
-      }
-    if (areFieldsSet != other.areFieldsSet
-	|| isTimeSet != other.isTimeSet
-	|| (isTimeSet && time != other.time)
-	|| getFirstDayOfWeek() != other.getFirstDayOfWeek()
-	|| getMinimalDaysInFirstWeek() != other.getMinimalDaysInFirstWeek()
-	|| isLenient() != other.isLenient()
-	|| ! getTimeZone().equals(other.getTimeZone()))
-      return false;
-    return true;
+      case WEEK_OF_YEAR:
+	return 52;
+      case DAY_OF_MONTH:
+	return 28;
+      case DAY_OF_YEAR:
+	return 365;
+      case DAY_OF_WEEK_IN_MONTH:
+      case WEEK_OF_MONTH:
+	return 4;
+      default:
+	return maximums[field];
+      }
+  }
+
+  /**
+   * Gets the actual minimum value that is allowed for the specified field.
+   * This value is dependant on the values of the other fields.  Note that
+   * this calls <code>complete()</code> if not enough fields are set.  This
+   * can have ugly side effects.
+   * @param field the time field. One of the time field constants.
+   * @return the actual minimum value.
+   * @since jdk1.2
+   */
+  public int getActualMinimum(int field)
+  {
+    if (field == WEEK_OF_YEAR)
+      {
+	int min = getMinimalDaysInFirstWeek();
+	if (min == 0)
+	  return 1;
+	if (!areFieldsSet || !isSet[ERA] || !isSet[YEAR])
+	  complete();
+
+	int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR];
+	int weekday = getWeekDay(year, min);
+	if ((7 + weekday - getFirstDayOfWeek()) % 7 >= min - 1)
+	  return 1;
+	return 0;
+      }
+    return minimums[field];
   }
 
-  public int hashCode ()
+  /**
+   * Gets the actual maximum value that is allowed for the specified field.
+   * This value is dependant on the values of the other fields.  Note that
+   * this calls <code>complete()</code> if not enough fields are set.  This
+   * can have ugly side effects.
+   * @param field the time field. One of the time field constants.
+   * @return the actual maximum value.  
+   */
+  public int getActualMaximum(int field)
   {
-    int hashcode = 0;
-    for (int i = FIELD_COUNT;  --i >= 0; )
+    switch (field)
       {
-	if (isSet[i])
-	  hashcode += 37 * fields[i];
+      case WEEK_OF_YEAR:
+	{
+	  if (!areFieldsSet || !isSet[ERA] || !isSet[YEAR])
+	    complete();
+	  // This is wrong for the year that contains the gregorian change.
+	  // I.e it gives the weeks in the julian year or in the gregorian
+	  // year in that case.
+	  int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR];
+	  int lastDay = isLeapYear(year) ? 366 : 365;
+	  int weekday = getWeekDay(year, lastDay);
+	  int week = (lastDay + 6
+		      - (7 + weekday - getFirstDayOfWeek()) % 7) / 7;
+
+	  int minimalDays = getMinimalDaysInFirstWeek();
+	  int firstWeekday = getWeekDay(year, minimalDays);
+	  if (minimalDays - (7 + firstWeekday - getFirstDayOfWeek()) % 7 < 1)
+	    return week + 1;
+	}
+	case DAY_OF_MONTH:
+	{
+	  if (!areFieldsSet || !isSet[MONTH])
+	    complete();
+	  int month = fields[MONTH];
+	  // If you change this, you should also change 
+	  // SimpleTimeZone.getDaysInMonth();
+	  if (month == FEBRUARY)
+	    {
+	      if (!isSet[YEAR] || !isSet[ERA])
+		complete();
+	      int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR];
+	      return isLeapYear(year) ? 29 : 28;
+	    }
+	  else if (month < AUGUST)
+	    return 31 - (month & 1);
+	  else
+	    return 30 + (month & 1);
+	}
+      case DAY_OF_YEAR:
+	{
+	  if (!areFieldsSet || !isSet[ERA] || !isSet[YEAR])
+	    complete();
+	  int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR];
+	  return isLeapYear(year) ? 366 : 365;
+	}
+      case DAY_OF_WEEK_IN_MONTH:
+	{
+	  // This is wrong for the month that contains the gregorian change.
+	  int daysInMonth = getActualMaximum(DAY_OF_MONTH);
+	  // That's black magic, I know
+	  return (daysInMonth - (fields[DAY_OF_MONTH] - 1) % 7 + 6) / 7;
+	}
+      case WEEK_OF_MONTH:
+	{
+	  int daysInMonth = getActualMaximum(DAY_OF_MONTH);
+	  int weekday = (daysInMonth - fields[DAY_OF_MONTH]
+			 + fields[DAY_OF_WEEK] - SUNDAY) % 7 + SUNDAY;
+	  return (daysInMonth + 6
+		  - (7 + weekday - getFirstDayOfWeek()) % 7) / 7;
+	}
+      default:
+	return maximums[field];
       }
-    if (isTimeSet)
-      hashcode += 89 * time;
-    return hashcode;
   }
 }
Index: java/util/natGregorianCalendar.cc
===================================================================
RCS file: natGregorianCalendar.cc
diff -N natGregorianCalendar.cc
--- /sourceware/cvs-tmp/cvsb2LShp	Thu May 10 09:29:02 2001
+++ /dev/null	Tue May  5 13:32:27 1998
@@ -1,159 +0,0 @@
-/* Copyright (C) 1998, 1999, 2000, 2001  Free Software Foundation
-
-   This file is part of libgcj.
-
-This software is copyrighted work licensed under the terms of the
-Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
-details.  */
-
-#include <config.h>
-
-#ifdef ECOS
-#include <string.h>
-#endif
-
-#include <gcj/cni.h>
-#include <java/util/TimeZone.h>
-#include <java/util/GregorianCalendar.h>
-#include <java/lang/IllegalArgumentException.h>
-#include <time.h>
-
-void
-java::util::GregorianCalendar::computeTime ()
-{
-  struct tm tim;
-  tim.tm_sec = elements(fields)[SECOND];
-  tim.tm_min = elements(fields)[MINUTE];
-  tim.tm_hour = elements(fields)[HOUR_OF_DAY];
-  tim.tm_mday = elements(fields)[DATE];
-  tim.tm_mon = elements(fields)[MONTH];
-  tim.tm_year = elements(fields)[YEAR] - 1900;
-  tim.tm_isdst = 0;
-#ifndef ECOS
-  // FIXME: None of the standard C library access to the ECOS calendar
-  // is yet available.
-  time_t t = mktime (&tim);
-
-  if (!isLenient ())
-    {
-      // mktime will correct for any time leniencies (e.g. 31-Apr becomes
-      // 1-May).
-      // Daylight savings time is a special case since times in hour 23
-      // will compute to hour 0 of the next day.
-      if (tim.tm_isdst == 0 || elements(fields)[HOUR_OF_DAY] != 23)
-        {
-	  if (tim.tm_sec != elements(fields)[SECOND] ||
-	      tim.tm_min != elements(fields)[MINUTE] ||
-	      tim.tm_hour != elements(fields)[HOUR_OF_DAY] +
-	      		     (tim.tm_isdst > 0 ? 1 : 0) ||
-	      tim.tm_mday != elements(fields)[DATE] ||
-	      tim.tm_mon != elements(fields)[MONTH] ||
-	      tim.tm_year != elements(fields)[YEAR] - 1900)
-	    throw new java::lang::IllegalArgumentException ();
-        }
-      else
-        {
-	  // The easiest thing to do is to temporarily shift the clock
-	  // back from the 23th hour so mktime doesn't cause the extra
-	  // hour for DST to roll the date to the next day.
-	  struct tm tmp_tim;
-	  tmp_tim.tm_sec = elements(fields)[SECOND];
-	  tmp_tim.tm_min = elements(fields)[MINUTE];
-	  tmp_tim.tm_hour = elements(fields)[HOUR_OF_DAY] - 1;
-	  tmp_tim.tm_mday = elements(fields)[DATE];
-	  tmp_tim.tm_mon = elements(fields)[MONTH];
-	  tmp_tim.tm_year = elements(fields)[YEAR] - 1900;
-	  tmp_tim.tm_isdst = 0;
-	  mktime (&tmp_tim);
-	  if (tmp_tim.tm_sec != elements(fields)[SECOND] ||
-	      tmp_tim.tm_min != elements(fields)[MINUTE] ||
-	      tmp_tim.tm_hour != elements(fields)[HOUR_OF_DAY] ||
-	      tmp_tim.tm_mday != elements(fields)[DATE] ||
-	      tmp_tim.tm_mon != elements(fields)[MONTH] ||
-	      tmp_tim.tm_year != elements(fields)[YEAR] - 1900)
-	    throw new java::lang::IllegalArgumentException ();
-	}
-    }
-#else
-  time_t t = 0;
-#endif
-
-  // Adjust for local timezone (introduced by mktime) and our
-  // timezone.
-#if defined (STRUCT_TM_HAS_GMTOFF)
-  t -= tim.tm_gmtoff;
-#elif defined (HAVE_TIMEZONE)
-  t += timezone;
-#endif
-  // Adjust for milliseconds.
-  time = t * (jlong) 1000 + elements(fields)[MILLISECOND];
-
-  // Now adjust for the real timezone, i.e. our timezone, which is in millis.
-  java::util::TimeZone *zone = getTimeZone ();
-  time += zone->getRawOffset();
-
-  isTimeSet = true;
-}
-
-void
-java::util::GregorianCalendar::computeFields ()
-{
-  time_t t = time / 1000;
-  int millis = time % 1000;
-  if (t < 0 && millis != 0)
-    {
-      t--;
-      millis = t - 1000 * t;
-    }
-  elements(fields)[MILLISECOND] = millis;
-  struct tm tim;
-  java::util::TimeZone *zone = getTimeZone ();
-
-  // FIXME: None of the standard C library access to the ECOS calendar
-  // is yet available.
-#ifdef ECOS
-  memset (&tim, 0, sizeof tim); 
-#else
-  if (zone->getRawOffset() == 0 || ! zone->useDaylightTime())
-    {
-#if defined(__JV_POSIX_THREADS__) && defined(HAVE_GMTIME_R)
-      gmtime_r (&t, &tim);
-#else
-      // Get global lock (because gmtime uses a global buffer).  FIXME
-      tim = *(struct tm*) gmtime (&t);
-      // Release global lock.  FIXME
-#endif
-    }
-  else
-    {
-#if defined(__JV_POSIX_THREADS__) && defined(HAVE_LOCALTIME_R)
-      localtime_r (&t, &tim);
-#else
-      // Get global lock (because localtime uses a global buffer).  FIXME
-      tim = *(struct tm*) localtime (&t);
-      // Release global lock.  FIXME
-#endif
-    }
-#endif /* ECOS */
-  elements(fields)[SECOND] = tim.tm_sec;
-  elements(fields)[MINUTE] = tim.tm_min;
-  elements(fields)[HOUR_OF_DAY] = tim.tm_hour;
-  elements(fields)[AM_PM] = tim.tm_hour < 12 ? AM : PM;
-  elements(fields)[HOUR] = tim.tm_hour % 12;
-  elements(fields)[DATE] = tim.tm_mday;
-  elements(fields)[MONTH] = tim.tm_mon;
-  elements(fields)[YEAR] = 1900 + tim.tm_year;
-  elements(fields)[DAY_OF_WEEK] = tim.tm_wday + 1;
-  elements(fields)[DAY_OF_WEEK_IN_MONTH] = ((tim.tm_mday - 1) / 7) + 1;
-  elements(fields)[DAY_OF_YEAR] = tim.tm_yday + 1;
-  elements(fields)[WEEK_OF_MONTH]
-    = (tim.tm_mday + 6 + (5 - tim.tm_wday + getFirstDayOfWeek()) % 7) / 7;
-  elements(fields)[WEEK_OF_YEAR]
-    = (tim.tm_yday + 7 + (5 - tim.tm_wday + getFirstDayOfWeek()) % 7) / 7;
-  elements(fields)[ERA] = AD;
-  elements(fields)[DST_OFFSET] = tim.tm_isdst <= 0 ? 0 : 60*60*1000;
-  elements(fields)[ZONE_OFFSET] = getTimeZone()->getRawOffset();
-  areFieldsSet = true;
-  for (int i = 0; i < FIELD_COUNT; i++)
-    elements(isSet__)[i] = true;
-}
Index: gnu/java/locale/LocaleInformation.java
===================================================================
RCS file: LocaleInformation.java
diff -N LocaleInformation.java
--- /dev/null	Tue May  5 13:32:27 1998
+++ LocaleInformation.java	Thu May 10 09:29:02 2001
@@ -0,0 +1,37 @@
+/* LocaleInformation.java -- Default locale information
+   Copyright (C) 1998 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 gnu.java.locale;
+
+/**
+  * This is the resource bundle for the default locale, which right now is 
+  * hardcoded to US English.
+  */
+public class LocaleInformation extends LocaleInformation_en
+{
+}
+
Index: gnu/java/locale/LocaleInformation_de.java
===================================================================
RCS file: LocaleInformation_de.java
diff -N LocaleInformation_de.java
--- /dev/null	Tue May  5 13:32:27 1998
+++ LocaleInformation_de.java	Thu May 10 09:29:02 2001
@@ -0,0 +1,220 @@
+/* LocaleInformation_de.java -- German locale data
+   Copyright (C) 1999 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 gnu.java.locale;
+
+import java.util.ListResourceBundle;
+import java.util.Calendar;
+
+/**
+  * This class contains locale data for the German locale
+  * @author Jochen Hoenicke
+  */
+public class LocaleInformation_de extends ListResourceBundle
+{
+
+/*
+ * This area is used for defining object values
+ */
+
+/**
+  * This is the set of collation rules used by java.text.RuleBasedCollator 
+  * to sort strings properly.  See the documentation of that class for the 
+  * proper format.
+  */
+private static final String collation_rules = 
+  "-<0,1<2<3<4<5<6<7<8<9<A,a<b,B<c,C<d,D<e,E<f,F<g,G<h,H<i,I<j,J<j,K" +
+  "<l,L<m,M<n,N<o,O<p,P<q,Q<r,R<s,S<t,T<u,U<v,V<w,W<x,X<y,Y,z<Z" + 
+  "&ae,\u00e4&Ae,\u00c4&oe,\u00f6&Oe,\u00d6&ue,\u00fc&Ue,\u00dc&ss,\u00df";
+
+/**
+  * This is the list of months, fully spelled out
+  */
+private static final String[] months = { "Januar", "Februar", "M\u00e4rz", 
+  "April", "Mai", "Juni", "Juli", "August", "September", "Oktober",
+  "November", "Dezember", null };
+
+/**
+  * This is the list of abbreviated month names
+  */
+private static final String[] shortMonths = { 
+  "Jan", "Feb", "M\u00e4r", "Apr", "Mai",
+  "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez", null 
+};
+
+/**
+  * This is the list of weekdays, fully spelled out
+  */
+private static final String[] weekdays = { 
+  null, "Sonntag", "Montag", "Dienstag",
+  "Mittwoch", "Donnerstag", "Freitag", "Samstag" 
+};
+
+/**
+  * This is the list of abbreviated weekdays
+  */
+private static final String[] shortWeekdays = { 
+  null, "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa" 
+};
+
+/**
+  * This is the list of era identifiers
+  */
+private static final String[] eras = { "v. Chr.", "n. Chr." };
+
+/**
+  * This is the list of timezone strings.  The JDK appears to include a
+  * city name as the sixth element.
+  */
+private static final String[][] zoneStrings =
+{
+  // European time zones.  The city names are a little bit random.
+  { "WET", "Westeurop\u00e4ische Zeit", "WEZ", "Westeurop\u00e4ische Sommerzeit", "WESZ", "London" },
+  { "CET", "Mitteleurop\u00e4ische Zeit", "MEZ", "Mitteleurop\u00e4ische Sommerzeit", "MESZ", "Berlin" },
+  { "EET", "Osteurop\u00e4ische Zeit", "OEZ", "Mitteleurop\u00e4ische Sommerzeit", "OESZ", "Istanbul" },
+};
+
+/**
+  * This is the DateFormat.SHORT date format
+  */
+private static final String shortDateFormat = "dd.MM.yy";
+
+/**
+  * This is the DateFormat.MEDIUM format
+  */
+private static final String mediumDateFormat = "d. MMM yy";
+
+/**
+  * This is the DateFormat.LONG format
+  */
+private static final String longDateFormat = "d. MMMM yyyy";
+
+/**
+  * This is the DateFormat.FULL format
+  */
+private static final String fullDateFormat = "EEEE, d. MMMM yyyy";
+
+/**
+  * This is the DateFormat.DEFAULT format
+  */
+private static final String defaultDateFormat = "dd.MM.yy";
+
+/**
+  * This is the DateFormat.SHORT format
+  */
+private static final String shortTimeFormat = "H:mm";
+
+/**
+  * This is the DateFormat.MEDIUM format
+  */
+private static final String mediumTimeFormat = "H:mm:ss";
+
+/**
+  * This is the DateFormat.LONG format
+  */
+private static final String longTimeFormat = "H:mm:ss z";
+
+/**
+  * This is the DateFormat.FULL format
+  */
+private static final String fullTimeFormat = "H:mm:ss 'Uhr' z";
+
+/**
+  * This is the DateFormat.DEFAULT format
+  */
+private static final String defaultTimeFormat = "H:mm:ss";
+
+/**
+  * This is the currency symbol
+  */
+private static final String currencySymbol = "DM";
+
+/**
+  * This is the international currency symbol. 
+  */
+private static final String intlCurrencySymbol = "DEM";
+
+/**
+  * This is the decimal point.
+  */
+private static final String decimalSeparator = ",";
+
+/**
+  * This is the decimal separator in monetary values.
+  */
+private static final String monetarySeparator = ",";
+
+/*************************************************************************/
+
+/**
+  * This is the object array used to hold the keys and values
+  * for this bundle
+  */
+
+private static final Object[][] contents =
+{
+  // For RuleBasedCollator
+  { "collation_rules", collation_rules },
+  // For SimpleDateFormat/DateFormatSymbols
+  { "months", months },
+  { "shortMonths", shortMonths },
+  { "weekdays", weekdays },
+  { "shortWeekdays", shortWeekdays },
+  { "eras", eras },
+  { "zoneStrings", zoneStrings },
+  { "shortDateFormat", shortDateFormat },
+  { "mediumDateFormat", mediumDateFormat },
+  { "longDateFormat", longDateFormat },
+  { "fullDateFormat", fullDateFormat },
+  { "defaultDateFormat", defaultDateFormat },
+  { "shortTimeFormat", shortTimeFormat },
+  { "mediumTimeFormat", mediumTimeFormat },
+  { "longTimeFormat", longTimeFormat },
+  { "fullTimeFormat", fullTimeFormat },
+  { "defaultTimeFormat", defaultTimeFormat },
+  // For DecimalFormat/DecimalFormatSymbols
+  { "currencySymbol", currencySymbol },
+  { "intlCurrencySymbol", intlCurrencySymbol },
+  { "decimalSeparator", decimalSeparator },
+  { "monetarySeparator", monetarySeparator },
+};
+
+/*************************************************************************/
+
+/**
+  * This method returns the object array of key, value pairs containing
+  * the data for this bundle.
+  *
+  * @return The key, value information.
+  */
+public Object[][]
+getContents()
+{
+  return(contents);
+}
+
+} // class LocaleInformation_de
Index: gnu/java/locale/LocaleInformation_en.java
===================================================================
RCS file: LocaleInformation_en.java
diff -N LocaleInformation_en.java
--- /dev/null	Tue May  5 13:32:27 1998
+++ LocaleInformation_en.java	Thu May 10 09:29:02 2001
@@ -0,0 +1,332 @@
+/* LocaleInformation_en.java -- US English locale data
+   Copyright (C) 1998, 1999 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 gnu.java.locale;
+
+import java.util.ListResourceBundle;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+  * This class contains locale data for the US English locale
+  */
+
+public class LocaleInformation_en extends ListResourceBundle
+{
+
+/*
+ * This area is used for defining object values
+ */
+
+/**
+  * This is the set of collation rules used by java.text.RuleBasedCollator 
+  * to sort strings properly.  See the documentation of that class for the 
+  * proper format.
+  */
+private static final String collation_rules = 
+  "-<0,1<2<3<4<5<6<7<8<9A,a<b,B<c,C<d,D<e,E<f,F<g,G<h,H<i,I<j,J<j,K" +
+  "<l,L<m,M<n,N<o,O<p,P<q,Q<r,R<s,S<t,T<u,U<v,V<w,W<x,X<y,Y,z<Z";
+
+/*
+ * For the followings lists, strings that are subsets of other break strigns
+ * must be listed first.  For example, if "\r" and "\r\n" are sequences,
+ * the "\r" must be first or it will never be used.
+ */
+
+/**
+  * This is the list of word separator characters used by 
+  * java.text.BreakIterator 
+  */
+private static final String[] word_breaks = { " ", "\t", "\r\n", "\n" }; 
+
+/**
+  * This is the list of sentence break sequences used by 
+  * java.text.BreakIterator
+  */
+private static final String[] sentence_breaks = { ". " };
+
+/**
+  * This is the list of potential line break locations.
+  */
+private static final String[] line_breaks = { "\t", "-", "\r\n", 
+  "\n", ".  ", ". ", ".",  "?  ", "? ", "?",  "!  ", "! ", "!", ", ", " " };
+
+/**
+  * This is the list of months, fully spelled out
+  */
+private static final String[] months = { "January", "February", "March", 
+  "April", "May", "June", "July", "August", "September", "October",
+  "November", "December", null };
+
+/**
+  * This is the list of abbreviated month names
+  */
+private static final String[] shortMonths = { "Jan", "Feb", "Mar", "Apr", "May",
+  "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", null };
+
+/**
+  * This is the list of weekdays, fully spelled out
+  */
+private static final String[] weekdays = { null, "Sunday", "Monday", "Tuesday",
+  "Wednesday", "Thursday", "Friday", "Saturday" };
+
+/**
+  * This is the list of abbreviated weekdays
+  */
+private static final String[] shortWeekdays = { null, "Sun", "Mon", "Tue", "Wed",
+  "Thu", "Fri", "Sat" };
+
+/**
+  * This is the list of AM/PM strings
+  */
+private static final String[] ampms = { "AM", "PM" };
+
+/**
+  * This is the list of era identifiers
+  */
+private static final String[] eras = { "BC", "AD" };
+
+/**
+  * This is the list of timezone strings.  The JDK appears to include a
+  * city name as the sixth element.
+  */
+private static final String[][] zoneStrings =
+{
+  { "EST6EDT", "Eastern Standard Time", "EST", "Eastern Daylight Time", "EDT",
+    "New York" },
+  { "EST6", "Eastern Standard Time", "EST", "Eastern Standard Time", "EST",
+    "Indianapolis" },
+  { "CST6CDT", "Central Standard Time", "CST", "Central Daylight Time", "CDT",
+    "Chicago" },
+  { "MST6MDT", "Mountain Standard Time", "MST", "Mountain Daylight Time", 
+    "MDT", "Denver" },
+  { "MST6", "Mountain Standard Time", "MST", "Mountain Standard Time", "MST",
+    "Phoenix" },
+  { "PST6PDT", "Pacific Standard Time", "PDT", "Pacific Daylight Time", "PDT",
+    "San Francisco" },
+  { "AST6ADT", "Alaska Standard Time", "AST", "Alaska Daylight Time", "ADT",
+    "Anchorage" },
+  { "HST6HDT", "Hawaii Standard Time", "HST", "Hawaii Daylight Time", "HDT",
+    "Honolulu" },
+  // European time zones.  The city names are a little bit random.
+  { "WET", "Western European Time", "WET", "Western European Savings Time", "WEST", "London" },
+  { "CET", "Central European Time", "CET", "Central European Savings Time", "CEST", "Berlin" },
+  { "EET", "Eastern European Time", "EET", "Eastern European Savings Time", "EEST", "Istanbul" },
+};
+
+/**
+  * This is the list of pattern characters for formatting dates
+  */
+private static final String localPatternChars = "GyMdkHmsSEDFwWahKz"; // Not a mistake!
+
+/**
+  * This is the DateFormat.SHORT date format
+  */
+private static final String shortDateFormat = "M/d/yy";
+
+/**
+  * This is the DateFormat.MEDIUM format
+  */
+private static final String mediumDateFormat = "dd-MMM-yy";
+
+/**
+  * This is the DateFormat.LONG format
+  */
+private static final String longDateFormat = "MMMM d, yyyy";
+
+/**
+  * This is the DateFormat.FULL format
+  */
+private static final String fullDateFormat = "EEEE, MMMM d, yyyy";
+
+/**
+  * This is the DateFormat.DEFAULT format
+  */
+private static final String defaultDateFormat = "dd-MMM-yy";
+
+/**
+  * This is the DateFormat.SHORT format
+  */
+private static final String shortTimeFormat = "h:mm a";
+
+/**
+  * This is the DateFormat.MEDIUM format
+  */
+private static final String mediumTimeFormat = "h:mm:ss a";
+
+/**
+  * This is the DateFormat.LONG format
+  */
+private static final String longTimeFormat = "h:mm:ss a z";
+
+/**
+  * This is the DateFormat.FULL format
+  */
+private static final String fullTimeFormat = "h:mm:ss 'o''clock' a z";
+
+/**
+  * This is the DateFormat.DEFAULT format
+  */
+private static final String defaultTimeFormat = "h:mm:ss a";
+
+/**
+  * This is the currency symbol
+  */
+private static final String currencySymbol = "$";
+
+/**
+  * This is the international currency symbol. 
+  */
+private static final String intlCurrencySymbol = "US$";
+
+/**
+  * This is the decimal point.
+  */
+private static final String decimalSeparator = ".";
+
+/**
+  * This is the exponential symbol
+  */
+private static final String exponential = "E";
+
+/**
+  * This is the char used for digits in format strings
+  */
+private static final String digit = "#";
+
+/**
+  * This is the grouping separator symbols
+  */
+private static final String groupingSeparator = ",";
+
+/**
+  * This is the symbols for infinity
+  */
+private static final String infinity = "\u221e";
+
+/**
+  * This is the symbol for the not a number value
+  */
+private static final String NaN = "\ufffd";
+
+/**
+  * This is the minus sign symbol.
+  */
+private static final String minusSign = "-";
+
+/**
+  * This is the decimal separator in monetary values.
+  */
+private static final String monetarySeparator = ".";
+
+/**
+  * This is the separator between positive and negative subpatterns.
+  */
+private static final String patternSeparator = ";";
+
+/**
+  * This is the percent sign
+  */
+private static final String percent = "%";
+
+/**
+  * This is the per mille sign
+  */
+private static final String perMill = "\u2030";
+
+/**
+  * This is the character for zero.
+  */
+private static final String zeroDigit = "0";
+
+/*************************************************************************/
+
+/**
+  * This is the object array used to hold the keys and values
+  * for this bundle
+  */
+
+private static final Object[][] contents =
+{
+  // For RuleBasedCollator
+  { "collation_rules", collation_rules },
+  // For BreakIterator
+  { "word_breaks", word_breaks },
+  { "sentence_breaks", sentence_breaks },
+  { "line_breaks", line_breaks },
+  // For SimpleDateFormat/DateFormatSymbols
+  { "months", months },
+  { "shortMonths", shortMonths },
+  { "weekdays", weekdays },
+  { "shortWeekdays", shortWeekdays },
+  { "ampms", ampms },
+  { "eras", eras },
+  { "zoneStrings", zoneStrings },
+  { "localPatternChars", localPatternChars },
+  { "shortDateFormat", shortDateFormat },
+  { "mediumDateFormat", mediumDateFormat },
+  { "longDateFormat", longDateFormat },
+  { "fullDateFormat", fullDateFormat },
+  { "defaultDateFormat", defaultDateFormat },
+  { "shortTimeFormat", shortTimeFormat },
+  { "mediumTimeFormat", mediumTimeFormat },
+  { "longTimeFormat", longTimeFormat },
+  { "fullTimeFormat", fullTimeFormat },
+  { "defaultTimeFormat", defaultTimeFormat },
+  // For DecimalFormat/DecimalFormatSymbols
+  { "currencySymbol", currencySymbol },
+  { "intlCurrencySymbol", intlCurrencySymbol },
+  { "decimalSeparator", decimalSeparator },
+  { "digit", digit },
+  { "exponential", exponential },
+  { "groupingSeparator", groupingSeparator },
+  { "infinity", infinity },
+  { "NaN", NaN },
+  { "minusSign", minusSign },
+  { "monetarySeparator", monetarySeparator },
+  { "patternSeparator", patternSeparator },
+  { "percent", percent },
+  { "perMill", perMill },
+  { "zeroDigit", zeroDigit },
+};
+
+/*************************************************************************/
+
+/**
+  * This method returns the object array of key, value pairs containing
+  * the data for this bundle.
+  *
+  * @return The key, value information.
+  */
+public Object[][]
+getContents()
+{
+  return(contents);
+}
+
+} // class LocaleInformation_en
+
Index: gnu/java/locale/LocaleInformation_nl.java
===================================================================
RCS file: LocaleInformation_nl.java
diff -N LocaleInformation_nl.java
--- /dev/null	Tue May  5 13:32:27 1998
+++ LocaleInformation_nl.java	Thu May 10 09:29:02 2001
@@ -0,0 +1,338 @@
+/* LocaleInformation_nl.java -- Dutch locale data
+   Copyright (C) 1999 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 gnu.java.locale;
+
+import java.util.ListResourceBundle;
+import java.util.Calendar;
+import java.util.Date;
+
+/**
+  * This class contains locale data for the Dutch locale
+  */
+
+public class LocaleInformation_nl extends ListResourceBundle
+{
+
+/*
+ * This area is used for defining object values
+ */
+
+/**
+  * This is the set of collation rules used by java.text.RuleBasedCollator 
+  * to sort strings properly.  See the documentation of that class for the 
+  * proper format.
+  * <p>
+  * This is the same rule as used in the English locale.
+  */
+private static final String collation_rules = 
+  "-<0,1<2<3<4<5<6<7<8<9A,a<b,B<c,C<d,D<e,E<f,F<g,G<h,H<i,I<j,J<j,K" +
+  "<l,L<m,M<n,N<o,O<p,P<q,Q<r,R<s,S<t,T<u,U<v,V<w,W<x,X<y,Y,z<Z";
+
+/*
+ * For the followings lists, strings that are subsets of other break strings
+ * must be listed first.  For example, if "\r" and "\r\n" are sequences,
+ * the "\r" must be first or it will never be used.
+ */
+
+/**
+  * This is the list of word separator characters used by 
+  * java.text.BreakIterator 
+  * <p>
+  * This is the same list as used in the English local
+  */
+private static final String[] word_breaks = { " ", "\t", "\r\n", "\n" }; 
+
+/**
+  * This is the list of sentence break sequences used by 
+  * java.text.BreakIterator
+  * <p>
+  * This is the same list as used in the English local
+  */
+private static final String[] sentence_breaks = { ". " };
+
+/**
+  * This is the list of potential line break locations.
+  * <p>
+  * This is the same list as used in the English local
+  */
+private static final String[] line_breaks = { "\t", "-", "\r\n", 
+  "\n", ".  ", ". ", ".",  "?  ", "? ", "?",  "!  ", "! ", "!", ", ", " " };
+
+/**
+  * This is the list of months, fully spelled out
+  */
+private static final String[] months = { "januari", "februari", "maart", 
+  "april", "mei", "juni", "juli", "augustus", "september", "october",
+  "november", "december", null };
+
+/**
+  * This is the list of abbreviated month names
+  */
+private static final String[] shortMonths = { "jan", "feb", "mrt", "apr", "mei",
+  "jun", "jul", "aug", "sep", "oct", "nov", "dec", null };
+
+/**
+  * This is the list of weekdays, fully spelled out
+  */
+private static final String[] weekdays = { null, "zondag", "maandag", "dinsdag",
+  "woensdag", "donderdag", "vrijdag", "zaterdag" };
+
+/**
+  * This is the list of abbreviated weekdays
+  */
+private static final String[] shortWeekdays = { null, "zo", "ma", "di", "wo",
+  "do", "vr", "za" };
+
+/**
+  * This is the list of AM/PM strings
+  * <p>
+  * Is there a real equivalent in Dutch? "Voormiddag"/"Namiddag"?
+  * Just using the Latin names for now.
+  */
+private static final String[] ampms = { "AM", "PM" };
+
+/**
+  * This is the list of era identifiers
+  * <p>
+  * Is there a real equivalent in Dutch? "voor Christus"/"na Christus"?
+  * Just use the Latin/English names for now.
+  */
+private static final String[] eras = { "BC", "AD" };
+
+/**
+  * This is the list of timezone strings.  The JDK appears to include a
+  * city name as the sixth element.
+  * XXX - TODO - FIXME - Which timezones should be included here and how are
+  * they called?
+  */
+private static final String[][] zoneStrings =
+{
+  // European time zones.  The city names are a little bit random.
+  { "WET", "West Europese Tijd", "WET", "West Europese Zomertijd", "WEST", "London" },
+  { "CET", "Centraal Europese Tijd", "CET", "Centraal Europese Zomertijd", "CEST", "Amsterdam" },
+  { "EET", "Oost Europese Tijd", "EET", "Oost Europese Zomertijd", "EEST", "Istanbul" },
+};
+
+/**
+  * This is the list of pattern characters for formatting dates
+  * <p>
+  * This is the same as the English locale uses: era (G), year (y), month (M),
+  * month (d), hour from 1-12 (h), hour 0-23 (H), minute (m), second (s),
+  * millisecond (S), date of week (E), date of year (D),
+  * day of week in month (F), week in year (w), week in month (W), am/pm (a),
+  * hour from 1-24 (k), hour from 0-11 (K), time zone (z).
+  * Why would you use others?
+  */
+private static final String localPatternChars = "GyMdhHmsSEDFwWakKz"; // Not a mistake!
+
+/**
+  * This is the DateFormat.SHORT date format
+  */
+private static final String shortDateFormat = "dd-MM-yy";
+
+/**
+  * This is the DateFormat.MEDIUM format
+  */
+private static final String mediumDateFormat = "dd-MMM-yy";
+
+/**
+  * This is the DateFormat.LONG format
+  */
+private static final String longDateFormat = "dd MMMM yyyy";
+
+/**
+  * This is the DateFormat.FULL format
+  */
+private static final String fullDateFormat = "EEEE dd MMMM yyyy";
+
+/**
+  * This is the DateFormat.DEFAULT format
+  */
+private static final String defaultDateFormat = mediumDateFormat;
+
+/**
+  * This is the TimeFormat.SHORT format
+  */
+private static final String shortTimeFormat = "HH:mm";
+
+/**
+  * This is the TimeFormat.MEDIUM format
+  */
+private static final String mediumTimeFormat = "HH:mm:ss";
+
+/**
+  * This is the TimeFormat.LONG format
+  */
+private static final String longTimeFormat = "HH:mm:ss";
+
+/**
+  * This is the TimeFormat.FULL format
+  */
+private static final String fullTimeFormat = "HH:mm:ss z";
+
+/**
+  * This is the TimeFormat.DEFAULT format
+  */
+private static final String defaultTimeFormat = shortTimeFormat;
+
+/**
+  * This is the currency symbol
+  */
+private static final String currencySymbol = "fl";
+
+/**
+  * This is the international currency symbol. 
+  */
+private static final String intlCurrencySymbol = "NLG";
+
+/**
+  * This is the decimal point.
+  */
+private static final String decimalSeparator = ",";
+
+/**
+  * This is the exponential symbol
+  */
+private static final String exponential = "E";
+
+/**
+  * This is the char used for digits in format strings
+  */
+private static final String digit = "#";
+
+/**
+  * This is the grouping separator symbols
+  */
+private static final String groupingSeparator = ",";
+
+/**
+  * This is the symbols for infinity
+  */
+private static final String infinity = "\u221e";
+
+/**
+  * This is the symbol for the not a number value
+  */
+private static final String NaN = "\ufffd";
+
+/**
+  * This is the minus sign symbol.
+  */
+private static final String minusSign = "-";
+
+/**
+  * This is the decimal separator in monetary values.
+  */
+private static final String monetarySeparator = ",";
+
+/**
+  * This is the separator between positive and negative subpatterns.
+  */
+private static final String patternSeparator = ";";
+
+/**
+  * This is the percent sign
+  */
+private static final String percent = "%";
+
+/**
+  * This is the per mille sign
+  */
+private static final String perMill = "\u2030";
+
+/**
+  * This is the character for zero.
+  */
+private static final String zeroDigit = "0";
+
+/*************************************************************************/
+
+/**
+  * This is the object array used to hold the keys and values
+  * for this bundle
+  */
+
+private static final Object[][] contents =
+{
+  // For RuleBasedCollator
+  { "collation_rules", collation_rules },
+  // For BreakIterator
+  { "word_breaks", word_breaks },
+  { "sentence_breaks", sentence_breaks },
+  { "line_breaks", line_breaks },
+  // For SimpleDateFormat/DateFormatSymbols
+  { "months", months },
+  { "shortMonths", shortMonths },
+  { "weekdays", weekdays },
+  { "shortWeekdays", shortWeekdays },
+  { "ampms", ampms },
+  { "eras", eras },
+  { "zoneStrings", zoneStrings },
+  { "localPatternChars", localPatternChars },
+  { "shortDateFormat", shortDateFormat },
+  { "mediumDateFormat", mediumDateFormat },
+  { "longDateFormat", longDateFormat },
+  { "fullDateFormat", fullDateFormat },
+  { "defaultDateFormat", defaultDateFormat },
+  { "shortTimeFormat", shortTimeFormat },
+  { "mediumTimeFormat", mediumTimeFormat },
+  { "longTimeFormat", longTimeFormat },
+  { "fullTimeFormat", fullTimeFormat },
+  { "defaultTimeFormat", defaultTimeFormat },
+  // For DecimalFormat/DecimalFormatSymbols
+  { "currencySymbol", currencySymbol },
+  { "intlCurrencySymbol", intlCurrencySymbol },
+  { "decimalSeparator", decimalSeparator },
+  { "digit", digit },
+  { "exponential", exponential },
+  { "groupingSeparator", groupingSeparator },
+  { "infinity", infinity },
+  { "NaN", NaN },
+  { "minusSign", minusSign },
+  { "monetarySeparator", monetarySeparator },
+  { "patternSeparator", patternSeparator },
+  { "percent", percent },
+  { "perMill", perMill },
+  { "zeroDigit", zeroDigit },
+};
+
+/*************************************************************************/
+
+/**
+  * This method returns the object array of key, value pairs containing
+  * the data for this bundle.
+  *
+  * @return The key, value information.
+  */
+public Object[][]
+getContents()
+{
+  return(contents);
+}
+
+} // class LocaleInformation_nl


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]