harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ge...@apache.org
Subject svn commit: r350181 [117/198] - in /incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core: ./ depends/ depends/files/ depends/jars/ depends/libs/ depends/libs/linux.IA32/ depends/libs/win.IA32/ depends/oss/ depends/oss/linux.IA32/ depends/oss/win....
Date Thu, 01 Dec 2005 06:04:00 GMT
Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/ConcurrentModificationException.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/ConcurrentModificationException.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/ConcurrentModificationException.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/ConcurrentModificationException.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,47 @@
+/* Copyright 1998, 2002 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util;
+
+
+/**
+ * This runtime exception is thrown when a Collection is modified and an
+ * existing iterator on the Collection is used to modify the Collection as well.
+ * 
+ * @see java.lang.RuntimeException
+ */
+public class ConcurrentModificationException extends RuntimeException {
+
+	static final long serialVersionUID = -3666751008965953603L;
+
+	/**
+	 * Constructs a new instance of this class with its walkback filled in.
+	 */
+	public ConcurrentModificationException() {
+		/*empty*/
+	}
+
+	/**
+	 * Constructs a new instance of this class with its walkback and message
+	 * filled in.
+	 * 
+	 * @param detailMessage
+	 *            String The detail message for the exception.
+	 */
+	public ConcurrentModificationException(String detailMessage) {
+		super(detailMessage);
+	}
+
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/Currency.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/Currency.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/Currency.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/Currency.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,184 @@
+/* Copyright 2004, 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util;
+
+
+import java.io.Serializable;
+
+/**
+ * This class represents a currency as identified in the ISO 4217 currency
+ * codes.
+ */
+public final class Currency implements Serializable {
+
+	private static final long serialVersionUID = -158308464356906721L;
+
+	private static Hashtable codesToCurrencies = new Hashtable();
+
+	private String currencyCode;
+
+	private static String currencyVars = "EURO, HK, PREEURO"; //$NON-NLS-1$
+
+	private transient int defaultFractionDigits;
+
+	/**
+	 * @param currencyCode
+	 */
+	private Currency(String currencyCode) {
+		this.currencyCode = currencyCode;
+	}
+
+	/**
+	 * Answers the currency instance for this currency code.
+	 * <p>
+	 * 
+	 * @param currencyCode
+	 *            java.lang.String
+	 * @return currency java.util.Currency
+	 * 
+	 * @throws java.lang.IllegalArgumentException
+	 *             if the currency code is not a supported ISO 4217 currency
+	 *             code
+	 */
+	public static Currency getInstance(String currencyCode) {
+		Currency currency = (Currency) codesToCurrencies.get(currencyCode);
+
+		if (currency == null) {
+			ResourceBundle bundle = Locale.getBundle(
+					"ISO4CurrenciesToDigits", Locale.getDefault()); //$NON-NLS-1$
+			currency = new Currency(currencyCode);
+
+			String defaultFractionDigits = null;
+			try {
+				defaultFractionDigits = bundle.getString(currencyCode);
+			} catch (MissingResourceException e) {
+				throw new IllegalArgumentException(com.ibm.oti.util.Msg
+						.getString("K0322", currencyCode)); //$NON-NLS-1$
+			}
+			currency.defaultFractionDigits = Integer
+					.parseInt(defaultFractionDigits);
+			codesToCurrencies.put(currencyCode, currency);
+		}
+
+		return currency;
+	}
+
+	/***************************************************************************
+	 * Answers the currency instance for this locale.
+	 * 
+	 * @param locale
+	 *            java.util.Locale
+	 * @return currency java.util.Currency
+	 * 
+	 * @throws java.lang.IllegalArgumentException
+	 *             if the locale's country is not a supported ISO 3166 Country
+	 */
+	public static Currency getInstance(Locale locale) {
+		String country = locale.getCountry();
+		String variant = locale.getVariant();
+		if (!variant.equals("") && currencyVars.indexOf(variant) > -1) //$NON-NLS-1$
+			country = country + "_" + variant; //$NON-NLS-1$
+
+		ResourceBundle bundle = Locale.getBundle(
+				"ISO4Currencies", Locale.getDefault()); //$NON-NLS-1$
+		String currencyCode = null;
+		try {
+			currencyCode = bundle.getString(country);
+		} catch (MissingResourceException e) {
+			throw new IllegalArgumentException(com.ibm.oti.util.Msg.getString(
+					"K0323", locale.toString())); //$NON-NLS-1$
+		}
+
+		if (currencyCode.equals("None")) //$NON-NLS-1$
+			return null;
+
+		return getInstance(currencyCode);
+	}
+
+	public String getCurrencyCode() {
+		return currencyCode;
+	}
+
+	public String getSymbol() {
+		return getSymbol(Locale.getDefault());
+	}
+
+	/***************************************************************************
+	 * Return the symbol for this currency in the given locale.
+	 * <p>
+	 * 
+	 * If the locale doesn't have any countries (e.g.
+	 * <code>Locale.JAPANESE, new Locale("en","")</code>), currencyCode is
+	 * returned.
+	 * <p>
+	 * First the locale bundle is checked, if the locale has the same currency,
+	 * the CurrencySymbol in this locale bundle is returned.
+	 * <p>
+	 * Then a currency bundle for this locale is searched.
+	 * <p>
+	 * If a currency bundle for this locale does not exist, or there is no
+	 * symbol for this currency in this bundle, than <code>currencyCode</code>
+	 * is returned.
+	 * <p>
+	 * 
+	 * @param locale
+	 *            java.lang.String locale
+	 * @return symbol java.lang.String the representation of this Currency's
+	 *         symbol in this locale
+	 */
+	public String getSymbol(Locale locale) {
+		if (locale.getCountry().equals("")) //$NON-NLS-1$
+			return currencyCode;
+
+		// check in the Locale bundle first, if the local has the same currency
+		ResourceBundle bundle = Locale.getBundle("Locale", locale); //$NON-NLS-1$
+		if (((String) bundle.getObject("IntCurrencySymbol")).equals(currencyCode)) //$NON-NLS-1$
+			return (String) bundle.getObject("CurrencySymbol"); //$NON-NLS-1$
+
+		// search for a Currency bundle
+		bundle = null;
+		try {
+			bundle = Locale.getBundle("Currency", locale); //$NON-NLS-1$
+		} catch (MissingResourceException e) {
+			return currencyCode;
+		}
+
+		// is the bundle found for a different country? (for instance the
+		// default locale's currency bundle)
+		if (!bundle.getLocale().getCountry().equals(locale.getCountry()))
+			return currencyCode;
+
+		// check if the currency bundle for this locale
+		// has an entry for this currency
+		String result = (String) bundle.handleGetObject(currencyCode);
+		if (result != null)
+			return result;
+		else
+			return currencyCode;
+	}
+
+	public int getDefaultFractionDigits() {
+		return defaultFractionDigits;
+	}
+
+	public String toString() {
+		return currencyCode;
+	}
+
+	private Object readResolve() {
+		return getInstance(currencyCode);
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/Date.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/Date.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/Date.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/Date.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,706 @@
+/* Copyright 1998, 2004 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util;
+
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.text.DateFormat;
+import java.text.DateFormatSymbols;
+import java.text.SimpleDateFormat;
+
+/**
+ * Date represents a specific moment in time, to the millisecond.
+ * 
+ * @see System#currentTimeMillis
+ * @see Calendar
+ * @see GregorianCalendar
+ * @see SimpleTimeZone
+ * @see TimeZone
+ */
+public class Date implements Serializable, Cloneable, Comparable {
+	
+	static final long serialVersionUID = 7523967970034938905L;
+
+	transient private long milliseconds;
+
+	// Used by parse()
+	private static int creationYear = new Date().getYear();
+
+	/**
+	 * Initializes this Date instance to the current date and time.
+	 * 
+	 */
+	public Date() {
+		this(System.currentTimeMillis());
+	}
+
+	/**
+	 * Constructs a new Date initialized to midnight in the default TimeZone on
+	 * the specified date.
+	 * 
+	 * @param year
+	 *            the year, 0 is 1900
+	 * @param month
+	 *            the month, 0 - 11
+	 * @param day
+	 *            the day of the month, 1 - 31
+	 * 
+	 * @deprecated use GregorianCalendar(int, int, int)
+	 */
+	public Date(int year, int month, int day) {
+		GregorianCalendar cal = new GregorianCalendar(false);
+		cal.set(1900 + year, month, day);
+		milliseconds = cal.getTimeInMillis();
+	}
+
+	/**
+	 * Constructs a new Date initialized to the specified date and time in the
+	 * default TimeZone.
+	 * 
+	 * @param year
+	 *            the year, 0 is 1900
+	 * @param month
+	 *            the month, 0 - 11
+	 * @param day
+	 *            the day of the month, 1 - 31
+	 * @param hour
+	 *            the hour of day, 0 - 23
+	 * @param minute
+	 *            the minute of the hour, 0 - 59
+	 * 
+	 * @deprecated use GregorianCalendar(int, int, int, int, int)
+	 */
+	public Date(int year, int month, int day, int hour, int minute) {
+		GregorianCalendar cal = new GregorianCalendar(false);
+		cal.set(1900 + year, month, day, hour, minute);
+		milliseconds = cal.getTimeInMillis();
+	}
+
+	/**
+	 * Constructs a new Date initialized to the specified date and time in the
+	 * default TimeZone.
+	 * 
+	 * @param year
+	 *            the year, 0 is 1900
+	 * @param month
+	 *            the month, 0 - 11
+	 * @param day
+	 *            the day of the month, 1 - 31
+	 * @param hour
+	 *            the hour of day, 0 - 23
+	 * @param minute
+	 *            the minute of the hour, 0 - 59
+	 * @param second
+	 *            the second of the minute, 0 - 59
+	 * 
+	 * @deprecated use GregorianCalendar(int, int, int, int, int, int)
+	 */
+	public Date(int year, int month, int day, int hour, int minute, int second) {
+		GregorianCalendar cal = new GregorianCalendar(false);
+		cal.set(1900 + year, month, day, hour, minute, second);
+		milliseconds = cal.getTimeInMillis();
+	}
+
+	/**
+	 * Initializes this Date instance using the specified millisecond value. The
+	 * value is the number of milliseconds since Jan. 1, 1970 GMT.
+	 * 
+	 * @param milliseconds
+	 *            the number of milliseconds since Jan. 1, 1970 GMT
+	 */
+	public Date(long milliseconds) {
+		this.setTime(milliseconds);
+	}
+
+	/**
+	 * Constructs a new Date initialized to the date and time parsed from the
+	 * specified String.
+	 * 
+	 * @param string
+	 *            the String to parse
+	 * 
+	 * @deprecated use DateFormat
+	 */
+	public Date(String string) {
+		milliseconds = parse(string);
+	}
+
+	/**
+	 * Answers if this Date is after the specified Date.
+	 * 
+	 * @param date
+	 *            a Date instance to compare
+	 * @return true if this Date is after the specified Date, false otherwise
+	 */
+	public boolean after(Date date) {
+		return milliseconds > date.milliseconds;
+	}
+
+	/**
+	 * Boolean indication of whether or not this <code>Date</code> occurs
+	 * earlier than the <code>Date</code> argument.
+	 * 
+	 * @param date
+	 *            a Date instance to compare
+	 * @return <code>true</code> if this <code>Date</code> occurs earlier
+	 *         than <code>date</code>, otherwise <code>false</code>
+	 */
+	public boolean before(Date date) {
+		return milliseconds < date.milliseconds;
+	}
+
+	/**
+	 * Answers a new Date with the same millisecond value as this Date.
+	 * 
+	 * @return a shallow copy of this Date
+	 * 
+	 * @see java.lang.Cloneable
+	 */
+	public Object clone() {
+		try {
+			return super.clone();
+		} catch (CloneNotSupportedException e) {
+			return null;
+		}
+	}
+
+	/**
+	 * Compare the receiver to the specified Object to determine the relative
+	 * ordering.
+	 * 
+	 * @param object
+	 *            an Object
+	 * @return an int < 0 if this Date is less than the specified Date, 0 if
+	 *         they are equal, and > 0 if this Date is greater
+	 * 
+	 * @exception ClassCastException
+	 *                when object is not a Date
+	 */
+	public int compareTo(Object object) {
+		return compareTo((Date) object);
+	}
+
+	/**
+	 * Compare the receiver to the specified Date to determine the relative
+	 * ordering.
+	 * 
+	 * @param date
+	 *            a Date
+	 * @return an int < 0 if this Date is less than the specified Date, 0 if
+	 *         they are equal, and > 0 if this Date is greater
+	 */
+	public int compareTo(Date date) {
+		if (milliseconds < date.milliseconds)
+			return -1;
+		if (milliseconds == date.milliseconds)
+			return 0;
+		return 1;
+	}
+
+	/**
+	 * Compares the specified object to this Date and answer if they are equal.
+	 * The object must be an instance of Date and have the same millisecond
+	 * value.
+	 * 
+	 * @param object
+	 *            the object to compare with this object
+	 * @return true if the specified object is equal to this Date, false
+	 *         otherwise
+	 * 
+	 * @see #hashCode
+	 */
+	public boolean equals(Object object) {
+		return (object == this) || (object instanceof Date)
+				&& (milliseconds == ((Date) object).milliseconds);
+	}
+
+	/**
+	 * Answers the gregorian calendar day of the month for this Date object.
+	 * 
+	 * @return the day of the month
+	 * 
+	 * @deprecated use Calendar.get(Calendar.DATE)
+	 */
+	public int getDate() {
+		return new GregorianCalendar(milliseconds).get(Calendar.DATE);
+	}
+
+	/**
+	 * Answers the gregorian calendar day of the week for this Date object.
+	 * 
+	 * @return the day of the week
+	 * 
+	 * @deprecated use Calendar.get(Calendar.DAY_OF_WEEK)
+	 */
+	public int getDay() {
+		return new GregorianCalendar(milliseconds).get(Calendar.DAY_OF_WEEK) - 1;
+	}
+
+	/**
+	 * Answers the gregorian calendar hour of the day for this Date object.
+	 * 
+	 * @return the hour of the day
+	 * 
+	 * @deprecated use Calendar.get(Calendar.HOUR_OF_DAY)
+	 */
+	public int getHours() {
+		return new GregorianCalendar(milliseconds).get(Calendar.HOUR_OF_DAY);
+	}
+
+	/**
+	 * Answers the gregorian calendar minute of the hour for this Date object.
+	 * 
+	 * @return the minutes
+	 * 
+	 * @deprecated use Calendar.get(Calendar.MINUTE)
+	 */
+	public int getMinutes() {
+		return new GregorianCalendar(milliseconds).get(Calendar.MINUTE);
+	}
+
+	/**
+	 * Answers the gregorian calendar month for this Date object.
+	 * 
+	 * @return the month
+	 * 
+	 * @deprecated use Calendar.get(Calendar.MONTH)
+	 */
+	public int getMonth() {
+		return new GregorianCalendar(milliseconds).get(Calendar.MONTH);
+	}
+
+	/**
+	 * Answers the gregorian calendar second of the minute for this Date object.
+	 * 
+	 * @return the seconds
+	 * 
+	 * @deprecated use Calendar.get(Calendar.SECOND)
+	 */
+	public int getSeconds() {
+		return new GregorianCalendar(milliseconds).get(Calendar.SECOND);
+	}
+
+	/**
+	 * Answers this Date as a millisecond value. The value is the number of
+	 * milliseconds since Jan. 1, 1970 GMT.
+	 * 
+	 * @return the number of milliseconds since Jan. 1, 1970 GMT.
+	 */
+	public long getTime() {
+		return milliseconds;
+	}
+
+	/**
+	 * Answers the timezone offset in minutes of the default TimeZone.
+	 * 
+	 * @return the timezone offset in minutes of the default TimeZone
+	 * 
+	 * @deprecated use
+	 *             <code>(Calendar.get(Calendar.ZONE_OFFSET) + Calendar.get(Calendar.DST_OFFSET)) / 60000</code>
+	 */
+	public int getTimezoneOffset() {
+		GregorianCalendar cal = new GregorianCalendar(milliseconds);
+		return -(cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET)) / 60000;
+	}
+
+	/**
+	 * Answers the gregorian calendar year since 1900 for this Date object.
+	 * 
+	 * @return the year - 1900
+	 * 
+	 * @deprecated use Calendar.get(Calendar.YEAR) - 1900
+	 */
+	public int getYear() {
+		return new GregorianCalendar(milliseconds).get(Calendar.YEAR) - 1900;
+	}
+
+	/**
+	 * Answers an integer hash code for the receiver. Objects which are equal
+	 * answer the same value for this method.
+	 * 
+	 * @return the receiver's hash
+	 * 
+	 * @see #equals
+	 */
+	public int hashCode() {
+		return (int) (milliseconds >>> 32) ^ (int) milliseconds;
+	}
+
+	private static int parse(String string, String[] array) {
+		for (int i = 0, alength = array.length, slength = string.length(); i < alength; i++)
+			if (string.regionMatches(true, 0, array[i], 0, slength))
+				return i;
+		return -1;
+	}
+
+	/**
+	 * Answers the millisecond value of the date and time parsed from the
+	 * specified String. Many date/time formats are recognized, including IETF
+	 * standard syntax, i.e. Tue, 22 Jun 1999 12:16:00 GMT-0500
+	 * 
+	 * @param string
+	 *            the String to parse
+	 * @return the millisecond value parsed from the String
+	 * 
+	 * @deprecated use DateFormat
+	 */
+	public static long parse(String string) {
+		char sign = 0;
+		int commentLevel = 0;
+		int offset = 0, length = string.length(), state = 0;
+		int year = -1, month = -1, date = -1;
+		int hour = -1, minute = -1, second = -1, zoneOffset = 0;
+		boolean zone = false;
+		final int PAD = 0, LETTERS = 1, NUMBERS = 2;
+		StringBuffer buffer = new StringBuffer();
+
+		while (offset <= length) {
+			char next = offset < length ? string.charAt(offset) : '\r';
+			offset++;
+
+			if (next == '(')
+				commentLevel++;
+			if (commentLevel > 0) {
+				if (next == ')')
+					commentLevel--;
+				if (commentLevel == 0)
+					next = ' ';
+				else
+					continue;
+			}
+
+			int nextState = PAD;
+			if ('a' <= next && next <= 'z' || 'A' <= next && next <= 'Z')
+				nextState = LETTERS;
+			else if ('0' <= next && next <= '9')
+				nextState = NUMBERS;
+			else if (!Character.isSpace(next) && ",+-:/".indexOf(next) == -1) //$NON-NLS-1$
+				throw new IllegalArgumentException();
+
+			if (state == NUMBERS && nextState != NUMBERS) {
+				int digit = Integer.parseInt(buffer.toString());
+				buffer.setLength(0);
+				if (sign == '+' || sign == '-') {
+					if (year != -1 && zoneOffset == 0) {
+						zone = true;
+						zoneOffset = sign == '-' ? -digit : digit;
+					} else
+						throw new IllegalArgumentException();
+				} else if (digit >= 70) {
+					if (year == -1
+							&& (Character.isSpace(next) || next == ','
+									|| next == '/' || next == '\r'))
+						year = digit;
+					else
+						throw new IllegalArgumentException();
+				} else if (next == ':') {
+					if (hour == -1)
+						hour = digit;
+					else if (minute == -1)
+						minute = digit;
+					else
+						throw new IllegalArgumentException();
+				} else if (next == '/') {
+					if (month == -1)
+						month = digit - 1;
+					else if (date == -1)
+						date = digit;
+					else
+						throw new IllegalArgumentException();
+				} else if (Character.isSpace(next) || next == ','
+						|| next == '-' || next == '\r') {
+					if (hour != -1 && minute == -1)
+						minute = digit;
+					else if (minute != -1 && second == -1)
+						second = digit;
+					else if (date == -1)
+						date = digit;
+					else if (year == -1)
+						year = digit;
+					else
+						throw new IllegalArgumentException();
+				} else if (year == -1 && month != -1 && date != -1)
+					year = digit;
+				else
+					throw new IllegalArgumentException();
+			} else if (state == LETTERS && nextState != LETTERS) {
+				String text = buffer.toString().toUpperCase();
+				buffer.setLength(0);
+				if (text.length() == 1)
+					throw new IllegalArgumentException();
+				if (text.equals("AM")) { //$NON-NLS-1$
+					if (hour == 12)
+						hour = 0;
+					else if (hour < 1 || hour > 12)
+						throw new IllegalArgumentException();
+				} else if (text.equals("PM")) { //$NON-NLS-1$
+					if (hour == 12)
+						hour = 0;
+					else if (hour < 1 || hour > 12)
+						throw new IllegalArgumentException();
+					hour += 12;
+				} else {
+					DateFormatSymbols symbols = new DateFormatSymbols(Locale.US);
+					String[] weekdays = symbols.getWeekdays(), months = symbols
+							.getMonths();
+					int value;
+					if (parse(text, weekdays) != -1) {/*empty*/
+					} else if (month == -1
+							&& (month = parse(text, months)) != -1) {/*empty*/
+					} else if (text.equals("GMT") || text.equals("UT") //$NON-NLS-1$ //$NON-NLS-2$
+							|| text.equals("UTC")) { //$NON-NLS-1$
+						zone = true;
+						zoneOffset = 0;
+					} else if ((value = zone(text)) != 0) {
+						zone = true;
+						zoneOffset = value;
+					} else
+						throw new IllegalArgumentException();
+				}
+			}
+
+			if (next == '+' || (year != -1 && next == '-'))
+				sign = next;
+			else if (!Character.isSpace(next) && next != ','
+					&& nextState != NUMBERS)
+				sign = 0;
+
+			if (nextState == LETTERS || nextState == NUMBERS)
+				buffer.append(next);
+			state = nextState;
+		}
+
+		if (year != -1 && month != -1 && date != -1) {
+			if (hour == -1)
+				hour = 0;
+			if (minute == -1)
+				minute = 0;
+			if (second == -1)
+				second = 0;
+			if (year < (creationYear - 80))
+				year += 2000;
+			else if (year < 100)
+				year += 1900;
+			if (zone) {
+				if (zoneOffset >= 24 || zoneOffset <= -24) {
+					hour -= zoneOffset / 100;
+					minute -= zoneOffset % 100;
+				} else
+					hour -= zoneOffset;
+				return UTC(year - 1900, month, date, hour, minute, second);
+			} else
+				return new Date(year - 1900, month, date, hour, minute, second)
+						.getTime();
+		}
+		throw new IllegalArgumentException();
+	}
+
+	/**
+	 * Sets the gregorian calendar day of the month for this Date object.
+	 * 
+	 * @param day
+	 *            the day of the month
+	 * 
+	 * @deprecated use Calendar.set(Calendar.DATE, day)
+	 */
+	public void setDate(int day) {
+		GregorianCalendar cal = new GregorianCalendar(milliseconds);
+		cal.set(Calendar.DATE, day);
+		milliseconds = cal.getTimeInMillis();
+	}
+
+	/**
+	 * Sets the gregorian calendar hour of the day for this Date object.
+	 * 
+	 * @param hour
+	 *            the hour of the day
+	 * 
+	 * @deprecated use Calendar.set(Calendar.HOUR_OF_DAY, hour)
+	 */
+	public void setHours(int hour) {
+		GregorianCalendar cal = new GregorianCalendar(milliseconds);
+		cal.set(Calendar.HOUR_OF_DAY, hour);
+		milliseconds = cal.getTimeInMillis();
+	}
+
+	/**
+	 * Sets the gregorian calendar minute of the hour for this Date object.
+	 * 
+	 * @param minute
+	 *            the minutes
+	 * 
+	 * @deprecated use Calendar.set(Calendar.MINUTE, minute)
+	 */
+	public void setMinutes(int minute) {
+		GregorianCalendar cal = new GregorianCalendar(milliseconds);
+		cal.set(Calendar.MINUTE, minute);
+		milliseconds = cal.getTimeInMillis();
+	}
+
+	/**
+	 * Sets the gregorian calendar month for this Date object.
+	 * 
+	 * @param month
+	 *            the month
+	 * 
+	 * @deprecated use Calendar.set(Calendar.MONTH, month)
+	 */
+	public void setMonth(int month) {
+		GregorianCalendar cal = new GregorianCalendar(milliseconds);
+		cal.set(Calendar.MONTH, month);
+		milliseconds = cal.getTimeInMillis();
+	}
+
+	/**
+	 * Sets the gregorian calendar second of the minute for this Date object.
+	 * 
+	 * @param second
+	 *            the seconds
+	 * 
+	 * @deprecated use Calendar.set(Calendar.SECOND, second)
+	 */
+	public void setSeconds(int second) {
+		GregorianCalendar cal = new GregorianCalendar(milliseconds);
+		cal.set(Calendar.SECOND, second);
+		milliseconds = cal.getTimeInMillis();
+	}
+
+	/**
+	 * Sets this Date to the specified millisecond value. The value is the
+	 * number of milliseconds since Jan. 1, 1970 GMT.
+	 * 
+	 * @param milliseconds
+	 *            the number of milliseconds since Jan. 1, 1970 GMT.
+	 */
+	public void setTime(long milliseconds) {
+		this.milliseconds = milliseconds;
+	}
+
+	/**
+	 * Sets the gregorian calendar year since 1900 for this Date object.
+	 * 
+	 * @param year
+	 *            the year since 1900
+	 * 
+	 * @deprecated use Calendar.set(Calendar.YEAR, year + 1900)
+	 */
+	public void setYear(int year) {
+		GregorianCalendar cal = new GregorianCalendar(milliseconds);
+		cal.set(Calendar.YEAR, year + 1900);
+		milliseconds = cal.getTimeInMillis();
+	}
+
+	/**
+	 * Answers the string representation of this Date in GMT in the format: 22
+	 * Jun 1999 13:02:00 GMT
+	 * 
+	 * @return the string representation of this Date in GMT
+	 * 
+	 * @deprecated use DateFormat
+	 */
+	public String toGMTString() {
+		SimpleDateFormat format = new SimpleDateFormat(
+				"d MMM yyyy HH:mm:ss 'GMT'", Locale.US); //$NON-NLS-1$
+		format.setTimeZone(TimeZone.getTimeZone("GMT")); //$NON-NLS-1$
+		return format.format(this);
+	}
+
+	/**
+	 * Answers the string representation of this Date for the current Locale.
+	 * 
+	 * @return the string representation of this Date for the current Locale
+	 * 
+	 * @deprecated use DateFormat
+	 */
+	public String toLocaleString() {
+		return DateFormat.getDateTimeInstance().format(this);
+	}
+
+	/**
+	 * Answers the string representation of this Date in the format: Tue Jun 22
+	 * 13:07:00 GMT 1999
+	 * 
+	 * @return the string representation of this Date
+	 */
+	public String toString() {
+		return new SimpleDateFormat("E MMM dd HH:mm:ss z yyyy", Locale.US) //$NON-NLS-1$
+				.format(this);
+	}
+
+	/**
+	 * Answers the millisecond value of the specified date and time in GMT.
+	 * 
+	 * @param year
+	 *            the year, 0 is 1900
+	 * @param month
+	 *            the month, 0 - 11
+	 * @param day
+	 *            the day of the month, 1 - 31
+	 * @param hour
+	 *            the hour of day, 0 - 23
+	 * @param minute
+	 *            the minute of the hour, 0 - 59
+	 * @param second
+	 *            the second of the minute, 0 - 59
+	 * @return long
+	 * 
+	 * @deprecated use: <code>
+	 *	Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
+	 *	cal.set(year + 1900, month, day, hour, minute, second);
+	 * 	cal.getTime().getTime();</code>
+	 */
+	public static long UTC(int year, int month, int day, int hour, int minute,
+			int second) {
+		GregorianCalendar cal = new GregorianCalendar(false);
+		cal.setTimeZone(TimeZone.getTimeZone("GMT")); //$NON-NLS-1$
+		cal.set(1900 + year, month, day, hour, minute, second);
+		return cal.getTimeInMillis();
+	}
+
+	private static int zone(String text) {
+		if (text.equals("EST")) //$NON-NLS-1$
+			return -5;
+		if (text.equals("EDT")) //$NON-NLS-1$
+			return -4;
+		if (text.equals("CST")) //$NON-NLS-1$
+			return -6;
+		if (text.equals("CDT")) //$NON-NLS-1$
+			return -5;
+		if (text.equals("MST")) //$NON-NLS-1$
+			return -7;
+		if (text.equals("MDT")) //$NON-NLS-1$
+			return -6;
+		if (text.equals("PST")) //$NON-NLS-1$
+			return -8;
+		if (text.equals("PDT")) //$NON-NLS-1$
+			return -7;
+		return 0;
+	}
+
+	private void writeObject(ObjectOutputStream stream) throws IOException {
+		stream.defaultWriteObject();
+		stream.writeLong(getTime());
+	}
+
+	private void readObject(ObjectInputStream stream) throws IOException,
+			ClassNotFoundException {
+		stream.defaultReadObject();
+		setTime(stream.readLong());
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/Dictionary.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/Dictionary.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/Dictionary.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/Dictionary.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,120 @@
+/* Copyright 1998, 2002 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util;
+
+
+/**
+ * Dictionary is a abstract class which is the superclass of all classes that
+ * associate keys with values, such as Hashtable.
+ * 
+ * @see Hashtable
+ */
+public abstract class Dictionary {
+	/**
+	 * Constructs a new instance of this class.
+	 * 
+	 */
+	public Dictionary() {
+		super();
+	}
+
+	/**
+	 * Answers an Enumeration on the elements of this Dictionary.
+	 * 
+	 * @return an Enumeration of the values of this Dictionary
+	 * 
+	 * @see #keys
+	 * @see #size
+	 * @see Enumeration
+	 */
+	abstract public Enumeration elements();
+
+	/**
+	 * Answers the value associated with <code>key</code>.
+	 * 
+	 * @param key
+	 *            the key of the value returned
+	 * @return the value associated with <code>key</code> or <code>null</code>
+	 *         if the specified key does not exist
+	 * 
+	 * @see #put
+	 */
+	abstract public Object get(Object key);
+
+	/**
+	 * Answers if this Dictionary has no key/value pairs, a size of zero.
+	 * 
+	 * @return true if this Dictionary has no key/value pairs, false otherwise
+	 * 
+	 * @see #size
+	 */
+	abstract public boolean isEmpty();
+
+	/**
+	 * Answers an Enumeration on the keys of this Dictionary.
+	 * 
+	 * @return an Enumeration of the keys of this Dictionary
+	 * 
+	 * @see #elements
+	 * @see #size
+	 * @see Enumeration
+	 */
+	abstract public Enumeration keys();
+
+	/**
+	 * Associate <code>key</code> with <code>value</code> in this
+	 * <code>Dictionary</code>. If <code>key</code> exists in the
+	 * <code>Dictionary</code> prior to this call being made, the old value is
+	 * replaced.
+	 * 
+	 * @param key
+	 *            the key to add
+	 * @param value
+	 *            the value to add
+	 * @return the old value previously associated with <code>key</code> or
+	 *         <code>null</code> if <code>key</code> is new to the
+	 *         <code>Dictionary</code>.
+	 * 
+	 * @see #elements
+	 * @see #get
+	 * @see #keys
+	 */
+	abstract public Object put(Object key, Object value);
+
+	/**
+	 * Remove the key/value pair with the specified <code>key</code> from this
+	 * <code>Dictionary</code>.
+	 * 
+	 * @param key
+	 *            the key to remove
+	 * @return the associated value or else <code>null</code> if
+	 *         <code>key</code> is not known to this <code>Dictionary</code>
+	 * 
+	 * @see #get
+	 * @see #put
+	 */
+	abstract public Object remove(Object key);
+
+	/**
+	 * Answers the number of key/value pairs in this Dictionary.
+	 * 
+	 * @return the number of key/value pairs in this Dictionary
+	 * 
+	 * @see #elements
+	 * @see #keys
+	 */
+	abstract public int size();
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/EmptyStackException.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/EmptyStackException.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/EmptyStackException.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/EmptyStackException.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,33 @@
+/* Copyright 1998, 2002 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util;
+
+
+/**
+ * Runtime exception which is thrown when pop/peek method of stack is executed
+ * on a stack which is empty
+ */
+public class EmptyStackException extends RuntimeException {
+
+	static final long serialVersionUID = 5084686378493302095L;
+
+	/**
+	 * Constructs a new instance of this class with its walkback filled in.
+	 */
+	public EmptyStackException() {
+		super();
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/Enumeration.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/Enumeration.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/Enumeration.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/Enumeration.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,47 @@
+/* Copyright 1998, 2002 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util;
+
+
+/**
+ * An Enumeration is used to sequence over a collection of objects.
+ * 
+ * @see Hashtable
+ * @see Properties
+ * @see Vector
+ */
+public interface Enumeration {
+	/**
+	 * Answers if this Enumeration has more elements.
+	 * 
+	 * @return true if there are more elements, false otherwise
+	 * 
+	 * @see #nextElement
+	 */
+	public boolean hasMoreElements();
+
+	/**
+	 * Answers the next element in this Enumeration.
+	 * 
+	 * @return the next element in this Enumeration
+	 * 
+	 * @exception NoSuchElementException
+	 *                when there are no more elements
+	 * 
+	 * @see #hasMoreElements
+	 */
+	public Object nextElement();
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/EventListener.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/EventListener.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/EventListener.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/EventListener.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,26 @@
+/* Copyright 1998, 2002 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util;
+
+
+/**
+ * EventListener is the superclass of all event listener interfaces.
+ *
+ * @see			EventObject
+ */
+public interface EventListener {
+	/*empty*/
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/EventListenerProxy.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/EventListenerProxy.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/EventListenerProxy.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/EventListenerProxy.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,38 @@
+/* Copyright 2004, 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util;
+
+
+/**
+ * This abstract class provides a simple wrapper to types of EventListener.
+ * 
+ */
+public abstract class EventListenerProxy implements EventListener {
+
+	private final EventListener listener;
+
+	/**
+	 * @param listener
+	 */
+	public EventListenerProxy(EventListener listener) {
+		super();
+		this.listener = listener;
+	}
+
+	public EventListener getListener() {
+		return listener;
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/EventObject.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/EventObject.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/EventObject.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/EventObject.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,66 @@
+/* Copyright 1998, 2002 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util;
+
+
+import java.io.Serializable;
+
+/**
+ * EventObjects represent events. Typically applications subclass this class to
+ * add event specific information.
+ * 
+ * @see EventListener
+ */
+public class EventObject implements Serializable {
+	
+	static final long serialVersionUID = 5516075349620653480L;
+
+	/**
+	 * The event source.
+	 */
+	protected transient Object source;
+
+	/**
+	 * Constructs a new instance of this class.
+	 * 
+	 * @param source
+	 *            the object which fired the event
+	 */
+	public EventObject(Object source) {
+		if (source != null)
+			this.source = source;
+		else
+			throw new IllegalArgumentException();
+	}
+
+	/**
+	 * Answers the event source.
+	 * 
+	 * @return the object which fired the event
+	 */
+	public Object getSource() {
+		return source;
+	}
+
+	/**
+	 * Answers the string representation of this EventObject.
+	 * 
+	 * @return the string representation of this EventObject
+	 */
+	public String toString() {
+		return getClass().getName() + "[source=" + String.valueOf(source) + ']'; //$NON-NLS-1$
+	}
+}

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/GregorianCalendar.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/GregorianCalendar.java?rev=350181&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/GregorianCalendar.java (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/ibm_core/java-src/luni/src/java/util/GregorianCalendar.java Wed Nov 30 21:29:27 2005
@@ -0,0 +1,1121 @@
+/* Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+/**
+ * GregorianCalendar provides the conversion between Dates and integer calendar
+ * fields, such as the month, year or minute, for the gregorian calendar. See
+ * Calendar for the defined fields.
+ * 
+ * @see Calendar
+ * @see TimeZone
+ * @see SimpleTimeZone
+ */
+public class GregorianCalendar extends Calendar {
+
+	static final long serialVersionUID = -8125100834729963327L;
+
+	public final static int BC = 0, AD = 1;
+
+	private long gregorianCutover = -12219292800000l;
+
+	transient private int changeYear = 1582;
+
+	transient private int julianSkew = ((changeYear - 2000) / 400)
+			+ julianError() - ((changeYear - 2000) / 100);
+
+	static byte[] DaysInMonth = new byte[] { 31, 28, 31, 30, 31, 30, 31, 31,
+			30, 31, 30, 31 };
+
+	private static int[] DaysInYear = new int[] { 0, 31, 59, 90, 120, 151, 181,
+			212, 243, 273, 304, 334 };
+
+	private static int[] maximums = new int[] { 1, 292278994, 11, 53, 6, 31,
+			366, 7, 6, 1, 11, 23, 59, 59, 999, 43200000, 3600000 };
+
+	private static int[] minimums = new int[] { 0, 1, 0, 1, 0, 1, 1, 1, -1, 0,
+			0, 0, 0, 0, 0, -43200000, 0 };
+
+	private static int[] leastMaximums = new int[] { 1, 292269054, 11, 52, 4,
+			28, 365, 7, 4, 1, 11, 23, 59, 59, 999, 43200000, 3600000 };
+
+	private boolean isCached = false;
+
+	private int cachedFields[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+
+	private long nextMidnightMillis = 0L;
+
+	private long lastMidnightMillis = 0L;
+
+	private boolean dstOffsetForwardAdjustment = false;
+
+	private boolean dstOffsetBackwardAdjustment = false;
+
+	/**
+	 * Constructs a new GregorianCalendar initialized to the current date and
+	 * time.
+	 */
+	public GregorianCalendar() {
+		this(TimeZone.getDefault(), Locale.getDefault());
+	}
+
+	/**
+	 * Constructs a new GregorianCalendar initialized to midnight in the default
+	 * time zone on the specified date.
+	 * 
+	 * @param year
+	 *            the year
+	 * @param month
+	 *            the month
+	 * @param day
+	 *            the day of the month
+	 */
+	public GregorianCalendar(int year, int month, int day) {
+		super(TimeZone.getDefault(), Locale.getDefault());
+		set(year, month, day);
+	}
+
+	/**
+	 * Constructs a new GregorianCalendar initialized to the specified date and
+	 * time.
+	 * 
+	 * @param year
+	 *            the year
+	 * @param month
+	 *            the month
+	 * @param day
+	 *            the day of the month
+	 * @param hour
+	 *            the hour
+	 * @param minute
+	 *            the minute
+	 */
+	public GregorianCalendar(int year, int month, int day, int hour, int minute) {
+		super(TimeZone.getDefault(), Locale.getDefault());
+		set(year, month, day, hour, minute);
+	}
+
+	/**
+	 * Constructs a new GregorianCalendar initialized to the specified date and
+	 * time.
+	 * 
+	 * @param year
+	 *            the year
+	 * @param month
+	 *            the month
+	 * @param day
+	 *            the day of the month
+	 * @param hour
+	 *            the hour
+	 * @param minute
+	 *            the minute
+	 * @param second
+	 *            the second
+	 */
+	public GregorianCalendar(int year, int month, int day, int hour,
+			int minute, int second) {
+		super(TimeZone.getDefault(), Locale.getDefault());
+		set(year, month, day, hour, minute, second);
+	}
+
+	GregorianCalendar(long milliseconds) {
+		this(false);
+		setTimeInMillis(milliseconds);
+	}
+
+	/**
+	 * Constructs a new GregorianCalendar initialized to the current date and
+	 * time and using the specified Locale.
+	 * 
+	 * @param locale
+	 *            the Locale
+	 */
+	public GregorianCalendar(Locale locale) {
+		this(TimeZone.getDefault(), locale);
+	}
+
+	/**
+	 * Constructs a new GregorianCalendar initialized to the current date and
+	 * time and using the specified TimeZone.
+	 * 
+	 * @param timezone
+	 *            the TimeZone
+	 */
+	public GregorianCalendar(TimeZone timezone) {
+		this(timezone, Locale.getDefault());
+	}
+
+	/**
+	 * Constructs a new GregorianCalendar initialized to the current date and
+	 * time and using the specified TimeZone and Locale.
+	 * 
+	 * @param timezone
+	 *            the TimeZone
+	 * @param locale
+	 *            the Locale
+	 */
+	public GregorianCalendar(TimeZone timezone, Locale locale) {
+		super(timezone, locale);
+		setTimeInMillis(System.currentTimeMillis());
+	}
+
+	GregorianCalendar(boolean ignored) {
+		super(TimeZone.getDefault());
+		setFirstDayOfWeek(SUNDAY);
+		setMinimalDaysInFirstWeek(1);
+	}
+
+	/**
+	 * Adds the specified amount to a Calendar field.
+	 * 
+	 * @param field
+	 *            the Calendar field to modify
+	 * @param value
+	 *            the amount to add to the field
+	 * 
+	 * @exception IllegalArgumentException
+	 *                when the specified field is DST_OFFSET or ZONE_OFFSET.
+	 */
+	public void add(int field, int value) {
+		if (value == 0)
+			return;
+		if (field < 0 || field >= ZONE_OFFSET)
+			throw new IllegalArgumentException();
+
+		isCached = false;
+
+		if (field == ERA) {
+			complete();
+			if (fields[ERA] == AD) {
+				if (value >= 0)
+					return;
+				set(ERA, BC);
+			} else {
+				if (value <= 0)
+					return;
+				set(ERA, AD);
+			}
+			complete();
+			return;
+		}
+
+		if (field == YEAR || field == MONTH) {
+			complete();
+			if (field == MONTH) {
+				int month = fields[MONTH] + value;
+				if (month < 0) {
+					value = (month - 11) / 12;
+					month = 12 + (month % 12);
+				} else
+					value = month / 12;
+				set(MONTH, month % 12);
+			}
+			set(YEAR, fields[YEAR] + value);
+			int days = daysInMonth(isLeapYear(fields[YEAR]), fields[MONTH]);
+			if (fields[DATE] > days)
+				set(DATE, days);
+			complete();
+			return;
+		}
+
+		long multiplier = 0;
+		getTimeInMillis(); // Update the time
+		switch (field) {
+		case MILLISECOND:
+			time += value;
+			break;
+		case SECOND:
+			time += value * 1000L;
+			break;
+		case MINUTE:
+			time += value * 60000L;
+			break;
+		case HOUR:
+		case HOUR_OF_DAY:
+			time += value * 3600000L;
+			break;
+		case AM_PM:
+			multiplier = 43200000L;
+			break;
+		case DATE:
+		case DAY_OF_YEAR:
+		case DAY_OF_WEEK:
+			multiplier = 86400000L;
+			break;
+		case WEEK_OF_YEAR:
+		case WEEK_OF_MONTH:
+		case DAY_OF_WEEK_IN_MONTH:
+			multiplier = 604800000L;
+			break;
+		}
+		if (multiplier > 0) {
+			int zoneOffset = getTimeZone().getRawOffset();
+			int offset = getOffset(time + zoneOffset);
+			time += value * multiplier;
+			int newOffset = getOffset(time + zoneOffset);
+			// Adjust for moving over a DST boundary
+			if (newOffset != offset)
+				time += offset - newOffset;
+		}
+		areFieldsSet = false;
+		complete();
+	}
+
+	private final void fullFieldsCalc(long timeVal, int millis, int zoneOffset) {
+		long days = timeVal / 86400000;
+
+		if (millis < 0) {
+			millis += 86400000;
+			days--;
+		}
+		// Cannot add ZONE_OFFSET to time as it might overflow
+		millis += zoneOffset;
+		if (millis < 0) {
+			millis += 86400000;
+			days--;
+		} else if (millis >= 86400000) {
+			millis -= 86400000;
+			days++;
+		}
+
+		int dayOfYear = computeYearAndDay(days, timeVal + zoneOffset);
+		fields[DAY_OF_YEAR] = dayOfYear;
+		int month = dayOfYear / 32;
+		boolean leapYear = isLeapYear(fields[YEAR]);
+		int date = dayOfYear - daysInYear(leapYear, month);
+		if (date > daysInMonth(leapYear, month)) {
+			date -= daysInMonth(leapYear, month);
+			month++;
+		}
+		fields[DAY_OF_WEEK] = mod7(days - 3) + 1;
+		int dstOffset = fields[YEAR] <= 0 ? 0 : getTimeZone().getOffset(AD,
+				fields[YEAR], month, date, fields[DAY_OF_WEEK], millis);
+		if (fields[YEAR] > 0)
+			dstOffset -= zoneOffset;
+		fields[DST_OFFSET] = dstOffset;
+		if (dstOffset != 0) {
+			long oldDays = days;
+			millis += dstOffset;
+			if (millis < 0) {
+				millis += 86400000;
+				days--;
+			} else if (millis >= 86400000) {
+				millis -= 86400000;
+				days++;
+			}
+			if (oldDays != days) {
+				dayOfYear = computeYearAndDay(days, timeVal - zoneOffset
+						+ dstOffset);
+				fields[DAY_OF_YEAR] = dayOfYear;
+				month = dayOfYear / 32;
+				leapYear = isLeapYear(fields[YEAR]);
+				date = dayOfYear - daysInYear(leapYear, month);
+				if (date > daysInMonth(leapYear, month)) {
+					date -= daysInMonth(leapYear, month);
+					month++;
+				}
+				fields[DAY_OF_WEEK] = mod7(days - 3) + 1;
+			}
+		}
+
+		fields[MILLISECOND] = (millis % 1000);
+		millis /= 1000;
+		fields[SECOND] = (millis % 60);
+		millis /= 60;
+		fields[MINUTE] = (millis % 60);
+		millis /= 60;
+		fields[HOUR_OF_DAY] = (millis % 24);
+		millis /= 24;
+		fields[AM_PM] = fields[HOUR_OF_DAY] > 11 ? 1 : 0;
+		fields[HOUR] = fields[HOUR_OF_DAY] % 12;
+
+		if (fields[YEAR] <= 0) {
+			fields[ERA] = BC;
+			fields[YEAR] = -fields[YEAR] + 1;
+		} else
+			fields[ERA] = AD;
+		fields[MONTH] = month;
+		fields[DATE] = date;
+		fields[DAY_OF_WEEK_IN_MONTH] = (date - 1) / 7 + 1;
+		fields[WEEK_OF_MONTH] = (date - 1 + mod7(days - date - 2
+				- (getFirstDayOfWeek() - 1))) / 7 + 1;
+		int daysFromStart = mod7(days - 3 - (fields[DAY_OF_YEAR] - 1)
+				- (getFirstDayOfWeek() - 1));
+		int week = (fields[DAY_OF_YEAR] - 1 + daysFromStart) / 7
+				+ (7 - daysFromStart >= getMinimalDaysInFirstWeek() ? 1 : 0);
+		if (week == 0) {
+			fields[WEEK_OF_YEAR] = 7 - mod7(daysFromStart
+					- (isLeapYear(fields[YEAR] - 1) ? 2 : 1)) >= getMinimalDaysInFirstWeek() ? 53
+					: 52;
+		} else if (fields[DAY_OF_YEAR] >= (leapYear ? 367 : 366)
+				- mod7(daysFromStart + (leapYear ? 2 : 1))) {
+			fields[WEEK_OF_YEAR] = 7 - mod7(daysFromStart + (leapYear ? 2 : 1)) >= getMinimalDaysInFirstWeek() ? 1
+					: week;
+		} else {
+			fields[WEEK_OF_YEAR] = week;
+		}
+	}
+
+	private final void cachedFieldsCheckAndGet(long timeVal,
+			long newTimeMillis, long newTimeMillisAdjusted, int millis,
+			int zoneOffset) {
+		int dstOffset = fields[DST_OFFSET];
+		if (!isCached
+				|| newTimeMillis >= nextMidnightMillis
+				|| newTimeMillis <= lastMidnightMillis
+				|| cachedFields[4] != zoneOffset
+				|| (dstOffset == 0 && (newTimeMillisAdjusted >= nextMidnightMillis))
+				|| (dstOffset != 0 && (newTimeMillisAdjusted <= lastMidnightMillis))) {
+			fullFieldsCalc(timeVal, millis, zoneOffset);
+			isCached = false;
+		} else {
+			fields[YEAR] = cachedFields[0];
+			fields[MONTH] = cachedFields[1];
+			fields[DATE] = cachedFields[2];
+			fields[DAY_OF_WEEK] = cachedFields[3];
+			fields[ERA] = cachedFields[5];
+			fields[WEEK_OF_YEAR] = cachedFields[6];
+			fields[WEEK_OF_MONTH] = cachedFields[7];
+			fields[DAY_OF_YEAR] = cachedFields[8];
+			fields[DAY_OF_WEEK_IN_MONTH] = cachedFields[9];
+		}
+	}
+
+	/**
+	 * Computes the Calendar fields from the time.
+	 */
+	protected void computeFields() {
+		int zoneOffset = getTimeZone().getRawOffset();
+
+		fields[ZONE_OFFSET] = zoneOffset;
+
+		int millis = (int) (time % 86400000);
+		int savedMillis = millis;
+		int dstOffset = fields[DST_OFFSET];
+		// compute without a change in daylight saving time
+		int offset = zoneOffset + dstOffset;
+		long newTime = time + offset;
+
+		if (time > 0L && newTime < 0L && offset > 0)
+			newTime = 0x7fffffffffffffffL;
+		else if (time < 0L && newTime > 0L && offset < 0)
+			newTime = 0x8000000000000000L;
+
+		if (isCached) {
+			if (millis < 0) {
+				millis += 86400000;
+			}
+
+			// Cannot add ZONE_OFFSET to time as it might overflow
+			millis += zoneOffset;
+			millis += dstOffset;
+
+			if (millis < 0) {
+				millis += 86400000;
+			} else if (millis >= 86400000) {
+				millis -= 86400000;
+			}
+
+			fields[MILLISECOND] = (millis % 1000);
+			millis /= 1000;
+			fields[SECOND] = (millis % 60);
+			millis /= 60;
+			fields[MINUTE] = (millis % 60);
+			millis /= 60;
+			fields[HOUR_OF_DAY] = (millis % 24);
+			millis /= 24;
+			fields[AM_PM] = fields[HOUR_OF_DAY] > 11 ? 1 : 0;
+			fields[HOUR] = fields[HOUR_OF_DAY] % 12;
+
+			long newTimeAdjusted = newTime;
+			if (getTimeZone().useDaylightTime()) {
+				int dstSavings = ((SimpleTimeZone) getTimeZone())
+						.getDSTSavings();
+				newTimeAdjusted += (dstOffset == 0) ? dstSavings : -dstSavings;
+			}
+
+			if (newTime > 0L && newTimeAdjusted < 0L && dstOffset == 0)
+				newTimeAdjusted = 0x7fffffffffffffffL;
+			else if (newTime < 0L && newTimeAdjusted > 0L && dstOffset != 0)
+				newTimeAdjusted = 0x8000000000000000L;
+
+			cachedFieldsCheckAndGet(time, newTime, newTimeAdjusted,
+					savedMillis, zoneOffset);
+		} else
+			fullFieldsCalc(time, savedMillis, zoneOffset);
+
+		for (int i = 0; i < FIELD_COUNT; i++)
+			isSet[i] = true;
+
+		// Caching
+		if (!isCached
+				&& newTime != 0x7fffffffffffffffL
+				&& newTime != 0x8000000000000000L
+				&& (!getTimeZone().useDaylightTime() || getTimeZone() instanceof SimpleTimeZone)) {
+			int cacheMillis = 0;
+
+			cachedFields[0] = fields[YEAR];
+			cachedFields[1] = fields[MONTH];
+			cachedFields[2] = fields[DATE];
+			cachedFields[3] = fields[DAY_OF_WEEK];
+			cachedFields[4] = zoneOffset;
+			cachedFields[5] = fields[ERA];
+			cachedFields[6] = fields[WEEK_OF_YEAR];
+			cachedFields[7] = fields[WEEK_OF_MONTH];
+			cachedFields[8] = fields[DAY_OF_YEAR];
+			cachedFields[9] = fields[DAY_OF_WEEK_IN_MONTH];
+
+			cacheMillis += (23 - fields[HOUR_OF_DAY]) * 60 * 60 * 1000;
+			cacheMillis += (59 - fields[MINUTE]) * 60 * 1000;
+			cacheMillis += (59 - fields[SECOND]) * 1000;
+			nextMidnightMillis = newTime + cacheMillis;
+
+			cacheMillis = fields[HOUR_OF_DAY] * 60 * 60 * 1000;
+			cacheMillis += fields[MINUTE] * 60 * 1000;
+			cacheMillis += fields[SECOND] * 1000;
+			lastMidnightMillis = newTime - cacheMillis;
+
+			isCached = true;
+		}
+	}
+
+	/**
+	 * Computes the time from the Calendar fields.
+	 * 
+	 * @exception IllegalArgumentException
+	 *                when the time cannot be computed from the current field
+	 *                values
+	 */
+	protected void computeTime() {
+		if (!isLenient()) {
+			if (isSet[HOUR_OF_DAY]) {
+				if (fields[HOUR_OF_DAY] < 0 || fields[HOUR_OF_DAY] > 23)
+					throw new IllegalArgumentException();
+			} else if (isSet[HOUR] && (fields[HOUR] < 0 || fields[HOUR] > 11))
+				throw new IllegalArgumentException();
+			if (isSet[MINUTE] && (fields[MINUTE] < 0 || fields[MINUTE] > 59))
+				throw new IllegalArgumentException();
+			if (isSet[SECOND] && (fields[SECOND] < 0 || fields[SECOND] > 59))
+				throw new IllegalArgumentException();
+			if (isSet[MILLISECOND]
+					&& (fields[MILLISECOND] < 0 || fields[MILLISECOND] > 999))
+				throw new IllegalArgumentException();
+			if (isSet[WEEK_OF_YEAR]
+					&& (fields[WEEK_OF_YEAR] < 1 || fields[WEEK_OF_YEAR] > 53))
+				throw new IllegalArgumentException();
+			if (isSet[DAY_OF_WEEK]
+					&& (fields[DAY_OF_WEEK] < 1 || fields[DAY_OF_WEEK] > 7))
+				throw new IllegalArgumentException();
+			if (isSet[DAY_OF_WEEK_IN_MONTH]
+					&& (fields[DAY_OF_WEEK_IN_MONTH] < 1 || fields[DAY_OF_WEEK_IN_MONTH] > 6))
+				throw new IllegalArgumentException();
+			if (isSet[WEEK_OF_MONTH]
+					&& (fields[WEEK_OF_MONTH] < 1 || fields[WEEK_OF_MONTH] > 6))
+				throw new IllegalArgumentException();
+			if (isSet[AM_PM] && fields[AM_PM] != AM && fields[AM_PM] != PM)
+				throw new IllegalArgumentException();
+			if (isSet[HOUR] && (fields[HOUR] < 0 || fields[HOUR] > 11))
+				throw new IllegalArgumentException();
+			if (isSet[YEAR]) {
+				if (isSet[ERA] && fields[ERA] == BC
+						&& (fields[YEAR] < 1 || fields[YEAR] > 292269054))
+					throw new IllegalArgumentException();
+				else if (fields[YEAR] < 1 || fields[YEAR] > 292278994)
+					throw new IllegalArgumentException();
+			}
+			if (isSet[MONTH] && (fields[MONTH] < 0 || fields[MONTH] > 11))
+				throw new IllegalArgumentException();
+		}
+
+		long timeVal;
+		int hour = 0;
+		if (isSet[HOUR_OF_DAY] && lastTimeFieldSet != HOUR)
+			hour = fields[HOUR_OF_DAY];
+		else if (isSet[HOUR])
+			hour = (fields[AM_PM] * 12) + fields[HOUR];
+		timeVal = hour * 3600000;
+
+		if (isSet[MINUTE])
+			timeVal += fields[MINUTE] * 60000;
+		if (isSet[SECOND])
+			timeVal += fields[SECOND] * 1000;
+		if (isSet[MILLISECOND])
+			timeVal += fields[MILLISECOND];
+
+		long days;
+		int year = isSet[YEAR] ? fields[YEAR] : 1970;
+		if (isSet[ERA]) {
+			// Always test for valid ERA, even if the Calendar is lenient
+			if (fields[ERA] != BC && fields[ERA] != AD)
+				throw new IllegalArgumentException();
+			if (fields[ERA] == BC)
+				year = 1 - year;
+		}
+
+		boolean weekMonthSet = isSet[WEEK_OF_MONTH]
+				|| isSet[DAY_OF_WEEK_IN_MONTH];
+		boolean useMonth = (isSet[DATE] || isSet[MONTH] || weekMonthSet)
+				&& lastDateFieldSet != DAY_OF_YEAR;
+		if (useMonth
+				&& (lastDateFieldSet == DAY_OF_WEEK || lastDateFieldSet == WEEK_OF_YEAR)) {
+			if (isSet[WEEK_OF_YEAR] && isSet[DAY_OF_WEEK])
+				useMonth = lastDateFieldSet != WEEK_OF_YEAR && weekMonthSet
+						&& isSet[DAY_OF_WEEK];
+			else if (isSet[DAY_OF_YEAR])
+				useMonth = isSet[DATE] && isSet[MONTH];
+		}
+
+		if (useMonth) {
+			int month = fields[MONTH];
+			year += month / 12;
+			month %= 12;
+			if (month < 0) {
+				year--;
+				month += 12;
+			}
+			boolean leapYear = isLeapYear(year);
+			days = daysFromBaseYear(year) + daysInYear(leapYear, month);
+			boolean useDate = isSet[DATE];
+			if (useDate
+					&& (lastDateFieldSet == DAY_OF_WEEK
+							|| lastDateFieldSet == WEEK_OF_MONTH || lastDateFieldSet == DAY_OF_WEEK_IN_MONTH)) {
+				useDate = !(isSet[DAY_OF_WEEK] && weekMonthSet);
+			}
+			if (useDate) {
+				if (!isLenient()
+						&& (fields[DATE] < 1 || fields[DATE] > daysInMonth(
+								leapYear, month)))
+					throw new IllegalArgumentException();
+				days += fields[DATE] - 1;
+			} else {
+				int dayOfWeek;
+				if (isSet[DAY_OF_WEEK]) {
+					dayOfWeek = fields[DAY_OF_WEEK] - 1;
+				} else
+					dayOfWeek = getFirstDayOfWeek() - 1;
+				if (isSet[WEEK_OF_MONTH]
+						&& lastDateFieldSet != DAY_OF_WEEK_IN_MONTH) {
+					int skew = mod7(days - 3 - (getFirstDayOfWeek() - 1));
+					days += (fields[WEEK_OF_MONTH] - 1) * 7
+							+ mod7(skew + dayOfWeek - (days - 3)) - skew;
+				} else if (isSet[DAY_OF_WEEK_IN_MONTH]) {
+					if (fields[DAY_OF_WEEK_IN_MONTH] >= 0) {
+						days += mod7(dayOfWeek - (days - 3))
+								+ (fields[DAY_OF_WEEK_IN_MONTH] - 1) * 7;
+					} else {
+						days += daysInMonth(leapYear, month)
+								+ mod7(dayOfWeek
+										- (days + daysInMonth(leapYear, month) - 3))
+								+ fields[DAY_OF_WEEK_IN_MONTH] * 7;
+					}
+				}
+			}
+		} else {
+			boolean useWeekYear = isSet[WEEK_OF_YEAR]
+					&& lastDateFieldSet != DAY_OF_YEAR;
+			if (useWeekYear && isSet[DAY_OF_YEAR])
+				useWeekYear = isSet[DAY_OF_WEEK];
+			days = daysFromBaseYear(year);
+			if (useWeekYear) {
+				int dayOfWeek;
+				if (isSet[DAY_OF_WEEK]) {
+					dayOfWeek = fields[DAY_OF_WEEK] - 1;
+				} else
+					dayOfWeek = getFirstDayOfWeek() - 1;
+				int skew = mod7(days - 3 - (getFirstDayOfWeek() - 1));
+				days += (fields[WEEK_OF_YEAR] - 1) * 7
+						+ mod7(skew + dayOfWeek - (days - 3)) - skew;
+				if (7 - skew < getMinimalDaysInFirstWeek())
+					days += 7;
+			} else if (isSet[DAY_OF_YEAR]) {
+				if (!isLenient()
+						&& (fields[DAY_OF_YEAR] < 1 || fields[DAY_OF_YEAR] > (365 + (isLeapYear(year) ? 1
+								: 0))))
+					throw new IllegalArgumentException();
+				days += fields[DAY_OF_YEAR] - 1;
+			} else if (isSet[DAY_OF_WEEK]) {
+				days += mod7(fields[DAY_OF_WEEK] - 1 - (days - 3));
+			}
+		}
+		lastDateFieldSet = 0;
+
+		timeVal += days * 86400000;
+		// Use local time to compare with the gregorian change
+		if (year == changeYear
+				&& timeVal >= gregorianCutover + julianError() * 86400000)
+			timeVal -= julianError() * 86400000;
+		timeVal -= getOffset(timeVal);
+		this.time = timeVal;
+	}
+
+	private int computeYearAndDay(long dayCount, long localTime) {
+		int year = 1970;
+		long days = dayCount;
+		if (localTime < gregorianCutover)
+			days -= julianSkew;
+		int approxYears;
+
+		while ((approxYears = (int) (days / 365)) != 0) {
+			year = year + approxYears;
+			days = dayCount - daysFromBaseYear(year);
+		}
+		if (days < 0) {
+			year = year - 1;
+			days = days + 365 + (isLeapYear(year) ? 1 : 0);
+			if (year == changeYear && localTime < gregorianCutover)
+				days -= julianError();
+		}
+		fields[YEAR] = year;
+		return (int) days + 1;
+	}
+
+	private long daysFromBaseYear(int year) {
+		if (year >= 1970) {
+			long days = (year - 1970) * (long) 365 + ((year - 1969) / 4);
+			if (year > changeYear)
+				days -= ((year - 1901) / 100) - ((year - 1601) / 400);
+			else
+				days += julianSkew;
+			return days;
+		} else if (year <= changeYear) {
+			return (year - 1970) * (long) 365 + ((year - 1972) / 4)
+					+ julianSkew;
+		}
+		return (year - 1970) * (long) 365 + ((year - 1972) / 4)
+				- ((year - 2000) / 100) + ((year - 2000) / 400);
+
+	}
+
+	private int daysInMonth() {
+		return daysInMonth(isLeapYear(fields[YEAR]), fields[MONTH]);
+	}
+
+	private int daysInMonth(boolean leapYear, int month) {
+		if (leapYear && month == FEBRUARY)
+			return DaysInMonth[month] + 1;
+
+		return DaysInMonth[month];
+	}
+
+	private int daysInYear() {
+		return isLeapYear(fields[YEAR]) ? 366 : 365;
+	}
+
+	private int daysInYear(boolean leapYear, int month) {
+		if (leapYear && month > FEBRUARY)
+			return DaysInYear[month] + 1;
+
+		return DaysInYear[month];
+	}
+
+	/**
+	 * Compares the specified object to this GregorianCalendar and answer if
+	 * they are equal. The object must be an instance of GregorianCalendar and
+	 * have the same properties.
+	 * 
+	 * @param object
+	 *            the object to compare with this object
+	 * @return true if the specified object is equal to this GregorianCalendar,
+	 *         false otherwise
+	 * 
+	 * @exception IllegalArgumentException
+	 *                when the time is not set and the time cannot be computed
+	 *                from the current field values
+	 * 
+	 * @see #hashCode
+	 */
+	public boolean equals(Object object) {
+		return super.equals(object)
+				&& gregorianCutover == ((GregorianCalendar) object).gregorianCutover;
+	}
+
+	/**
+	 * Gets the maximum value of the specified field for the current date. For
+	 * example, the maximum number of days in the current month.
+	 * 
+	 * @param field
+	 *            the field
+	 * @return the maximum value of the specified field
+	 */
+	public int getActualMaximum(int field) {
+		int value;
+		if ((value = getMaximum(field)) == getLeastMaximum(field))
+			return value;
+
+		switch (field) {
+		case WEEK_OF_YEAR:
+		case WEEK_OF_MONTH:
+			isCached = false;
+			break;
+		}
+
+		complete();
+		long orgTime = time;
+		int result = 0;
+		switch (field) {
+		case WEEK_OF_YEAR:
+			set(DATE, 31);
+			set(MONTH, DECEMBER);
+			result = get(WEEK_OF_YEAR);
+			if (result == 1) {
+				set(DATE, 31 - 7);
+				result = get(WEEK_OF_YEAR);
+			}
+			areFieldsSet = false;
+			break;
+		case WEEK_OF_MONTH:
+			set(DATE, daysInMonth());
+			result = get(WEEK_OF_MONTH);
+			areFieldsSet = false;
+			break;
+		case DATE:
+			return daysInMonth();
+		case DAY_OF_YEAR:
+			return daysInYear();
+		case DAY_OF_WEEK_IN_MONTH:
+			result = get(DAY_OF_WEEK_IN_MONTH)
+					+ ((daysInMonth() - get(DATE)) / 7);
+			break;
+		case YEAR:
+			GregorianCalendar clone = (GregorianCalendar) clone();
+			if (get(ERA) == AD)
+				clone.setTimeInMillis(Long.MAX_VALUE);
+			else
+				clone.setTimeInMillis(Long.MIN_VALUE);
+			result = clone.get(YEAR);
+			clone.set(YEAR, get(YEAR));
+			if (clone.before(this))
+				result--;
+			break;
+		}
+		time = orgTime;
+		return result;
+	}
+
+	/**
+	 * Gets the minimum value of the specified field for the current date. For
+	 * the gregorian calendar, this value is the same as
+	 * <code>getMinimum()</code>.
+	 * 
+	 * @param field
+	 *            the field
+	 * @return the minimum value of the specified field
+	 */
+	public int getActualMinimum(int field) {
+		return getMinimum(field);
+	}
+
+	/**
+	 * Gets the greatest minimum value of the specified field. For the gregorian
+	 * calendar, this value is the same as <code>getMinimum()</code>.
+	 * 
+	 * @param field
+	 *            the field
+	 * @return the greatest minimum value of the specified field
+	 */
+	public int getGreatestMinimum(int field) {
+		return minimums[field];
+	}
+
+	/**
+	 * Answers the gregorian change date of this calendar. This is the date on
+	 * which the gregorian calendar came into effect.
+	 * 
+	 * @return a Date which represents the gregorian change date
+	 */
+	public final Date getGregorianChange() {
+		return new Date(gregorianCutover);
+	}
+
+	/**
+	 * Gets the smallest maximum value of the specified field. For example, 28
+	 * for the day of month field.
+	 * 
+	 * @param field
+	 *            the field
+	 * @return the smallest maximum value of the specified field
+	 */
+	public int getLeastMaximum(int field) {
+		return leastMaximums[field];
+	}
+
+	/**
+	 * Gets the greatest maximum value of the specified field. For example, 31
+	 * for the day of month field.
+	 * 
+	 * @param field
+	 *            the field
+	 * @return the greatest maximum value of the specified field
+	 */
+	public int getMaximum(int field) {
+		return maximums[field];
+	}
+
+	/**
+	 * Gets the smallest minimum value of the specified field.
+	 * 
+	 * @param field
+	 *            the field
+	 * @return the smallest minimum value of the specified field
+	 */
+	public int getMinimum(int field) {
+		return minimums[field];
+	}
+
+	int getOffset(long localTime) {
+		TimeZone timeZone = getTimeZone();
+		if (!timeZone.useDaylightTime())
+			return timeZone.getRawOffset();
+
+		long dayCount = localTime / 86400000;
+		int millis = (int) (localTime % 86400000);
+		if (millis < 0) {
+			millis += 86400000;
+			dayCount--;
+		}
+
+		int year = 1970;
+		long days = dayCount;
+		if (localTime < gregorianCutover)
+			days -= julianSkew;
+		int approxYears;
+
+		while ((approxYears = (int) (days / 365)) != 0) {
+			year = year + approxYears;
+			days = dayCount - daysFromBaseYear(year);
+		}
+		if (days < 0) {
+			year = year - 1;
+			days = days + 365 + (isLeapYear(year) ? 1 : 0);
+			if (year == changeYear && localTime < gregorianCutover)
+				days -= julianError();
+		}
+		if (year <= 0)
+			return timeZone.getRawOffset();
+		int dayOfYear = (int) days + 1;
+
+		int month = dayOfYear / 32;
+		boolean leapYear = isLeapYear(year);
+		int date = dayOfYear - daysInYear(leapYear, month);
+		if (date > daysInMonth(leapYear, month)) {
+			date -= daysInMonth(leapYear, month);
+			month++;
+		}
+		int dayOfWeek = mod7(dayCount - 3) + 1;
+		int offset = timeZone.getOffset(AD, year, month, date, dayOfWeek,
+				millis);
+		return offset;
+	}
+
+	/**
+	 * Answers an integer hash code for the receiver. Objects which are equal
+	 * answer the same value for this method.
+	 * 
+	 * @return the receiver's hash
+	 * 
+	 * @see #equals
+	 */
+	public int hashCode() {
+		return super.hashCode()
+				+ ((int) (gregorianCutover >>> 32) ^ (int) gregorianCutover);
+	}
+
+	/**
+	 * Answers if the specified year is a leap year.
+	 * 
+	 * @param year
+	 *            the year
+	 * @return true if the specified year is a leap year, false otherwise
+	 */
+	public boolean isLeapYear(int year) {
+		if (year > changeYear)
+			return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
+
+		return year % 4 == 0;
+	}
+
+	private int julianError() {
+		return changeYear / 100 - changeYear / 400 - 2;
+	}
+
+	private int mod(int value, int mod) {
+		int rem = value % mod;
+		if (value < 0 && rem < 0)
+			return rem + mod;
+		return rem;
+	}
+
+	private int mod7(long num1) {
+		int rem = (int) (num1 % 7);
+		if (num1 < 0 && rem < 0)
+			return rem + 7;
+		return rem;
+	}
+
+	/**
+	 * Adds the specified amount the specified field and wrap the value of the
+	 * field when it goes beyond the maximum or minimum value for the current
+	 * date. Other fields will be adjusted as required to maintain a consistent
+	 * date.
+	 * 
+	 * @param field
+	 *            the field to roll
+	 * @param value
+	 *            the amount to add
+	 * 
+	 * @exception IllegalArgumentException
+	 *                when an invalid field is specified
+	 */
+	public void roll(int field, int value) {
+		if (value == 0)
+			return;
+		if (field < 0 || field >= ZONE_OFFSET)
+			throw new IllegalArgumentException();
+
+		isCached = false;
+
+		complete();
+		int max = -1;
+		switch (field) {
+		case YEAR:
+			max = maximums[field];
+			break;
+		case WEEK_OF_YEAR:
+		case WEEK_OF_MONTH:
+			int days,
+			day;
+			if (field == WEEK_OF_YEAR) {
+				days = daysInYear();
+				day = DAY_OF_YEAR;
+			} else {
+				days = daysInMonth();
+				day = DATE;
+			}
+			int mod = mod7(fields[DAY_OF_WEEK] - fields[day]
+					- (getFirstDayOfWeek() - 1));
+			int maxWeeks = (days - 1 + mod) / 7 + 1;
+			int newWeek = mod(fields[field] - 1 + value, maxWeeks) + 1;
+			if (newWeek == maxWeeks) {
+				if (fields[day] + (newWeek - fields[field]) * 7 > days)
+					set(day, days);
+				else
+					set(field, newWeek);
+			} else if (newWeek == 1) {
+				int week = (fields[day] - ((fields[day] - 1) / 7 * 7) - 1 + mod) / 7 + 1;
+				if (week > 1)
+					set(day, 1);
+				else
+					set(field, newWeek);
+			} else
+				set(field, newWeek);
+			break;
+		case DATE:
+			max = daysInMonth();
+			break;
+		case DAY_OF_YEAR:
+			max = daysInYear();
+			break;
+		case DAY_OF_WEEK:
+			max = maximums[field];
+			lastDateFieldSet = WEEK_OF_MONTH;
+			break;
+		case DAY_OF_WEEK_IN_MONTH:
+			max = (fields[DATE] + ((daysInMonth() - fields[DATE]) / 7 * 7) - 1) / 7 + 1;
+			break;
+
+		case ERA:
+		case MONTH:
+		case AM_PM:
+		case HOUR:
+		case HOUR_OF_DAY:
+		case MINUTE:
+		case SECOND:
+		case MILLISECOND:
+			set(field, mod(fields[field] + value, maximums[field] + 1));
+			if (field == MONTH && fields[DATE] > daysInMonth())
+				set(DATE, daysInMonth());
+			else if (field == AM_PM)
+				lastTimeFieldSet = HOUR;
+			break;
+		}
+		if (max != -1)
+			set(field, mod(fields[field] - 1 + value, max) + 1);
+		complete();
+	}
+
+	/**
+	 * Increment or decrement the specified field and wrap the value of the
+	 * field when it goes beyond the maximum or minimum value for the current
+	 * date. Other fields will be adjusted as required to maintain a consistent
+	 * date. For example, March 31 will roll to April 30 when rolling the month
+	 * field.
+	 * 
+	 * @param field
+	 *            the field to roll
+	 * @param increment
+	 *            true to increment the field, false to decrement
+	 * 
+	 * @exception IllegalArgumentException
+	 *                when an invalid field is specified
+	 */
+	public void roll(int field, boolean increment) {
+		roll(field, increment ? 1 : -1);
+	}
+
+	/**
+	 * Sets the gregorian change date of this calendar.
+	 * 
+	 * @param date
+	 *            a Date which represents the gregorian change date
+	 */
+	public void setGregorianChange(Date date) {
+		gregorianCutover = date.getTime();
+		GregorianCalendar cal = new GregorianCalendar(TimeZone.GMT);
+		cal.setTime(date);
+		changeYear = cal.get(YEAR);
+		if (cal.get(ERA) == BC)
+			changeYear = 1 - changeYear;
+		julianSkew = ((changeYear - 2000) / 400) + julianError()
+				- ((changeYear - 2000) / 100);
+		isCached = false;
+	}
+
+	private void writeObject(ObjectOutputStream stream) throws IOException {
+		stream.defaultWriteObject();
+	}
+
+	private void readObject(ObjectInputStream stream) throws IOException,
+			ClassNotFoundException {
+
+		stream.defaultReadObject();
+		setGregorianChange(new Date(gregorianCutover));
+		isCached = false;
+	}
+
+	public void setFirstDayOfWeek(int value) {
+		super.setFirstDayOfWeek(value);
+		isCached = false;
+	}
+
+	public void setMinimalDaysInFirstWeek(int value) {
+		super.setMinimalDaysInFirstWeek(value);
+		isCached = false;
+	}
+}



Mime
View raw message