// time 是当前时间,单位是毫秒。
// 它是当前时间距离“January 1, 1970, 0:00:00 GMT”的差值。
protected long time;
Calendar就是根据 time 计算出 “Calendar的年、月、日、星期、时、分、秒”等等信息。
2. Calendar 各个字段的定义和初始化
Calendar 的“年、月、日、星期、时、分、秒”这些信息,一共是17个字段。 我们使用Calendar,无非是就是使用这17个字段。它们的定义如下: (字段0) public final static int ERA = 0; 说明:纪元。 取值:只能为0 或 1。0表示BC(“before Christ”,即公元前),1表示AD(拉丁语“Anno Domini”,即公元)。
(字段1) public final static int YEAR = 1; 说明:年。
(字段2) public final static int MONTH = 2; 说明:月 取值:可以为,JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER, UNDECIMBER。 其中第一个月是 JANUARY,它为 0。
(字段3) public final static int WEEK_OF_YEAR = 3; 说明:当前日期在本年中对应第几个星期。一年中第一个星期的值为 1。
(字段4) public final static int WEEK_OF_MONTH = 4; 说明:当前日期在本月中对应第几个星期。一个月中第一个星期的值为 1。
(字段5) public final static int DATE = 5; 说明:日。一个月中第一天的值为 1。
(字段5) public final static int DAY_OF_MONTH = 5; 说明:同“DATE”,表示“日”。
(字段6) public final static int DAY_OF_YEAR = 6; 说明:当前日期在本年中对应第几天。一年中第一天的值为 1。
(字段7) public final static int DAY_OF_WEEK = 7; 说明:星期几。 取值:可以为,SUNDAY、MONDAY、TUESDAY、WEDNESDAY、THURSDAY、FRIDAY 和 SATURDAY。 其中,SUNDAY为1,MONDAY为2,依次类推。
(字段8) public final static int DAY_OF_WEEK_IN_MONTH = 8; 说明:当前月中的第几个星期。 取值:DAY_OF_MONTH 1 到 7 总是对应于 DAY_OF_WEEK_IN_MONTH 1;8 到 14 总是对应于 DAY_OF_WEEK_IN_MONTH 2,依此类推。
(字段9) public final static int AM_PM = 9; 说明:上午 还是 下午 取值:可以是AM 或 PM。AM为0,表示上午;PM为1,表示下午。
(字段10) public final static int HOUR = 10; 说明:指示一天中的第几小时。 HOUR 用于 12 小时制时钟 (0 - 11)。中午和午夜用 0 表示,不用 12 表示。
(字段11) public final static int HOUR_OF_DAY = 11; 说明:指示一天中的第几小时。 HOUR_OF_DAY 用于 24 小时制时钟。例如,在 10:04:15.250 PM 这一时刻,HOUR_OF_DAY 为 22。
(字段12) public final static int MINUTE = 12; 说明:一小时中的第几分钟。 例如,在 10:04:15.250 PM这一时刻,MINUTE 为 4。
(字段13) public final static int SECOND = 13; 说明:一分钟中的第几秒。 例如,在 10:04:15.250 PM 这一时刻,SECOND 为 15。
(字段14) public final static int MILLISECOND = 14; 说明:一秒中的第几毫秒。 例如,在 10:04:15.250 PM 这一时刻,MILLISECOND 为 250。
(字段15) public final static int ZONE_OFFSET = 15; 说明:毫秒为单位指示距 GMT 的大致偏移量。
(字段16) public final static int DST_OFFSET = 16; 说明:毫秒为单位指示夏令时的偏移量。
public final static int FIELD_COUNT = 17;
这17个字段是保存在int数组中。定义如下:
// 保存这17个字段的数组
protected int fields[];
// 数组的定义函数
protected Calendar(TimeZone zone, Locale aLocale)
{
// 初始化“fields数组”
fields = new int[FIELD_COUNT];
isSet = new boolean[FIELD_COUNT];
stamp = new int[FIELD_COUNT];
1 protected void computeTime() {
2 // In non-lenient mode, perform brief checking of calendar
3 // fields which have been set externally. Through this
4 // checking, the field values are stored in originalFields[]
5 // to see if any of them are normalized later.
6 if (!isLenient()) {
7 if (originalFields == null) {
8 originalFields = new int[FIELD_COUNT];
9 }
10 for (int field = 0; field < FIELD_COUNT; field++) {
11 int value = internalGet(field);
12 if (isExternallySet(field)) {
13 // Quick validation for any out of range values
14 if (value < getMinimum(field) || value > getMaximum(field)) {
15 throw new IllegalArgumentException(getFieldName(field));
16 }
17 }
18 originalFields[field] = value;
19 }
20 }
21
22 // Let the super class determine which calendar fields to be
23 // used to calculate the time.
24 int fieldMask = selectFields();
25
26 // The year defaults to the epoch start. We don't check
27 // fieldMask for YEAR because YEAR is a mandatory field to
28 // determine the date.
29 int year = isSet(YEAR) ? internalGet(YEAR) : EPOCH_YEAR;
30
31 int era = internalGetEra();
32 if (era == BCE) {
33 year = 1 - year;
34 } else if (era != CE) {
35 // Even in lenient mode we disallow ERA values other than CE & BCE.
36 // (The same normalization rule as add()/roll() could be
37 // applied here in lenient mode. But this checking is kept
38 // unchanged for compatibility as of 1.5.)
39 throw new IllegalArgumentException("Invalid era");
40 }
41
42 // If year is 0 or negative, we need to set the ERA value later.
43 if (year <= 0 && !isSet(ERA)) {
44 fieldMask |= ERA_MASK;
45 setFieldsComputed(ERA_MASK);
46 }
47
48 // Calculate the time of day. We rely on the convention that
49 // an UNSET field has 0.
50 long timeOfDay = 0;
51 if (isFieldSet(fieldMask, HOUR_OF_DAY)) {
52 timeOfDay += (long) internalGet(HOUR_OF_DAY);
53 } else {
54 timeOfDay += internalGet(HOUR);
55 // The default value of AM_PM is 0 which designates AM.
56 if (isFieldSet(fieldMask, AM_PM)) {
57 timeOfDay += 12 * internalGet(AM_PM);
58 }
59 }
60 timeOfDay *= 60;
61 timeOfDay += internalGet(MINUTE);
62 timeOfDay *= 60;
63 timeOfDay += internalGet(SECOND);
64 timeOfDay *= 1000;
65 timeOfDay += internalGet(MILLISECOND);
66
67 // Convert the time of day to the number of days and the
68 // millisecond offset from midnight.
69 long fixedDate = timeOfDay / ONE_DAY;
70 timeOfDay %= ONE_DAY;
71 while (timeOfDay < 0) {
72 timeOfDay += ONE_DAY;
73 --fixedDate;
74 }
75
76 // Calculate the fixed date since January 1, 1 (Gregorian).
77 calculateFixedDate: {
78 long gfd, jfd;
79 if (year > gregorianCutoverYear && year > gregorianCutoverYearJulian) {
80 gfd = fixedDate + getFixedDate(gcal, year, fieldMask);
81 if (gfd >= gregorianCutoverDate) {
82 fixedDate = gfd;
83 break calculateFixedDate;
84 }
85 jfd = fixedDate + getFixedDate(getJulianCalendarSystem(), year, fieldMask);
86 } else if (year < gregorianCutoverYear && year < gregorianCutoverYearJulian) {
87 jfd = fixedDate + getFixedDate(getJulianCalendarSystem(), year, fieldMask);
88 if (jfd < gregorianCutoverDate) {
89 fixedDate = jfd;
90 break calculateFixedDate;
91 }
92 gfd = fixedDate + getFixedDate(gcal, year, fieldMask);
93 } else {
94 gfd = fixedDate + getFixedDate(gcal, year, fieldMask);
95 jfd = fixedDate + getFixedDate(getJulianCalendarSystem(), year, fieldMask);
96 }
97 // Now we have to determine which calendar date it is.
98 if (gfd >= gregorianCutoverDate) {
99 if (jfd >= gregorianCutoverDate) {
100 fixedDate = gfd;
101 } else {
102 // The date is in an "overlapping" period. No way
103 // to disambiguate it. Determine it using the
104 // previous date calculation.
105 if (calsys == gcal || calsys == null) {
106 fixedDate = gfd;
107 } else {
108 fixedDate = jfd;
109 }
110 }
111 } else {
112 if (jfd < gregorianCutoverDate) {
113 fixedDate = jfd;
114 } else {
115 // The date is in a "missing" period.
116 if (!isLenient()) {
117 throw new IllegalArgumentException("the specified date doesn't exist");
118 }
119 // Take the Julian date for compatibility, which
120 // will produce a Gregorian date.
121 fixedDate = jfd;
122 }
123 }
124 }
125
126 // millis represents local wall-clock time in milliseconds.
127 long millis = (fixedDate - EPOCH_OFFSET) * ONE_DAY + timeOfDay;
128
129 // Compute the time zone offset and DST offset. There are two potential
130 // ambiguities here. We'll assume a 2:00 am (wall time) switchover time
131 // for discussion purposes here.
132 // 1. The transition into DST. Here, a designated time of 2:00 am - 2:59 am
133 // can be in standard or in DST depending. However, 2:00 am is an invalid
134 // representation (the representation jumps from 1:59:59 am Std to 3:00:00 am DST).
135 // We assume standard time.
136 // 2. The transition out of DST. Here, a designated time of 1:00 am - 1:59 am
137 // can be in standard or DST. Both are valid representations (the rep
138 // jumps from 1:59:59 DST to 1:00:00 Std).
139 // Again, we assume standard time.
140 // We use the TimeZone object, unless the user has explicitly set the ZONE_OFFSET
141 // or DST_OFFSET fields; then we use those fields.
142 TimeZone zone = getZone();
143 if (zoneOffsets == null) {
144 zoneOffsets = new int[2];
145 }
146 int tzMask = fieldMask & (ZONE_OFFSET_MASK|DST_OFFSET_MASK);
147 if (tzMask != (ZONE_OFFSET_MASK|DST_OFFSET_MASK)) {
148 if (zone instanceof ZoneInfo) {
149 ((ZoneInfo)zone).getOffsetsByWall(millis, zoneOffsets);
150 } else {
151 int gmtOffset = isFieldSet(fieldMask, ZONE_OFFSET) ?
152 internalGet(ZONE_OFFSET) : zone.getRawOffset();
153 zone.getOffsets(millis - gmtOffset, zoneOffsets);
154 }
155 }
156 if (tzMask != 0) {
157 if (isFieldSet(tzMask, ZONE_OFFSET)) {
158 zoneOffsets[0] = internalGet(ZONE_OFFSET);
159 }
160 if (isFieldSet(tzMask, DST_OFFSET)) {
161 zoneOffsets[1] = internalGet(DST_OFFSET);
162 }
163 }
164
165 // Adjust the time zone offset values to get the UTC time.
166 millis -= zoneOffsets[0] + zoneOffsets[1];
167
168 // Set this calendar's time in milliseconds
169 time = millis;
170
171 int mask = computeFields(fieldMask | getSetStateFields(), tzMask);
172
173 if (!isLenient()) {
174 for (int field = 0; field < FIELD_COUNT; field++) {
175 if (!isExternallySet(field)) {
176 continue;
177 }
178 if (originalFields[field] != internalGet(field)) {
179 // Restore the original field values
180 System.arraycopy(originalFields, 0, fields, 0, fields.length);
181 throw new IllegalArgumentException(getFieldName(field));
182 }
183 }
184 }
185 setFieldsNormalized(mask);
186 }
View Code
下面,我们看看internalGet(field)的定义。如下:
protected final int internalGet(int field) {
return fields[field];
}
// 设置“年月日”
final void set(int year, int month, int day)
// 设置“年月日时分”
final void set(int year, int month, int day, int hourOfDay, int minute, int second)
// 设置“年月日时分秒”
final void set(int year, int month, int day, int hourOfDay, int minute)
// 获取Calendar对应的日期
final Date getTime()
// 设置Calendar为date
final void setTime(Date date)
// 获取Calendar对应的时区
TimeZone getTimeZone()
// 设置Calendar对应的时区
void setTimeZone(TimeZone timezone)
// 获取Calendar对应的milliscondes值,就是“Calendar当前日期”距离“1970-01-01 0:00:00 GMT”的毫秒数
long getTimeInMillis()
// 设置Calendar对应的milliscondes值
void setTimeInMillis(long milliseconds)