Calendarpublic abstract class Calendar extends Object Calendar is an abstract class for getting and setting dates
using a set of integer fields such as
YEAR , MONTH , DAY ,
and so on. (A Date object represents a specific instant in
time with millisecond precision. See
{@link Date}
for information about the Date class.)
Subclasses of Calendar interpret a Date
according to the rules of a specific calendar system.
Like other locale-sensitive classes, Calendar provides a
class method, getInstance , for getting a generally useful
object of this type.
Calendar rightNow = Calendar.getInstance();
A Calendar object can produce all the time field values
needed to implement the date-time formatting for a particular language
and calendar style (for example, Japanese-Gregorian, Japanese-Traditional).
When computing a Date from time fields,
there may be insufficient information to compute the
Date (such as only year and month but no day in the month).
Insufficient information. The calendar will use default
information to specify the missing fields. This may vary by calendar; for
the Gregorian calendar, the default for a field is the same as that of the
start of the epoch: i.e., YEAR = 1970, MONTH = JANUARY, DATE = 1, etc.
Inconsistent information. In the J2SE calendar, it is
possible to set fields inconsistently. However, in this subset, the
DAY_OF_WEEK field cannot be set, and only a subset of the other J2SE
Calendar fields are included. So it is not possible to set
inconsistent data.
Note: The ambiguity in interpretation of what day midnight
belongs to, is resolved as so: midnight "belongs" to the following day.
23:59 on Dec 31, 1969 < 00:00 on Jan 1, 1970.
12:00 PM is midday, and 12:00 AM is midnight.
11:59 PM on Jan 1 < 12:00 AM on Jan 2 < 12:01 AM on Jan 2.
11:59 AM on Mar 10 < 12:00 PM on Mar 10 < 12:01 PM on Mar 10.
24:00 or greater are invalid.
Hours greater than 12 are invalid in AM/PM mode.
Setting the time will never change the date.
If equivalent times are entered in AM/PM or 24 hour mode, equality will be
determined by the actual time rather than the entered time.
This class is a subset for J2ME of the J2SE Calendar class.
Many methods and variables have been
pruned, and other methods simplified, in an effort to reduce the size
of this class. |
Fields Summary |
---|
public static final int | YEARField number for get and set indicating the
year. This is a calendar-specific value. | public static final int | MONTHField number for get and set indicating the
month. This is a calendar-specific value. | public static final int | DATEField number for get and set indicating the
day of the month. This is a synonym for DAY_OF_MONTH . | public static final int | DAY_OF_MONTHField number for get and set indicating the
day of the month. This is a synonym for DATE . | public static final int | DAY_OF_WEEKField number for get and set indicating the
day of the week. | public static final int | AM_PMField number for get and set indicating
whether the HOUR is before or after noon.
E.g., at 10:04:15.250 PM the AM_PM is PM . | public static final int | HOURField number for get and set indicating the
hour of the morning or afternoon. HOUR is used for the
12-hour clock.
E.g., at 10:04:15.250 PM the HOUR is 10. | public static final int | HOUR_OF_DAYField number for get and set indicating the
hour of the day. HOUR_OF_DAY is used for the 24-hour clock.
E.g., at 10:04:15.250 PM the HOUR_OF_DAY is 22. | public static final int | MINUTEField number for get and set indicating the
minute within the hour.
E.g., at 10:04:15.250 PM the MINUTE is 4. | public static final int | SECONDField number for get and set indicating the
second within the minute.
E.g., at 10:04:15.250 PM the SECOND is 15. | public static final int | MILLISECONDField number for get and set indicating the
millisecond within the second.
E.g., at 10:04:15.250 PM the MILLISECOND is 250. | public static final int | SUNDAYValue of the DAY_OF_WEEK field indicating
Sunday. | public static final int | MONDAYValue of the DAY_OF_WEEK field indicating
Monday. | public static final int | TUESDAYValue of the DAY_OF_WEEK field indicating
Tuesday. | public static final int | WEDNESDAYValue of the DAY_OF_WEEK field indicating
Wednesday. | public static final int | THURSDAYValue of the DAY_OF_WEEK field indicating
Thursday. | public static final int | FRIDAYValue of the DAY_OF_WEEK field indicating
Friday. | public static final int | SATURDAYValue of the DAY_OF_WEEK field indicating
Saturday. | public static final int | JANUARYValue of the MONTH field indicating the
first month of the year. | public static final int | FEBRUARYValue of the MONTH field indicating the
second month of the year. | public static final int | MARCHValue of the MONTH field indicating the
third month of the year. | public static final int | APRILValue of the MONTH field indicating the
fourth month of the year. | public static final int | MAYValue of the MONTH field indicating the
fifth month of the year. | public static final int | JUNEValue of the MONTH field indicating the
sixth month of the year. | public static final int | JULYValue of the MONTH field indicating the
seventh month of the year. | public static final int | AUGUSTValue of the MONTH field indicating the
eighth month of the year. | public static final int | SEPTEMBERValue of the MONTH field indicating the
ninth month of the year. | public static final int | OCTOBERValue of the MONTH field indicating the
tenth month of the year. | public static final int | NOVEMBERValue of the MONTH field indicating the
eleventh month of the year. | public static final int | DECEMBERValue of the MONTH field indicating the
twelfth month of the year. | public static final int | AMValue of the AM_PM field indicating the
period of the day from midnight to just before noon. | public static final int | PMValue of the AM_PM field indicating the
period of the day from noon to just before midnight. | private int | packed_time | private int | packed_date | private int | day_field | private int | dstOffset | private boolean | dstSet | private long | timeThe currently set time for this calendar, expressed in milliseconds after
January 1, 1970, 0:00:00 GMT. | private boolean | millisSetTrue if then the value of time is valid.
The time is made invalid by a change to an item of field[] . | private TimeZone | zoneThe TimeZone used by this calendar. Calendar
uses the time zone data to translate between locale and GMT time. | private static final int | JAN_1_1_JULIAN_DAY | private static final int | EPOCH_JULIAN_DAY | private static final int | EPOCH_YEAR | private static final int[] | NUM_DAYS | private static final int[] | LEAP_NUM_DAYS | private static final int | ONE_SECOND | private static final int | ONE_MINUTE | private static final int | ONE_HOUR | private static final long | ONE_DAY | private static final long | ONE_WEEK | private static final long | gregorianCutoverThe point at which the Gregorian calendar rules are used, measured in
milliseconds from the standard epoch. Default is October 15, 1582
(Gregorian) 00:00:00 UTC or -12219292800000L. For this value, October 4,
1582 (Julian) is followed by October 15, 1582 (Gregorian). This
corresponds to Julian day number 2299161. | private static final int | gregorianCutoverYearThe year of the gregorianCutover, with 0 representing
1 BC, -1 representing 2 BC, etc. | private Date | date | private int | hour_12hrif both of these are set, the set() method will recalculate
the HOUR_OF_DAY using 12hr time. | private int | am_pm_12hr | private static String | platformThe platform name | private static String | classRootThe root of the classes |
Constructors Summary |
---|
protected Calendar()Constructs a Calendar with the default time zone
and default locale.
zone = TimeZone.getDefault();
if (zone == null) {
throw new RuntimeException(
/* #ifdef VERBOSE_EXCEPTIONS */
/// skipped "Could not find default timezone"
/* #endif */
);
}
setTimeInMillis(System.currentTimeMillis());
|
Methods Summary |
---|
public boolean | after(java.lang.Object when)Compares the time field records.
Equivalent to comparing result of conversion to UTC.
return (when instanceof Calendar
&& getTimeInMillis() > ((Calendar)when).getTimeInMillis());
| public boolean | before(java.lang.Object when)Compares the time field records.
Equivalent to comparing result of conversion to UTC.
return (when instanceof Calendar
&& getTimeInMillis() < ((Calendar)when).getTimeInMillis());
| private void | calculateDstOffset()
if (day_field == 0) {
getTimeInMillis();
calculateFields();
}
int rawOffset = zone.getRawOffset();
long localMillis = time + rawOffset;
long days = (long) (localMillis / ONE_DAY);
int millisInDay = (int) (localMillis - (days * ONE_DAY));
if (millisInDay < 0)
millisInDay += ONE_DAY;
dstOffset = zone.getOffset(1,
packed_date >> 9,
(packed_date >> 5) & 15,
packed_date & 31,
day_field,
millisInDay) - rawOffset;
dstSet = true;
| private void | calculateFields()Converts UTC as milliseconds to time field values.
int rawOffset = zone.getRawOffset();
long localMillis = time + rawOffset;
/* Check for very extreme values -- millis near Long.MIN_VALUE or
* Long.MAX_VALUE. For these values, adding the zone offset can push
* the millis past MAX_VALUE to MIN_VALUE, or vice versa. This produces
* the undesirable effect that the time can wrap around at the ends,
* yielding, for example, a Date(Long.MAX_VALUE) with a big BC year
* (should be AD). Handle this by pinning such values to Long.MIN_VALUE
* or Long.MAX_VALUE. - liu 8/11/98 CR 4149677 */
if (time > 0 && localMillis < 0 && rawOffset > 0) {
localMillis = Long.MAX_VALUE;
} else if (time < 0 && localMillis > 0 && rawOffset < 0) {
localMillis = Long.MIN_VALUE;
}
// Time to fields takes the wall millis (Standard or DST).
timeToFields(localMillis);
long days = (long) (localMillis / ONE_DAY);
int millisInDay = (int) (localMillis - (days * ONE_DAY));
if (millisInDay < 0) millisInDay += ONE_DAY;
// Call getOffset() to get the TimeZone offset. The millisInDay value must
// be standard local millis.
dstOffset = zone.getOffset(1,
packed_date >> 9,
(packed_date >> 5) & 15,
packed_date & 31,
day_field,
millisInDay) - rawOffset;
dstSet = true;
// Adjust our millisInDay for DST, if necessary.
millisInDay += dstOffset;
// If DST has pushed us into the next day, we must call timeToFields() again.
// This happens in DST between 12:00 am and 1:00 am every day. The call to
// timeToFields() will give the wrong day, since the Standard time is in the
// previous day.
if (millisInDay >= ONE_DAY) {
long dstMillis = localMillis + dstOffset;
millisInDay -= ONE_DAY;
// As above, check for and pin extreme values
if (localMillis > 0 && dstMillis < 0 && dstOffset > 0) {
dstMillis = Long.MAX_VALUE;
} else if (localMillis < 0 && dstMillis > 0 && dstOffset < 0) {
dstMillis = Long.MIN_VALUE;
}
timeToFields(dstMillis);
}
// Fill in all time-related fields based on millisInDay.
// so as not to perturb flags.
packed_time = (packed_time & (~1023)) | (millisInDay % 1000);
millisInDay /= 1000;
packed_time = (packed_time & (~(63<<10))) | ((millisInDay % 60) << 10);
millisInDay /= 60;
packed_time = (packed_time & (~(63<<16))) | ((millisInDay % 60) << 16);
millisInDay /= 60;
packed_time = (packed_time & (~(31<<22))) | ((millisInDay & 31) << 22);
| private final long | calculateJulianDay(boolean isGregorian, int year)Compute the Julian day number under either the Gregorian or the
Julian calendar, using the given year and the remaining fields.
int month = 0, y;
long millis = 0;
month = (packed_date >> 5) & 15 - JANUARY;
// If the month is out of range, adjust it into range
if (month < 0 || month > 11) {
int[] rem = new int[1];
year += floorDivide(month, 12, rem);
month = rem[0];
}
boolean isLeap = year%4 == 0;
y = year - 1;
long julianDay = 365L*y + floorDivide(y, 4) + (JAN_1_1_JULIAN_DAY - 3);
if (isGregorian) {
isLeap = isLeap && ((year%100 != 0) || (year%400 == 0));
// Add 2 because Gregorian calendar starts 2 days after Julian calendar
julianDay += floorDivide(y, 400) - floorDivide(y, 100) + 2;
}
// At this point julianDay is the 0-based day BEFORE the first day of
// January 1, year 1 of the given calendar. If julianDay == 0, it
// specifies (Jan. 1, 1) - 1, in whatever calendar we are using (Julian
// or Gregorian).
julianDay += isLeap ? LEAP_NUM_DAYS[month] : NUM_DAYS[month];
julianDay += packed_date & 31;
return julianDay;
| private void | calculateTime()Converts time field values to UTC as milliseconds.
// This function takes advantage of the fact that unset fields in
// the time field list have a value of zero.
// First, use the year to determine whether to use the Gregorian or the
// Julian calendar. If the year is not the year of the cutover, this
// computation will be correct. But if the year is the cutover year,
// this may be incorrect. In that case, assume the Gregorian calendar,
// make the computation, and then recompute if the resultant millis
// indicate the wrong calendar has been assumed.
// A date such as Oct. 10, 1582 does not exist in a Gregorian calendar
// with the default changeover of Oct. 15, 1582, since in such a
// calendar Oct. 4 (Julian) is followed by Oct. 15 (Gregorian). This
// algorithm will interpret such a date using the Julian calendar,
// yielding Oct. 20, 1582 (Gregorian).
int year_field = packed_date >> 9;
boolean isGregorian = year_field >= gregorianCutoverYear;
long julianDay = calculateJulianDay(isGregorian, year_field);
long millis = julianDayToMillis(julianDay);
// The following check handles portions of the cutover year BEFORE the
// cutover itself happens. The check for the julianDate number is for a
// rare case; it's a hardcoded number, but it's efficient. The given
// Julian day number corresponds to Dec 3, 292269055 BC, which
// corresponds to millis near Long.MIN_VALUE. The need for the check
// arises because for extremely negative Julian day numbers, the millis
// actually overflow to be positive values. Without the check, the
// initial date is interpreted with the Gregorian calendar, even when
// the cutover doesn't warrant it.
if (isGregorian != (millis >= gregorianCutover) &&
julianDay != -106749550580L) { // See above
julianDay = calculateJulianDay(!isGregorian, year_field);
millis = julianDayToMillis(julianDay);
}
// Do the time portion of the conversion.
int millisInDay = 0;
// Hours
// Don't normalize here; let overflow bump into the next period.
// This is consistent with how we handle other fields.
millisInDay += (packed_time >> 22) & 31;
millisInDay *= 60;
millisInDay += (packed_time >> 16) & 63; // now have minutes
millisInDay *= 60;
millisInDay += (packed_time >> 10) & 63; // now have seconds
millisInDay *= 1000;
millisInDay += packed_time & 1023; // now have millis
// Compute the time zone offset and DST offset. There are two potential
// ambiguities here. We'll assume a 2:00 am (wall time) switchover time
// for discussion purposes here.
// 1. The transition into DST. Here, a designated time of 2:00 am - 2:59 am
// can be in standard or in DST depending. However, 2:00 am is an invalid
// representation (the representation jumps from 1:59:59 am Std to 3:00:00 am DST).
// We assume standard time.
// 2. The transition out of DST. Here, a designated time of 1:00 am - 1:59 am
// can be in standard or DST. Both are valid representations (the rep
// jumps from 1:59:59 DST to 1:00:00 Std).
// Again, we assume standard time.
// We use the TimeZone object to get the zone offset
int zoneOffset = zone.getRawOffset();
// Now add date and millisInDay together, to make millis contain local wall
// millis, with no zone or DST adjustments
millis += millisInDay;
dstOffset = 0;
/* Normalize the millisInDay to 0..ONE_DAY-1. If the millis is out
* of range, then we must call timeToFields() to recompute our
* fields. */
int[] normalizedMillisInDay = new int[1];
floorDivide(millis, (int)ONE_DAY, normalizedMillisInDay);
// We need to have the month, the day, and the day of the week.
// Calling timeToFields will compute the MONTH and DATE fields.
//
// It's tempting to try to use DAY_OF_WEEK here, if it
// is set, but we CAN'T. Even if it's set, it might have
// been set wrong by the user. We should rely only on
// the Julian day number, which has been computed correctly
// using the disambiguation algorithm above. [LIU]
int dow = julianDayToDayOfWeek(julianDay);
// It's tempting to try to use DAY_OF_WEEK here, if it
// is set, but we CAN'T. Even if it's set, it might have
// been set wrong by the user. We should rely only on
// the Julian day number, which has been computed correctly
// using the disambiguation algorithm above. [LIU]
dstOffset = zone.getOffset(1,
packed_date >> 9,
(packed_date >> 5) & 15,
packed_date & 31,
dow,
normalizedMillisInDay[0]) -
zoneOffset;
dstSet = true;
// Note: Because we pass in wall millisInDay, rather than
// standard millisInDay, we interpret "1:00 am" on the day
// of cessation of DST as "1:00 am Std" (assuming the time
// of cessation is 2:00 am).
// Store our final computed GMT time, with timezone adjustments.
time = millis - zoneOffset - dstOffset;
| public boolean | equals(java.lang.Object obj)Compares this calendar to the specified object.
The result is true if and only if the argument is
not null and is a Calendar object that
represents the same calendar as this object.
if (this == obj)
return true;
if (!(obj instanceof Calendar))
return false;
Calendar that = (Calendar)obj;
return getTimeInMillis() == that.getTimeInMillis() && zone.equals(that.zone);
| private static final long | floorDivide(long numerator, long denominator)Divide two long integers, returning the floor of the quotient.
Unlike the built-in division, this is mathematically well-behaved.
E.g., -1/4 => 0
but floorDivide(-1,4) => -1.
// We do this computation in order to handle
// a numerator of Long.MIN_VALUE correctly
return (numerator >= 0) ?
numerator / denominator :
((numerator + 1) / denominator) - 1;
| private static final int | floorDivide(int numerator, int denominator)Divide two integers, returning the floor of the quotient.
Unlike the built-in division, this is mathematically well-behaved.
E.g., -1/4 => 0
but floorDivide(-1,4) => -1.
// We do this computation in order to handle
// a numerator of Integer.MIN_VALUE correctly
return (numerator >= 0) ?
numerator / denominator :
((numerator + 1) / denominator) - 1;
| private static final int | floorDivide(int numerator, int denominator, int[] remainder)Divide two integers, returning the floor of the quotient, and
the modulus remainder.
Unlike the built-in division, this is mathematically well-behaved.
E.g., -1/4 => 0 and -1%4 => -1,
but floorDivide(-1,4) => -1 with remainder[0] => 3.
if (numerator >= 0) {
remainder[0] = numerator % denominator;
return numerator / denominator;
}
int quotient = ((numerator + 1) / denominator) - 1;
remainder[0] = numerator - (quotient * denominator);
return quotient;
| private static final int | floorDivide(long numerator, int denominator, int[] remainder)Divide two integers, returning the floor of the quotient, and
the modulus remainder.
Unlike the built-in division, this is mathematically well-behaved.
E.g., -1/4 => 0 and -1%4 => -1,
but floorDivide(-1,4) => -1 with remainder[0] => 3.
if (numerator >= 0) {
remainder[0] = (int)(numerator % denominator);
return (int)(numerator / denominator);
}
int quotient = (int)(((numerator + 1) / denominator) - 1);
remainder[0] = (int)(numerator - (quotient * denominator));
return quotient;
| public final int | get(int field)Gets the value for a given time field.
switch (field) {
case YEAR: return packed_date >> 9;
case MONTH: return (packed_date >> 5) & 15;
case DATE: return packed_date & 31;
case DAY_OF_WEEK: {
if (day_field == 0) {
getTimeInMillis();
calculateFields();
}
return day_field;
}
case HOUR_OF_DAY: return packed_time >> 22;
case HOUR: {
int hr = (packed_time >> 22) % 12;
return hr == 0? 12 : hr;
}
case AM_PM: return (packed_time >> 22) < 12? AM: PM;
case MINUTE: return (packed_time >> 16) & 63;
case SECOND: return (packed_time >> 10) & 63;
case MILLISECOND: return packed_time & 1023;
}
throw new ArrayIndexOutOfBoundsException();
| public static synchronized java.util.Calendar | getInstance()Gets a calendar using the default time zone and default locale.
if (platform == null) {
/* Setup the platform name */
platform = "j2me";
/* See if there is an alternate protocol class root */
classRoot = System.getProperty("microedition.implpath");
if (classRoot == null) {
classRoot = "com.sun.cldc";
}
}
try {
/* Using the platform and protocol names lookup a class to implement the connection */
Class clazz = Class.forName(classRoot+".util."+platform+".CalendarImpl");
/* Construct a new instance */
return (Calendar)clazz.newInstance();
}
catch (Exception x) {}
return null;
| public static synchronized java.util.Calendar | getInstance(java.util.TimeZone zone)Gets a calendar using the specified time zone and default locale.
Calendar cal = getInstance();
cal.setTimeZone(zone);
return cal;
| public final java.util.Date | getTime()Gets this Calendar's current time.
if (date == null)
return date = new Date( getTimeInMillis() );
else {
synchronized (date) {
date.setTime( getTimeInMillis() );
return date;
}
}
| protected long | getTimeInMillis()Gets this Calendar's current time as a long expressed in milliseconds
after January 1, 1970, 0:00:00 GMT (the epoch).
if (!millisSet) {
calculateTime();
millisSet = true;
}
return time;
| public java.util.TimeZone | getTimeZone()Gets the time zone.
return zone;
| private static final int | julianDayToDayOfWeek(long julian)
// If julian is negative, then julian%7 will be negative, so we adjust
// accordingly. We add 1 because Julian day 0 is Monday.
int dayOfWeek = (int)((julian + 1) % 7);
return dayOfWeek + ((dayOfWeek < 0) ? (7 + SUNDAY) : SUNDAY);
| private static final long | julianDayToMillis(long julian)Converts Julian day to time as milliseconds.
return (julian - EPOCH_JULIAN_DAY) * ONE_DAY;
| private static final long | millisToJulianDay(long millis)Converts time as milliseconds to Julian day.
return EPOCH_JULIAN_DAY + floorDivide(millis, ONE_DAY);
| public final void | set(int field, int value)Sets the time field with the given value.
millisSet = false;
day_field = 0;
switch (field) {
case YEAR: // 16383 = (2 to the power 14) - 1
packed_date = (packed_date & 511) | (value << 9);
break;
case MONTH:
packed_date = (packed_date & (~(15<<5))) | ((value & 15) << 5);
break;
case DATE:
packed_date = (packed_date & (~31)) | (value & 31);
break;
case HOUR_OF_DAY:
value = value % 24;
packed_time = (packed_time & 4194303) | (value << 22);
hour_12hr = am_pm_12hr = -1;
break;
case HOUR: {
if (value > 12)
value = 12;
if (am_pm_12hr != -1) {
if (am_pm_12hr == PM) {
if (value != 12)
value += 12;
}
else if (value == 12)
value = 0;
hour_12hr = am_pm_12hr = -1;
}
else
hour_12hr = value;
packed_time = (packed_time & 4194303) | (value << 22);
break;
}
case AM_PM: {
if (hour_12hr != -1) {
if (value == PM) {
if (hour_12hr != 12)
hour_12hr += 12;
}
else if (hour_12hr == 12)
hour_12hr = 0;
packed_time = (packed_time & 4194303) | (hour_12hr << 22);
hour_12hr = am_pm_12hr = -1;
}
else
am_pm_12hr = value;
break;
}
case MINUTE:
packed_time = (packed_time & (~(63<<16))) | ((value & 63) << 16);
break;
case SECOND:
packed_time = (packed_time & (~(63<<10))) | ((value & 63) << 10);
break;
case MILLISECOND:
packed_time = (packed_time & (~1023)) | (value & 1023);
break;
default: throw new ArrayIndexOutOfBoundsException();
}
dstSet = false;
| public final void | setTime(java.util.Date date)Sets this Calendar's current time with the given Date.
Note: Calling setTime() with
Date(Long.MAX_VALUE) or Date(Long.MIN_VALUE)
may yield incorrect field values from get() .
setTimeInMillis( date.getTime() );
| protected void | setTimeInMillis(long millis)Sets this Calendar's current time from the given long value.
millisSet = true;
day_field = 0;
time = millis;
calculateFields();
| public void | setTimeZone(java.util.TimeZone value)Sets the time zone with the given time zone value.
zone = value;
getTimeInMillis();
calculateFields();
| private final void | timeToFields(long theTime)Convert the time as milliseconds to the date fields. Millis must be
given as local wall millis to get the correct local day. For example,
if it is 11:30 pm Standard, and DST is in effect, the correct DST millis
must be passed in to get the right date.
Fields that are completed by this method: YEAR, MONTH, DATE, DAY_OF_WEEK.
int dayOfYear, weekCount, year_field;
boolean isLeap;
// Compute the year, month, and day of month from the given millis
if (theTime >= gregorianCutover) {
// The Gregorian epoch day is zero for Monday January 1, year 1.
long gregorianEpochDay = millisToJulianDay(theTime) - JAN_1_1_JULIAN_DAY;
// Here we convert from the day number to the multiple radix
// representation. We use 400-year, 100-year, and 4-year cycles.
// For example, the 4-year cycle has 4 years + 1 leap day; giving
// 1461 == 365*4 + 1 days.
int[] rem = new int[1];
int n400 = floorDivide(gregorianEpochDay, 146097, rem); // 400-year cycle length
int n100 = floorDivide(rem[0], 36524, rem); // 100-year cycle length
int n4 = floorDivide(rem[0], 1461, rem); // 4-year cycle length
int n1 = floorDivide(rem[0], 365, rem);
year_field = 400*n400 + 100*n100 + 4*n4 + n1;
dayOfYear = rem[0]; // zero-based day of year
if (n100 == 4 || n1 == 4) dayOfYear = 365; // Dec 31 at end of 4- or 400-yr cycle
else ++year_field;
isLeap = ((year_field&0x3) == 0) && // equiv. to (year_field%4 == 0)
(year_field%100 != 0 || year_field%400 == 0);
// Gregorian day zero is a Monday
day_field = (int)((gregorianEpochDay+1) % 7);
}
else {
// The Julian epoch day (not the same as Julian Day)
// is zero on Saturday December 30, 0 (Gregorian).
long julianEpochDay = millisToJulianDay(theTime) - (JAN_1_1_JULIAN_DAY - 2);
year_field = (int) floorDivide(4*julianEpochDay + 1464, 1461);
// Compute the Julian calendar day number for January 1, year
long january1 = 365*(year_field-1) + floorDivide(year_field-1, 4);
dayOfYear = (int)(julianEpochDay - january1); // 0-based
// Julian leap years occurred historically every 4 years starting
// with 8 AD. Before 8 AD the spacing is irregular; every 3 years
// from 45 BC to 9 BC, and then none until 8 AD. However, we don't
// implement this historical detail; instead, we implement the
// computationally cleaner proleptic calendar, which assumes
// consistent 4-year cycles throughout time.
isLeap = ((year_field&0x3) == 0); // equiv. to (year_field%4 == 0)
// Julian calendar day zero is a Saturday
day_field = (int)((julianEpochDay-1) % 7);
}
// Common Julian/Gregorian calculation
int correction = 0;
int march1 = isLeap ? 60 : 59; // zero-based DOY for March 1
if (dayOfYear >= march1) correction = isLeap ? 1 : 2;
int month_field = (12 * (dayOfYear + correction) + 6) / 367; // zero-based month
int date_field = dayOfYear -
(isLeap ? LEAP_NUM_DAYS[month_field] : NUM_DAYS[month_field]) + 1; // one-based DOM
// Normalize day of week
day_field += (day_field < 0) ? (SUNDAY+7) : SUNDAY;
month_field += JANUARY; // 0-based
packed_date = year_field << 9;
packed_date |= (month_field & 15) << 5;
packed_date |= date_field & 31;
|
|