GregorianCalendarpublic class GregorianCalendar extends Calendar {@code GregorianCalendar} is a concrete subclass of {@link Calendar}
and provides the standard calendar used by most of the world.
The standard (Gregorian) calendar has 2 eras, BC and AD.
This implementation handles a single discontinuity, which corresponds by
default to the date the Gregorian calendar was instituted (October 15, 1582
in some countries, later in others). The cutover date may be changed by the
caller by calling {@code setGregorianChange()}.
Historically, in those countries which adopted the Gregorian calendar first,
October 4, 1582 was thus followed by October 15, 1582. This calendar models
this correctly. Before the Gregorian cutover, {@code GregorianCalendar}
implements the Julian calendar. The only difference between the Gregorian and
the Julian calendar is the leap year rule. The Julian calendar specifies leap
years every four years, whereas the Gregorian calendar omits century years
which are not divisible by 400.
{@code GregorianCalendar} implements proleptic Gregorian
and Julian calendars. That is, dates are computed by extrapolating the
current rules indefinitely far backward and forward in time. As a result,
{@code GregorianCalendar} may be used for all years to generate
meaningful and consistent results. However, dates obtained using
{@code GregorianCalendar} are historically accurate only from March 1,
4 AD onward, when modern Julian calendar rules were adopted. Before this
date, leap year rules were applied irregularly, and before 45 BC the Julian
calendar did not even exist.
Prior to the institution of the Gregorian calendar, New Year's Day was March
25. To avoid confusion, this calendar always uses January 1. A manual
adjustment may be made if desired for dates that are prior to the Gregorian
changeover and which fall between January 1 and March 24.
Values calculated for the {@code WEEK_OF_YEAR} field range from 1 to
53. Week 1 for a year is the earliest seven day period starting on
{@code getFirstDayOfWeek()} that contains at least
{@code getMinimalDaysInFirstWeek()} days from that year. It thus
depends on the values of {@code getMinimalDaysInFirstWeek()},
{@code getFirstDayOfWeek()}, and the day of the week of January 1.
Weeks between week 1 of one year and week 1 of the following year are
numbered sequentially from 2 to 52 or 53 (as needed).
For example, January 1, 1998 was a Thursday. If
{@code getFirstDayOfWeek()} is {@code MONDAY} and
{@code getMinimalDaysInFirstWeek()} is 4 (these are the values
reflecting ISO 8601 and many national standards), then week 1 of 1998 starts
on December 29, 1997, and ends on January 4, 1998. If, however,
{@code getFirstDayOfWeek()} is {@code SUNDAY}, then week 1 of
1998 starts on January 4, 1998, and ends on January 10, 1998; the first three
days of 1998 then are part of week 53 of 1997.
Values calculated for the {@code WEEK_OF_MONTH} field range from 0 or
1 to 4 or 5. Week 1 of a month (the days with WEEK_OF_MONTH =
1 )
is the earliest set of at least {@code getMinimalDaysInFirstWeek()}
contiguous days in that month, ending on the day before
{@code getFirstDayOfWeek()}. Unlike week 1 of a year, week 1 of a
month may be shorter than 7 days, need not start on
{@code getFirstDayOfWeek()}, and will not include days of the
previous month. Days of a month before week 1 have a
{@code WEEK_OF_MONTH} of 0.
For example, if {@code getFirstDayOfWeek()} is {@code SUNDAY}
and {@code getMinimalDaysInFirstWeek()} is 4, then the first week of
January 1998 is Sunday, January 4 through Saturday, January 10. These days
have a {@code WEEK_OF_MONTH} of 1. Thursday, January 1 through
Saturday, January 3 have a {@code WEEK_OF_MONTH} of 0. If
{@code getMinimalDaysInFirstWeek()} is changed to 3, then January 1
through January 3 have a {@code WEEK_OF_MONTH} of 1.
Example:
// get the supported ids for GMT-08:00 (Pacific Standard Time)
String[] ids = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000);
// if no ids were returned, something is wrong. get out.
if (ids.length == 0)
System.exit(0);
// begin output
System.out.println("Current Time");
// create a Pacific Standard Time time zone
SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, ids[0]);
// set up rules for daylight savings time
pdt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
pdt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
// create a GregorianCalendar with the Pacific Daylight time zone
// and the current date and time
Calendar calendar = new GregorianCalendar(pdt);
Date trialTime = new Date();
calendar.setTime(trialTime);
// print out a bunch of interesting things
System.out.println("ERA: " + calendar.get(Calendar.ERA));
System.out.println("YEAR: " + calendar.get(Calendar.YEAR));
System.out.println("MONTH: " + calendar.get(Calendar.MONTH));
System.out.println("WEEK_OF_YEAR: " + calendar.get(Calendar.WEEK_OF_YEAR));
System.out.println("WEEK_OF_MONTH: " + calendar.get(Calendar.WEEK_OF_MONTH));
System.out.println("DATE: " + calendar.get(Calendar.DATE));
System.out.println("DAY_OF_MONTH: " + calendar.get(Calendar.DAY_OF_MONTH));
System.out.println("DAY_OF_YEAR: " + calendar.get(Calendar.DAY_OF_YEAR));
System.out.println("DAY_OF_WEEK: " + calendar.get(Calendar.DAY_OF_WEEK));
System.out.println("DAY_OF_WEEK_IN_MONTH: "
+ calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH));
System.out.println("AM_PM: " + calendar.get(Calendar.AM_PM));
System.out.println("HOUR: " + calendar.get(Calendar.HOUR));
System.out.println("HOUR_OF_DAY: " + calendar.get(Calendar.HOUR_OF_DAY));
System.out.println("MINUTE: " + calendar.get(Calendar.MINUTE));
System.out.println("SECOND: " + calendar.get(Calendar.SECOND));
System.out.println("MILLISECOND: " + calendar.get(Calendar.MILLISECOND));
System.out.println("ZONE_OFFSET: "
+ (calendar.get(Calendar.ZONE_OFFSET)/(60*60*1000)));
System.out.println("DST_OFFSET: "
+ (calendar.get(Calendar.DST_OFFSET)/(60*60*1000)));
System.out.println("Current Time, with hour reset to 3");
calendar.clear(Calendar.HOUR_OF_DAY); // so doesn't override
calendar.set(Calendar.HOUR, 3);
System.out.println("ERA: " + calendar.get(Calendar.ERA));
System.out.println("YEAR: " + calendar.get(Calendar.YEAR));
System.out.println("MONTH: " + calendar.get(Calendar.MONTH));
System.out.println("WEEK_OF_YEAR: " + calendar.get(Calendar.WEEK_OF_YEAR));
System.out.println("WEEK_OF_MONTH: " + calendar.get(Calendar.WEEK_OF_MONTH));
System.out.println("DATE: " + calendar.get(Calendar.DATE));
System.out.println("DAY_OF_MONTH: " + calendar.get(Calendar.DAY_OF_MONTH));
System.out.println("DAY_OF_YEAR: " + calendar.get(Calendar.DAY_OF_YEAR));
System.out.println("DAY_OF_WEEK: " + calendar.get(Calendar.DAY_OF_WEEK));
System.out.println("DAY_OF_WEEK_IN_MONTH: "
+ calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH));
System.out.println("AM_PM: " + calendar.get(Calendar.AM_PM));
System.out.println("HOUR: " + calendar.get(Calendar.HOUR));
System.out.println("HOUR_OF_DAY: " + calendar.get(Calendar.HOUR_OF_DAY));
System.out.println("MINUTE: " + calendar.get(Calendar.MINUTE));
System.out.println("SECOND: " + calendar.get(Calendar.SECOND));
System.out.println("MILLISECOND: " + calendar.get(Calendar.MILLISECOND));
System.out.println("ZONE_OFFSET: "
+ (calendar.get(Calendar.ZONE_OFFSET)/(60*60*1000))); // in hours
System.out.println("DST_OFFSET: "
+ (calendar.get(Calendar.DST_OFFSET)/(60*60*1000))); // in hours
|
Fields Summary |
---|
private static final long | serialVersionUID | public static final int | BCValue for the BC era. | public static final int | ADValue for the AD era. | private static final long | defaultGregorianCutover | private long | gregorianCutover | private transient int | changeYear | private transient int | julianSkew | static byte[] | DaysInMonth | private static int[] | DaysInYear | private static int[] | maximums | private static int[] | minimums | private static int[] | leastMaximums | private boolean | isCached | private int[] | cachedFields | private long | nextMidnightMillis | private long | lastMidnightMillis | private int | currentYearSkew | private int | lastYearSkew |
Constructors Summary |
---|
public GregorianCalendar()Constructs a new {@code GregorianCalendar} initialized to the current date and
time with the default {@code Locale} and {@code TimeZone}.
this(TimeZone.getDefault(), Locale.getDefault());
| public GregorianCalendar(int year, int month, int day)Constructs a new {@code GregorianCalendar} initialized to midnight in the default
{@code TimeZone} and {@code Locale} on the specified date.
super(TimeZone.getDefault(), Locale.getDefault());
set(year, month, day);
| public GregorianCalendar(int year, int month, int day, int hour, int minute)Constructs a new {@code GregorianCalendar} initialized to the specified date and
time in the default {@code TimeZone} and {@code Locale}.
super(TimeZone.getDefault(), Locale.getDefault());
set(year, month, day, hour, minute);
| public GregorianCalendar(int year, int month, int day, int hour, int minute, int second)Constructs a new {@code GregorianCalendar} initialized to the specified date and
time in the default {@code TimeZone} and {@code Locale}.
super(TimeZone.getDefault(), Locale.getDefault());
set(year, month, day, hour, minute, second);
| GregorianCalendar(long milliseconds)
this(false);
setTimeInMillis(milliseconds);
| public GregorianCalendar(Locale locale)Constructs a new {@code GregorianCalendar} initialized to the current date and
time and using the specified {@code Locale} and the default {@code TimeZone}.
this(TimeZone.getDefault(), locale);
| public GregorianCalendar(TimeZone timezone)Constructs a new {@code GregorianCalendar} initialized to the current date and
time and using the specified {@code TimeZone} and the default {@code Locale}.
this(timezone, Locale.getDefault());
| public GregorianCalendar(TimeZone timezone, Locale locale)Constructs a new {@code GregorianCalendar} initialized to the current date and
time and using the specified {@code TimeZone} and {@code Locale}.
super(timezone, locale);
setTimeInMillis(System.currentTimeMillis());
| GregorianCalendar(boolean ignored)
super(TimeZone.getDefault());
setFirstDayOfWeek(SUNDAY);
setMinimalDaysInFirstWeek(1);
|
Methods Summary |
---|
public void | add(int field, int value)Adds the specified amount to a {@code Calendar} field.
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 | 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];
}
| public java.lang.Object | clone()Creates new instance of {@code GregorianCalendar} with the same properties.
GregorianCalendar thisClone = (GregorianCalendar) super.clone();
thisClone.cachedFields = cachedFields.clone();
return thisClone;
| 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()) {
// BEGIN android-changed: removed unnecessary cast
int dstSavings = (/* (SimpleTimeZone) */ getTimeZone())
.getDSTSavings();
// END android-changed
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;
}
| 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;
long 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 += ((long) fields[MINUTE]) * 60000;
}
if (isSet[SECOND]) {
timeVal += ((long) 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() * 86400000L) {
timeVal -= julianError() * 86400000L;
}
// It is not possible to simply subtract getOffset(timeVal) from timeVal
// to get UTC.
// The trick is needed for the moment when DST transition occurs,
// say 1:00 is a transition time when DST offset becomes +1 hour,
// then wall time in the interval 1:00 - 2:00 is invalid and is
// treated as UTC time.
long timeValWithoutDST = timeVal - getOffset(timeVal)
+ getTimeZone().getRawOffset();
timeVal -= getOffset(timeValWithoutDST);
// Need to update wall time in fields, since it was invalid due to DST
// transition
this.time = timeVal;
if (timeValWithoutDST != timeVal) {
computeFields();
areFieldsSet = true;
}
| 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 + daysInYear(year);
}
fields[YEAR] = year;
return (int) days + 1;
| private long | daysFromBaseYear(int iyear)
long year = iyear;
if (year >= 1970) {
long days = (year - 1970) * 365 + ((year - 1969) / 4);
if (year > changeYear) {
days -= ((year - 1901) / 100) - ((year - 1601) / 400);
} else {
if(year == changeYear){
days += currentYearSkew;
}else if(year == changeYear -1){
days += lastYearSkew;
}else{
days += julianSkew;
}
}
return days;
} else if (year <= changeYear) {
return (year - 1970) * 365 + ((year - 1972) / 4) + julianSkew;
}
return (year - 1970) * 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(int year)
int daysInYear = isLeapYear(year) ? 366 : 365;
if (year == changeYear) {
daysInYear -= currentYearSkew;
}
if (year == changeYear - 1) {
daysInYear -= lastYearSkew;
}
return daysInYear;
| private int | daysInYear(boolean leapYear, int month)
if (leapYear && month > FEBRUARY) {
return DaysInYear[month] + 1;
}
return DaysInYear[month];
| public boolean | equals(java.lang.Object object)Compares the specified {@code Object} to this {@code GregorianCalendar} and returns whether
they are equal. To be equal, the {@code Object} must be an instance of {@code GregorianCalendar} and
have the same properties.
return super.equals(object)
&& gregorianCutover == ((GregorianCalendar) object).gregorianCutover;
| 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;
while (millis < 0) {
millis += 86400000;
days--;
}
while (millis >= 86400000) {
millis -= 86400000;
days++;
}
int dayOfYear = computeYearAndDay(days, timeVal + zoneOffset);
fields[DAY_OF_YEAR] = dayOfYear;
if(fields[YEAR] == changeYear && gregorianCutover < timeVal + zoneOffset){
dayOfYear += currentYearSkew;
}
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;
if(fields[YEAR] == changeYear && gregorianCutover < timeVal - zoneOffset + dstOffset){
dayOfYear += currentYearSkew;
}
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;
}
| public int | getActualMaximum(int field)Gets the maximum value of the specified field for the current date. For
example, the maximum number of days in the current month.
int value;
if ((value = maximums[field]) == leastMaximums[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(fields[YEAR]);
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;
case DST_OFFSET:
result = getMaximum(DST_OFFSET);
break;
}
time = orgTime;
return result;
| public int | getActualMinimum(int field)Gets the minimum value of the specified field for the current date. For
the gregorian calendar, this value is the same as
{@code getMinimum()}.
return getMinimum(field);
| public int | getGreatestMinimum(int field)Gets the greatest minimum value of the specified field. For the gregorian
calendar, this value is the same as {@code getMinimum()}.
return minimums[field];
| public final java.util.Date | getGregorianChange()Returns the gregorian change date of this calendar. This is the date on
which the gregorian calendar came into effect.
return new Date(gregorianCutover);
| public int | getLeastMaximum(int field)Gets the smallest maximum value of the specified field. For example, 28
for the day of month field.
// return value for WEEK_OF_YEAR should make corresponding changes when
// the gregorian change date have been reset.
if (gregorianCutover != defaultGregorianCutover
&& field == WEEK_OF_YEAR) {
long currentTimeInMillis = time;
setTimeInMillis(gregorianCutover);
int actual = getActualMaximum(field);
setTimeInMillis(currentTimeInMillis);
return actual;
}
return leastMaximums[field];
| public int | getMaximum(int field)Gets the greatest maximum value of the specified field. For example, 31
for the day of month field.
return maximums[field];
| public int | getMinimum(int field)Gets the smallest minimum value of the specified 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;
| public int | hashCode()Returns an integer hash code for the receiver. Objects which are equal
return the same value for this method.
return super.hashCode()
+ ((int) (gregorianCutover >>> 32) ^ (int) gregorianCutover);
| public boolean | isLeapYear(int year)Returns whether the specified year is a leap 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;
| private void | readObject(java.io.ObjectInputStream stream)
stream.defaultReadObject();
setGregorianChange(new Date(gregorianCutover));
isCached = false;
| public void | roll(int field, int value)Adds the specified amount the specified field and wraps 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.
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(fields[YEAR]);
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(fields[YEAR]);
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();
| public void | roll(int field, boolean increment)Increments or decrements the specified field and wraps 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.
roll(field, increment ? 1 : -1);
| public void | setFirstDayOfWeek(int value)
super.setFirstDayOfWeek(value);
isCached = false;
| public void | setGregorianChange(java.util.Date date)Sets the gregorian change date of this calendar.
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;
int dayOfYear = cal.get(DAY_OF_YEAR);
if (dayOfYear < julianSkew) {
currentYearSkew = dayOfYear-1;
lastYearSkew = julianSkew - dayOfYear + 1;
} else {
lastYearSkew = 0;
currentYearSkew = julianSkew;
}
isCached = false;
| public void | setMinimalDaysInFirstWeek(int value)
super.setMinimalDaysInFirstWeek(value);
isCached = false;
| private void | writeObject(java.io.ObjectOutputStream stream)
stream.defaultWriteObject();
|
|