diff options
Diffstat (limited to 'libjava/java/util/GregorianCalendar.java')
-rw-r--r-- | libjava/java/util/GregorianCalendar.java | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/libjava/java/util/GregorianCalendar.java b/libjava/java/util/GregorianCalendar.java new file mode 100644 index 00000000000..d20c06ef825 --- /dev/null +++ b/libjava/java/util/GregorianCalendar.java @@ -0,0 +1,257 @@ +/* Copyright (C) 1998, 1999 Cygnus Solutions + + 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. */ + +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. + */ + +public class GregorianCalendar extends Calendar { + public static final int BC = 0; + 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 */ + }; + + 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 */ + }; + + 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 */ + }; + + public GregorianCalendar () + { + this(null, null); + } + + public GregorianCalendar (TimeZone zone) + { + this (zone, null); + } + + public GregorianCalendar (Locale locale) + { + this (null, locale); + } + + public GregorianCalendar (TimeZone zone, Locale locale) + { + super (zone, locale); + } + + public GregorianCalendar (int year, int month, int date) + { + this((TimeZone) null); + set (year, month, date); + } + + public GregorianCalendar (int year, int month, int date, + int hour, int minute) + { + this((TimeZone) null); + set (year, month, date, hour, minute); + } + + public GregorianCalendar (int year, int month, int date, + int hour, int minute, int second) + { + this((TimeZone) null); + set (year, month, date, hour, minute, second); + } + + 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]; } + + protected native void computeFields(); + + protected native void computeTime(); + + public void add (int fld, int amount) + { + if (fld >= ZONE_OFFSET) + throw new IllegalArgumentException("bad field to add"); + fields[fld] += amount; + adjust(fld); + } + + public void roll (int fld, boolean up) + { + if (fld >= ZONE_OFFSET) + throw new IllegalArgumentException("bad field to roll"); + + int old = fields[fld]; + if (up) + { + fields[fld] = old == getMaximum(fld) ? getMinimum(fld) + : old + 1; + } + else + { + fields[fld] = old == getMinimum(fld) ? getMaximum(fld) + : old - 1; + } + } + + private void adjust (int fld) + { + int value = fields[fld]; + int radix = maxs[fld] + 1; + switch (fld) + { + case MONTH: + case SECOND: + case MILLISECOND: + if (value >= radix) + { + int next = value / radix; + fields[fld] = value - radix * next; + fields[fld - 1] += next; + adjust(fld - 1); + } + else if (value < 0) // min[fld] + { + int next = (value - radix - 1) / radix; + fields[fld] = value - radix * next; + fields[fld - 1] += next; + adjust(fld - 1); + } + break; + } + } + + public final Date getGregorianChange() { return new Date(gregorianCutover); } + public void setGregorianChange (Date date) + { gregorianCutover = date.getTime(); } + + public boolean isLeapYear(int year) + { + 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(); + } + + public boolean after (Object cal) + { + return cal instanceof Calendar + && getTimeInMillis() > ((Calendar) cal).getTimeInMillis(); + } + + public boolean before (Object cal) + { + return cal instanceof Calendar + && getTimeInMillis() < ((Calendar) cal).getTimeInMillis(); + } + + public boolean equals (Object obj) + { + if (obj == null || ! (obj instanceof GregorianCalendar)) + return false; + GregorianCalendar other = (GregorianCalendar) obj; + + for (int i = FIELD_COUNT; --i >= 0; ) + { + 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; + } + + public int hashCode () + { + int hashcode = 0; + for (int i = FIELD_COUNT; --i >= 0; ) + { + if (isSet[i]) + hashcode += 37 * fields[i]; + } + if (isTimeSet) + hashcode += 89 * time; + return hashcode; + } +} |