39 |
|
|
40 |
package java.util; |
package java.util; |
41 |
|
|
42 |
|
|
43 |
/** |
/** |
44 |
* <p> |
* <p> |
45 |
* This class represents the Gregorian calendar, that is used in most |
* This class represents the Gregorian calendar, that is used in most |
47 |
* for dates smaller than the date of the change to the Gregorian calendar. |
* for dates smaller than the date of the change to the Gregorian calendar. |
48 |
* The Gregorian calendar differs from the Julian calendar by a different |
* The Gregorian calendar differs from the Julian calendar by a different |
49 |
* leap year rule (no leap year every 100 years, except if year is divisible |
* leap year rule (no leap year every 100 years, except if year is divisible |
50 |
* by 400). |
* by 400). |
51 |
* </p> |
* </p> |
52 |
* <p> |
* <p> |
53 |
* This change date is different from country to country, and can be changed with |
* This change date is different from country to country, and can be changed with |
137 |
* Constant representing the era BC (Before Christ). |
* Constant representing the era BC (Before Christ). |
138 |
*/ |
*/ |
139 |
public static final int BC = 0; |
public static final int BC = 0; |
140 |
|
|
141 |
/** |
/** |
142 |
* Constant representing the era AD (Anno Domini). |
* Constant representing the era AD (Anno Domini). |
143 |
*/ |
*/ |
172 |
* @param locale the locale in use for this calendar. |
* @param locale the locale in use for this calendar. |
173 |
* @return A resource bundle for the calendar for the specified locale. |
* @return A resource bundle for the calendar for the specified locale. |
174 |
*/ |
*/ |
175 |
private static ResourceBundle getBundle(Locale locale) |
private static ResourceBundle getBundle(Locale locale) |
176 |
{ |
{ |
177 |
return ResourceBundle.getBundle(bundleName, locale, |
return ResourceBundle.getBundle(bundleName, locale, |
178 |
ClassLoader.getSystemClassLoader()); |
ClassLoader.getSystemClassLoader()); |
179 |
} |
} |
180 |
|
|
181 |
/** |
/** |
182 |
* Constructs a new GregorianCalender representing the current |
* Constructs a new GregorianCalender representing the current |
183 |
* time, using the default time zone and the default locale. |
* time, using the default time zone and the default locale. |
184 |
*/ |
*/ |
185 |
public GregorianCalendar() |
public GregorianCalendar() |
186 |
{ |
{ |
187 |
this(TimeZone.getDefault(), Locale.getDefault()); |
this(TimeZone.getDefault(), Locale.getDefault()); |
188 |
} |
} |
189 |
|
|
190 |
/** |
/** |
191 |
* Constructs a new GregorianCalender representing the current |
* Constructs a new GregorianCalender representing the current |
192 |
* time, using the specified time zone and the default locale. |
* time, using the specified time zone and the default locale. |
193 |
* |
* |
194 |
* @param zone a time zone. |
* @param zone a time zone. |
195 |
*/ |
*/ |
196 |
public GregorianCalendar(TimeZone zone) |
public GregorianCalendar(TimeZone zone) |
197 |
{ |
{ |
198 |
this(zone, Locale.getDefault()); |
this(zone, Locale.getDefault()); |
199 |
} |
} |
200 |
|
|
201 |
/** |
/** |
202 |
* Constructs a new GregorianCalender representing the current |
* Constructs a new GregorianCalender representing the current |
203 |
* time, using the default time zone and the specified locale. |
* time, using the default time zone and the specified locale. |
204 |
* |
* |
205 |
* @param locale a locale. |
* @param locale a locale. |
206 |
*/ |
*/ |
207 |
public GregorianCalendar(Locale locale) |
public GregorianCalendar(Locale locale) |
213 |
* Constructs a new GregorianCalender representing the current |
* Constructs a new GregorianCalender representing the current |
214 |
* time with the given time zone and the given locale. |
* time with the given time zone and the given locale. |
215 |
* |
* |
216 |
* @param zone a time zone. |
* @param zone a time zone. |
217 |
* @param locale a locale. |
* @param locale a locale. |
218 |
*/ |
*/ |
219 |
public GregorianCalendar(TimeZone zone, Locale locale) |
public GregorianCalendar(TimeZone zone, Locale locale) |
220 |
{ |
{ |
225 |
|
|
226 |
/** |
/** |
227 |
* Common constructor that all constructors should call. |
* Common constructor that all constructors should call. |
228 |
* @param zone a time zone. |
* @param zone a time zone. |
229 |
* @param locale a locale. |
* @param locale a locale. |
230 |
* @param unused unused parameter to make the signature differ from |
* @param unused unused parameter to make the signature differ from |
231 |
* the public constructor (TimeZone, Locale). |
* the public constructor (TimeZone, Locale). |
232 |
*/ |
*/ |
278 |
* @param minute corresponds to the MINUTE time field. |
* @param minute corresponds to the MINUTE time field. |
279 |
* @param second corresponds to the SECOND time field. |
* @param second corresponds to the SECOND time field. |
280 |
*/ |
*/ |
281 |
public GregorianCalendar(int year, int month, int day, |
public GregorianCalendar(int year, int month, int day, int hour, int minute, |
282 |
int hour, int minute, int second) |
int second) |
283 |
{ |
{ |
284 |
this(TimeZone.getDefault(), Locale.getDefault(), false); |
this(TimeZone.getDefault(), Locale.getDefault(), false); |
285 |
set(year, month, day, hour, minute, second); |
set(year, month, day, hour, minute, second); |
322 |
* </p> |
* </p> |
323 |
* |
* |
324 |
* @param year a year (use a negative value for BC). |
* @param year a year (use a negative value for BC). |
325 |
* @return true, if the given year is a leap year, false otherwise. |
* @return true, if the given year is a leap year, false otherwise. |
326 |
*/ |
*/ |
327 |
public boolean isLeapYear(int year) |
public boolean isLeapYear(int year) |
328 |
{ |
{ |
333 |
// compute the linear day of the 29. February of that year. |
// compute the linear day of the 29. February of that year. |
334 |
// The 13 is the number of days, that were omitted in the Gregorian |
// The 13 is the number of days, that were omitted in the Gregorian |
335 |
// Calender until the epoch. |
// Calender until the epoch. |
336 |
int julianDay = (((year-1) * (365*4+1)) >> 2) + (31+29 - |
int julianDay = (((year - 1) * (365 * 4 + 1)) >> 2) |
337 |
(((1970-1) * (365*4+1)) / 4 + 1 - 13)); |
+ (31 + 29 - (((1970 - 1) * (365 * 4 + 1)) / 4 + 1 - 13)); |
338 |
|
|
339 |
// If that day is smaller than the gregorianChange the julian |
// If that day is smaller than the gregorianChange the julian |
340 |
// rule applies: This is a leap year since it is divisible by 4. |
// rule applies: This is a leap year since it is divisible by 4. |
341 |
if (julianDay * (24 * 60 * 60 * 1000L) < gregorianCutover) |
if (julianDay * (24 * 60 * 60 * 1000L) < gregorianCutover) |
353 |
* @param year the year of the date. |
* @param year the year of the date. |
354 |
* @param dayOfYear the day of year of the date; 1 based. |
* @param dayOfYear the day of year of the date; 1 based. |
355 |
* @param millis the millisecond in that day. |
* @param millis the millisecond in that day. |
356 |
* @return the days since the epoch, may be negative. |
* @return the days since the epoch, may be negative. |
357 |
*/ |
*/ |
358 |
private long getLinearTime(int year, int dayOfYear, int millis) |
private long getLinearTime(int year, int dayOfYear, int millis) |
359 |
{ |
{ |
361 |
// Calendar until the epoch. |
// Calendar until the epoch. |
362 |
// We shift right by 2 instead of dividing by 4, to get correct |
// We shift right by 2 instead of dividing by 4, to get correct |
363 |
// results for negative years (and this is even more efficient). |
// results for negative years (and this is even more efficient). |
364 |
int julianDay = ((year * (365 * 4 + 1)) >> 2) + dayOfYear - |
int julianDay = ((year * (365 * 4 + 1)) >> 2) + dayOfYear |
365 |
((1970 * (365 * 4 + 1)) / 4 + 1 - 13); |
- ((1970 * (365 * 4 + 1)) / 4 + 1 - 13); |
366 |
long time = julianDay * (24 * 60 * 60 * 1000L) + millis; |
long time = julianDay * (24 * 60 * 60 * 1000L) + millis; |
367 |
|
|
368 |
if (time >= gregorianCutover) |
if (time >= gregorianCutover) |
379 |
// And on and after the leap day, the leap day has already been |
// And on and after the leap day, the leap day has already been |
380 |
// included in dayOfYear. |
// included in dayOfYear. |
381 |
int gregOffset = (year / 400) - (year / 100) + 2; |
int gregOffset = (year / 400) - (year / 100) + 2; |
382 |
if (isLeapYear (year, true)) |
if (isLeapYear(year, true)) |
383 |
--gregOffset; |
--gregOffset; |
384 |
time += gregOffset * (24 * 60 * 60 * 1000L); |
time += gregOffset * (24 * 60 * 60 * 1000L); |
385 |
} |
} |
396 |
*/ |
*/ |
397 |
private int getWeekDay(int year, int dayOfYear) |
private int getWeekDay(int year, int dayOfYear) |
398 |
{ |
{ |
399 |
int day = |
int day = (int) (getLinearTime(year, dayOfYear, 0) / (24 * 60 * 60 * 1000L)); |
|
(int) (getLinearTime(year, dayOfYear, 0) / (24 * 60 * 60 * 1000L)); |
|
400 |
|
|
401 |
// The epoch was a thursday. |
// The epoch was a thursday. |
402 |
int weekday = (day + THURSDAY) % 7; |
int weekday = (day + THURSDAY) % 7; |
407 |
|
|
408 |
/** |
/** |
409 |
* <p> |
* <p> |
410 |
* Calculate the dayOfYear from the fields array. |
* Calculate the dayOfYear from the fields array. |
411 |
* The relativeDays is used, to account for weeks that begin before |
* The relativeDays is used, to account for weeks that begin before |
412 |
* the Gregorian change and end after it. |
* the Gregorian change and end after it. |
413 |
* </p> |
* </p> |
416 |
* should use the Gregorian calendar or the Julian calendar, in order |
* should use the Gregorian calendar or the Julian calendar, in order |
417 |
* to handle the change year. The second is a relative day after the given |
* to handle the change year. The second is a relative day after the given |
418 |
* day. This is necessary for week calculation in the year in |
* day. This is necessary for week calculation in the year in |
419 |
* which the Gregorian change occurs. |
* which the Gregorian change occurs. |
420 |
* </p> |
* </p> |
421 |
* |
* |
422 |
* @param year the year, negative for BC. |
* @param year the year, negative for BC. |
423 |
* @return an array of two integer values, the first containing a reference |
* @return an array of two integer values, the first containing a reference |
424 |
* day in the current year, the second a relative count since this reference |
* day in the current year, the second a relative count since this reference |
425 |
* day. |
* day. |
426 |
*/ |
*/ |
427 |
private int[] getDayOfYear(int year) |
private int[] getDayOfYear(int year) |
428 |
{ |
{ |
431 |
int dayOfYear; |
int dayOfYear; |
432 |
if (fields[MONTH] > FEBRUARY) |
if (fields[MONTH] > FEBRUARY) |
433 |
{ |
{ |
|
|
|
434 |
// The months after February are regular: |
// The months after February are regular: |
435 |
// 9 is an offset found by try and error. |
// 9 is an offset found by try and error. |
436 |
dayOfYear = (fields[MONTH] * (31 + 30 + 31 + 30 + 31) - 9) / 5; |
dayOfYear = (fields[MONTH] * (31 + 30 + 31 + 30 + 31) - 9) / 5; |
438 |
dayOfYear++; |
dayOfYear++; |
439 |
} |
} |
440 |
else |
else |
441 |
dayOfYear = 31 * fields[MONTH]; |
dayOfYear = 31 * fields[MONTH]; |
442 |
|
|
443 |
if (isSet[DAY_OF_MONTH]) |
if (isSet[DAY_OF_MONTH]) |
444 |
{ |
return new int[] { dayOfYear + fields[DAY_OF_MONTH], 0 }; |
|
return new int[] |
|
|
{ |
|
|
dayOfYear + fields[DAY_OF_MONTH], 0}; |
|
|
} |
|
445 |
if (isSet[WEEK_OF_MONTH] && isSet[DAY_OF_WEEK]) |
if (isSet[WEEK_OF_MONTH] && isSet[DAY_OF_WEEK]) |
446 |
{ |
{ |
447 |
// the weekday of the first day in that month is: |
// the weekday of the first day in that month is: |
448 |
int weekday = getWeekDay(year, ++dayOfYear); |
int weekday = getWeekDay(year, ++dayOfYear); |
449 |
|
|
450 |
return new int[] |
return new int[] |
451 |
{ |
{ |
452 |
dayOfYear, |
dayOfYear, |
453 |
// the day of week in the first week |
// the day of week in the first week |
454 |
// (weeks starting on sunday) is: |
// (weeks starting on sunday) is: |
455 |
fields[DAY_OF_WEEK] - weekday + |
fields[DAY_OF_WEEK] - weekday |
456 |
// Now jump to the right week and correct the possible |
+ // Now jump to the right week and correct the possible |
457 |
// error made by assuming sunday is the first week day. |
// error made by assuming sunday is the first week day. |
458 |
7 * (fields[WEEK_OF_MONTH] |
7 * (fields[WEEK_OF_MONTH] |
459 |
+ (fields[DAY_OF_WEEK] < getFirstDayOfWeek()? 0 : -1) |
+ (fields[DAY_OF_WEEK] < getFirstDayOfWeek() ? 0 : -1) |
460 |
+ (weekday < getFirstDayOfWeek()? -1 : 0))}; |
+ (weekday < getFirstDayOfWeek() ? -1 : 0)) |
461 |
|
}; |
462 |
} |
} |
463 |
if (isSet[DAY_OF_WEEK] && isSet[DAY_OF_WEEK_IN_MONTH]) |
if (isSet[DAY_OF_WEEK] && isSet[DAY_OF_WEEK_IN_MONTH]) |
464 |
{ |
{ |
465 |
// the weekday of the first day in that month is: |
// the weekday of the first day in that month is: |
466 |
int weekday = getWeekDay(year, ++dayOfYear); |
int weekday = getWeekDay(year, ++dayOfYear); |
467 |
return new int[] { |
return new int[] |
468 |
dayOfYear, |
{ |
469 |
fields[DAY_OF_WEEK] - weekday + |
dayOfYear, |
470 |
7 * (fields[DAY_OF_WEEK_IN_MONTH] |
fields[DAY_OF_WEEK] - weekday |
471 |
+ (fields[DAY_OF_WEEK] < weekday ? 0 : -1))}; |
+ 7 * (fields[DAY_OF_WEEK_IN_MONTH] |
472 |
|
+ (fields[DAY_OF_WEEK] < weekday ? 0 : -1)) |
473 |
|
}; |
474 |
} |
} |
475 |
} |
} |
476 |
|
|
477 |
// MONTH + something did not succeed. |
// MONTH + something did not succeed. |
478 |
if (isSet[DAY_OF_YEAR]) |
if (isSet[DAY_OF_YEAR]) |
479 |
{ |
return new int[] { 0, fields[DAY_OF_YEAR] }; |
480 |
return new int[] {0, fields[DAY_OF_YEAR]}; |
|
|
} |
|
|
|
|
481 |
if (isSet[DAY_OF_WEEK] && isSet[WEEK_OF_YEAR]) |
if (isSet[DAY_OF_WEEK] && isSet[WEEK_OF_YEAR]) |
482 |
{ |
{ |
483 |
int dayOfYear = getMinimalDaysInFirstWeek(); |
int dayOfYear = getMinimalDaysInFirstWeek(); |
484 |
|
|
485 |
// the weekday of the day, that begins the first week |
// the weekday of the day, that begins the first week |
486 |
// in that year is: |
// in that year is: |
487 |
int weekday = getWeekDay(year, dayOfYear); |
int weekday = getWeekDay(year, dayOfYear); |
488 |
|
|
489 |
return new int[] { |
return new int[] |
490 |
dayOfYear, |
{ |
491 |
// the day of week in the first week |
dayOfYear, |
492 |
// (weeks starting on sunday) is: |
|
493 |
fields[DAY_OF_WEEK] - weekday |
// the day of week in the first week |
494 |
// Now jump to the right week and correct the possible |
// (weeks starting on sunday) is: |
495 |
// error made by assuming sunday is the first week day. |
fields[DAY_OF_WEEK] - weekday |
496 |
+ 7 * (fields[WEEK_OF_YEAR] |
// Now jump to the right week and correct the possible |
497 |
+ (fields[DAY_OF_WEEK] < getFirstDayOfWeek()? 0 : -1) |
// error made by assuming sunday is the first week day. |
498 |
+ (weekday < getFirstDayOfWeek()? -1 : 0))}; |
+ 7 * (fields[WEEK_OF_YEAR] |
499 |
|
+ (fields[DAY_OF_WEEK] < getFirstDayOfWeek() ? 0 : -1) |
500 |
|
+ (weekday < getFirstDayOfWeek() ? -1 : 0)) |
501 |
|
}; |
502 |
} |
} |
503 |
|
|
504 |
// As last resort return Jan, 1st. |
// As last resort return Jan, 1st. |
505 |
return new int[] {1, 0}; |
return new int[] { 1, 0 }; |
506 |
} |
} |
507 |
|
|
508 |
/** |
/** |
509 |
* Converts the time field values (<code>fields</code>) to |
* Converts the time field values (<code>fields</code>) to |
510 |
* milliseconds since the epoch UTC (<code>time</code>). |
* milliseconds since the epoch UTC (<code>time</code>). |
511 |
* |
* |
512 |
* @throws IllegalArgumentException if any calendar fields |
* @throws IllegalArgumentException if any calendar fields |
513 |
* are invalid. |
* are invalid. |
542 |
else if (isSet[HOUR]) |
else if (isSet[HOUR]) |
543 |
{ |
{ |
544 |
hour = fields[HOUR]; |
hour = fields[HOUR]; |
545 |
if (isSet[AM_PM] && fields[AM_PM] == PM) |
if (isSet[AM_PM] && fields[AM_PM] == PM) |
546 |
if (hour != 12) /* not Noon */ |
if (hour != 12) /* not Noon */ |
547 |
hour += 12; |
hour += 12; |
548 |
/* Fix the problem of the status of 12:00 AM (midnight). */ |
/* Fix the problem of the status of 12:00 AM (midnight). */ |
549 |
if (isSet[AM_PM] && fields[AM_PM] == AM && hour == 12) |
if (isSet[AM_PM] && fields[AM_PM] == AM && hour == 12) |
550 |
hour = 0; |
hour = 0; |
559 |
{ |
{ |
560 |
// prevent overflow |
// prevent overflow |
561 |
long allMillis = (((hour * 60L) + minute) * 60L + second) * 1000L |
long allMillis = (((hour * 60L) + minute) * 60L + second) * 1000L |
562 |
+ millis; |
+ millis; |
563 |
daysOfYear[1] += allMillis / (24 * 60 * 60 * 1000L); |
daysOfYear[1] += allMillis / (24 * 60 * 60 * 1000L); |
564 |
millisInDay = (int) (allMillis % (24 * 60 * 60 * 1000L)); |
millisInDay = (int) (allMillis % (24 * 60 * 60 * 1000L)); |
565 |
} |
} |
566 |
else |
else |
567 |
{ |
{ |
568 |
if (hour < 0 || hour >= 24 || minute < 0 || minute > 59 |
if (hour < 0 || hour >= 24 || minute < 0 || minute > 59 || second < 0 |
569 |
|| second < 0 || second > 59 || millis < 0 || millis >= 1000) |
|| second > 59 || millis < 0 || millis >= 1000) |
570 |
throw new IllegalArgumentException(); |
throw new IllegalArgumentException(); |
571 |
millisInDay = (((hour * 60) + minute) * 60 + second) * 1000 + millis; |
millisInDay = (((hour * 60) + minute) * 60 + second) * 1000 + millis; |
572 |
} |
} |
576 |
// get right behaviour when jumping over the gregorianCutover. |
// get right behaviour when jumping over the gregorianCutover. |
577 |
time += daysOfYear[1] * (24 * 60 * 60 * 1000L); |
time += daysOfYear[1] * (24 * 60 * 60 * 1000L); |
578 |
|
|
|
|
|
579 |
TimeZone zone = getTimeZone(); |
TimeZone zone = getTimeZone(); |
580 |
int rawOffset = isSet[ZONE_OFFSET] |
int rawOffset = isSet[ZONE_OFFSET] ? fields[ZONE_OFFSET] |
581 |
? fields[ZONE_OFFSET] : zone.getRawOffset(); |
: zone.getRawOffset(); |
582 |
|
|
583 |
int day = (int) (time / (24 * 60 * 60 * 1000L)); |
int day = (int) (time / (24 * 60 * 60 * 1000L)); |
584 |
millisInDay = (int) (time % (24 * 60 * 60 * 1000L)); |
millisInDay = (int) (time % (24 * 60 * 60 * 1000L)); |
594 |
int month = f[MONTH]; |
int month = f[MONTH]; |
595 |
day = f[DAY_OF_MONTH]; |
day = f[DAY_OF_MONTH]; |
596 |
int weekday = f[DAY_OF_WEEK]; |
int weekday = f[DAY_OF_WEEK]; |
597 |
int dstOffset = isSet[DST_OFFSET] |
int dstOffset = isSet[DST_OFFSET] ? fields[DST_OFFSET] |
598 |
? fields[DST_OFFSET] : (zone.getOffset((year < 0) ? BC : AD, |
: (zone.getOffset((year < 0) ? BC : AD, |
599 |
(year < 0) ? 1 - year : year, |
(year < 0) ? 1 - year |
600 |
month, day, weekday, millisInDay) |
: year, |
601 |
- zone.getRawOffset()); |
month, day, weekday, |
602 |
|
millisInDay) |
603 |
|
- zone.getRawOffset()); |
604 |
time -= rawOffset + dstOffset; |
time -= rawOffset + dstOffset; |
605 |
isTimeSet = true; |
isTimeSet = true; |
606 |
} |
} |
607 |
|
|
608 |
/** |
/** |
609 |
* <p> |
* <p> |
610 |
* Determines if the given year is a leap year. |
* Determines if the given year is a leap year. |
611 |
* </p> |
* </p> |
612 |
* <p> |
* <p> |
613 |
* To specify a year in the BC era, use a negative value calculated |
* To specify a year in the BC era, use a negative value calculated |
617 |
* |
* |
618 |
* @param year a year (use a negative value for BC). |
* @param year a year (use a negative value for BC). |
619 |
* @param gregorian if true, use the gregorian leap year rule. |
* @param gregorian if true, use the gregorian leap year rule. |
620 |
* @return true, if the given year is a leap year, false otherwise. |
* @return true, if the given year is a leap year, false otherwise. |
621 |
*/ |
*/ |
622 |
private boolean isLeapYear(int year, boolean gregorian) |
private boolean isLeapYear(int year, boolean gregorian) |
623 |
{ |
{ |
625 |
// Only years divisible by 4 can be leap years |
// Only years divisible by 4 can be leap years |
626 |
return false; |
return false; |
627 |
|
|
628 |
if (!gregorian) |
if (! gregorian) |
629 |
return true; |
return true; |
630 |
|
|
631 |
// We rely on AD area here. |
// We rely on AD area here. |
636 |
* Get the linear day in days since the epoch, using the |
* Get the linear day in days since the epoch, using the |
637 |
* Julian or Gregorian calendar as specified. If you specify a |
* Julian or Gregorian calendar as specified. If you specify a |
638 |
* nonpositive year it is interpreted as BC as following: 0 is 1 |
* nonpositive year it is interpreted as BC as following: 0 is 1 |
639 |
* BC, -1 is 2 BC and so on. |
* BC, -1 is 2 BC and so on. |
640 |
* |
* |
641 |
* @param year the year of the date. |
* @param year the year of the date. |
642 |
* @param dayOfYear the day of year of the date; 1 based. |
* @param dayOfYear the day of year of the date; 1 based. |
643 |
* @param gregorian <code>true</code>, if we should use the Gregorian rules. |
* @param gregorian <code>true</code>, if we should use the Gregorian rules. |
644 |
* @return the days since the epoch, may be negative. |
* @return the days since the epoch, may be negative. |
645 |
*/ |
*/ |
646 |
private long getLinearDay(int year, int dayOfYear, boolean gregorian) |
private long getLinearDay(int year, int dayOfYear, boolean gregorian) |
647 |
{ |
{ |
649 |
// Calender until the epoch. |
// Calender until the epoch. |
650 |
// We shift right by 2 instead of dividing by 4, to get correct |
// We shift right by 2 instead of dividing by 4, to get correct |
651 |
// results for negative years (and this is even more efficient). |
// results for negative years (and this is even more efficient). |
652 |
long julianDay = ((year * (365L * 4 + 1)) >> 2) + dayOfYear - |
long julianDay = ((year * (365L * 4 + 1)) >> 2) + dayOfYear |
653 |
((1970 * (365 * 4 + 1)) / 4 + 1 - 13); |
- ((1970 * (365 * 4 + 1)) / 4 + 1 - 13); |
654 |
|
|
655 |
if (gregorian) |
if (gregorian) |
656 |
{ |
{ |
664 |
// The additional leap year factor accounts for the fact that |
// The additional leap year factor accounts for the fact that |
665 |
// a leap day is not seen on Jan 1 of the leap year. |
// a leap day is not seen on Jan 1 of the leap year. |
666 |
int gregOffset = (year / 400) - (year / 100) + 2; |
int gregOffset = (year / 400) - (year / 100) + 2; |
667 |
if (isLeapYear (year, true) && dayOfYear < 31 + 29) |
if (isLeapYear(year, true) && dayOfYear < 31 + 29) |
668 |
--gregOffset; |
--gregOffset; |
669 |
julianDay += gregOffset; |
julianDay += gregOffset; |
670 |
} |
} |
676 |
* day_of_year, day_of_month, day_of_week, and writes the result |
* day_of_year, day_of_month, day_of_week, and writes the result |
677 |
* into the fields array. |
* into the fields array. |
678 |
* |
* |
679 |
* @param day the linear day. |
* @param day the linear day. |
680 |
* @param gregorian true, if we should use Gregorian rules. |
* @param gregorian true, if we should use Gregorian rules. |
681 |
*/ |
*/ |
682 |
private void calculateDay(int[] fields, long day, boolean gregorian) |
private void calculateDay(int[] fields, long day, boolean gregorian) |
683 |
{ |
{ |
684 |
// the epoch is a Thursday. |
// the epoch is a Thursday. |
685 |
int weekday = (int)(day + THURSDAY) % 7; |
int weekday = (int) (day + THURSDAY) % 7; |
686 |
if (weekday <= 0) |
if (weekday <= 0) |
687 |
weekday += 7; |
weekday += 7; |
688 |
fields[DAY_OF_WEEK] = weekday; |
fields[DAY_OF_WEEK] = weekday; |
689 |
|
|
690 |
// get a first approximation of the year. This may be one |
// get a first approximation of the year. This may be one |
691 |
// year too big. |
// year too big. |
692 |
int year = 1970 + (int)(gregorian |
int year = 1970 |
693 |
? ((day - 100) * 400) / (365 * 400 + 100 - 4 + 1) |
+ (int) (gregorian |
694 |
: ((day - 100) * 4) / (365 * 4 + 1)); |
? ((day - 100) * 400) / (365 * 400 + 100 - 4 + 1) |
695 |
|
: ((day - 100) * 4) / (365 * 4 + 1)); |
696 |
if (day >= 0) |
if (day >= 0) |
697 |
year++; |
year++; |
698 |
|
|
705 |
firstDayOfYear = getLinearDay(year, 1, gregorian); |
firstDayOfYear = getLinearDay(year, 1, gregorian); |
706 |
} |
} |
707 |
|
|
708 |
day -= firstDayOfYear - 1; // day of year, one based. |
day -= firstDayOfYear - 1; // day of year, one based. |
709 |
|
|
710 |
fields[DAY_OF_YEAR] = (int)day; |
fields[DAY_OF_YEAR] = (int) day; |
711 |
if (year <= 0) |
if (year <= 0) |
712 |
{ |
{ |
713 |
fields[ERA] = BC; |
fields[ERA] = BC; |
722 |
int leapday = isLeapYear(year, gregorian) ? 1 : 0; |
int leapday = isLeapYear(year, gregorian) ? 1 : 0; |
723 |
if (day <= 31 + 28 + leapday) |
if (day <= 31 + 28 + leapday) |
724 |
{ |
{ |
725 |
fields[MONTH] = (int)day / 32; // 31->JANUARY, 32->FEBRUARY |
fields[MONTH] = (int) day / 32; // 31->JANUARY, 32->FEBRUARY |
726 |
fields[DAY_OF_MONTH] = (int)day - 31 * fields[MONTH]; |
fields[DAY_OF_MONTH] = (int) day - 31 * fields[MONTH]; |
727 |
} |
} |
728 |
else |
else |
729 |
{ |
{ |
730 |
// A few more magic formulas |
// A few more magic formulas |
731 |
int scaledDay = ((int)day - leapday) * 5 + 8; |
int scaledDay = ((int) day - leapday) * 5 + 8; |
732 |
fields[MONTH] = scaledDay / (31 + 30 + 31 + 30 + 31); |
fields[MONTH] = scaledDay / (31 + 30 + 31 + 30 + 31); |
733 |
fields[DAY_OF_MONTH] = (scaledDay % (31 + 30 + 31 + 30 + 31)) / 5 + 1; |
fields[DAY_OF_MONTH] = (scaledDay % (31 + 30 + 31 + 30 + 31)) / 5 + 1; |
734 |
} |
} |
756 |
} |
} |
757 |
|
|
758 |
calculateDay(fields, day, gregorian); |
calculateDay(fields, day, gregorian); |
759 |
fields[DST_OFFSET] = |
fields[DST_OFFSET] = zone.getOffset(fields[ERA], fields[YEAR], |
760 |
zone.getOffset(fields[ERA], fields[YEAR], fields[MONTH], |
fields[MONTH], fields[DAY_OF_MONTH], |
761 |
fields[DAY_OF_MONTH], fields[DAY_OF_WEEK], |
fields[DAY_OF_WEEK], millisInDay) |
762 |
millisInDay) - fields[ZONE_OFFSET]; |
- fields[ZONE_OFFSET]; |
763 |
|
|
764 |
millisInDay += fields[DST_OFFSET]; |
millisInDay += fields[DST_OFFSET]; |
765 |
if (millisInDay >= 24 * 60 * 60 * 1000) |
if (millisInDay >= 24 * 60 * 60 * 1000) |
780 |
// Do the Correction: getMinimalDaysInFirstWeek() is always in the |
// Do the Correction: getMinimalDaysInFirstWeek() is always in the |
781 |
// first week. |
// first week. |
782 |
int minDays = getMinimalDaysInFirstWeek(); |
int minDays = getMinimalDaysInFirstWeek(); |
783 |
int firstWeekday = |
int firstWeekday = (7 + getWeekDay(fields[YEAR], minDays) |
784 |
(7 + getWeekDay(fields[YEAR], minDays) - getFirstDayOfWeek()) % 7; |
- getFirstDayOfWeek()) % 7; |
785 |
if (minDays - firstWeekday < 1) |
if (minDays - firstWeekday < 1) |
786 |
weekOfYear++; |
weekOfYear++; |
787 |
fields[WEEK_OF_YEAR] = weekOfYear; |
fields[WEEK_OF_YEAR] = weekOfYear; |
788 |
|
|
|
|
|
789 |
int hourOfDay = millisInDay / (60 * 60 * 1000); |
int hourOfDay = millisInDay / (60 * 60 * 1000); |
790 |
fields[AM_PM] = (hourOfDay < 12) ? AM : PM; |
fields[AM_PM] = (hourOfDay < 12) ? AM : PM; |
791 |
int hour = hourOfDay % 12; |
int hour = hourOfDay % 12; |
797 |
fields[SECOND] = millisInDay / (1000); |
fields[SECOND] = millisInDay / (1000); |
798 |
fields[MILLISECOND] = millisInDay % 1000; |
fields[MILLISECOND] = millisInDay % 1000; |
799 |
|
|
800 |
|
areFieldsSet = isSet[ERA] = isSet[YEAR] = isSet[MONTH] = isSet[WEEK_OF_YEAR] = isSet[WEEK_OF_MONTH] = isSet[DAY_OF_MONTH] = isSet[DAY_OF_YEAR] = isSet[DAY_OF_WEEK] = isSet[DAY_OF_WEEK_IN_MONTH] = isSet[AM_PM] = isSet[HOUR] = isSet[HOUR_OF_DAY] = isSet[MINUTE] = isSet[SECOND] = isSet[MILLISECOND] = isSet[ZONE_OFFSET] = isSet[DST_OFFSET] = true; |
|
areFieldsSet = isSet[ERA] = isSet[YEAR] = isSet[MONTH] = |
|
|
isSet[WEEK_OF_YEAR] = isSet[WEEK_OF_MONTH] = |
|
|
isSet[DAY_OF_MONTH] = isSet[DAY_OF_YEAR] = isSet[DAY_OF_WEEK] = |
|
|
isSet[DAY_OF_WEEK_IN_MONTH] = isSet[AM_PM] = isSet[HOUR] = |
|
|
isSet[HOUR_OF_DAY] = isSet[MINUTE] = isSet[SECOND] = |
|
|
isSet[MILLISECOND] = isSet[ZONE_OFFSET] = isSet[DST_OFFSET] = true; |
|
|
|
|
801 |
} |
} |
802 |
|
|
803 |
/** |
/** |
805 |
* equivalent to this if it is also a <code>GregorianCalendar</code> |
* equivalent to this if it is also a <code>GregorianCalendar</code> |
806 |
* with the same time since the epoch under the same conditions |
* with the same time since the epoch under the same conditions |
807 |
* (same change date and same time zone). |
* (same change date and same time zone). |
808 |
* |
* |
809 |
* @param o the object to that we should compare. |
* @param o the object to that we should compare. |
810 |
* @return true, if the given object is a calendar, that represents |
* @return true, if the given object is a calendar, that represents |
811 |
* the same time (but doesn't necessarily have the same fields). |
* the same time (but doesn't necessarily have the same fields). |
817 |
*/ |
*/ |
818 |
public boolean equals(Object o) |
public boolean equals(Object o) |
819 |
{ |
{ |
820 |
if (!(o instanceof GregorianCalendar)) |
if (! (o instanceof GregorianCalendar)) |
821 |
return false; |
return false; |
822 |
|
|
823 |
GregorianCalendar cal = (GregorianCalendar) o; |
GregorianCalendar cal = (GregorianCalendar) o; |
833 |
// public boolean before(Object o) { |
// public boolean before(Object o) { |
834 |
// if (!(o instanceof GregorianCalendar)) |
// if (!(o instanceof GregorianCalendar)) |
835 |
// return false; |
// return false; |
|
|
|
836 |
// GregorianCalendar cal = (GregorianCalendar) o; |
// GregorianCalendar cal = (GregorianCalendar) o; |
837 |
// return (cal.getTimeInMillis() < getTimeInMillis()); |
// return (cal.getTimeInMillis() < getTimeInMillis()); |
838 |
// } |
// } |
|
|
|
839 |
// /** |
// /** |
840 |
// * Compares the given calender with this. |
// * Compares the given calender with this. |
841 |
// * @param o the object to that we should compare. |
// * @param o the object to that we should compare. |
845 |
// public boolean after(Object o) { |
// public boolean after(Object o) { |
846 |
// if (!(o instanceof GregorianCalendar)) |
// if (!(o instanceof GregorianCalendar)) |
847 |
// return false; |
// return false; |
|
|
|
848 |
// GregorianCalendar cal = (GregorianCalendar) o; |
// GregorianCalendar cal = (GregorianCalendar) o; |
849 |
// return (cal.getTimeInMillis() > getTimeInMillis()); |
// return (cal.getTimeInMillis() > getTimeInMillis()); |
850 |
// } |
// } |
855 |
* it does what you expect: Jan, 25 + 10 Days is Feb, 4. |
* it does what you expect: Jan, 25 + 10 Days is Feb, 4. |
856 |
* @param field one of the time field constants. |
* @param field one of the time field constants. |
857 |
* @param amount the amount of time to add. |
* @param amount the amount of time to add. |
858 |
* @exception IllegalArgumentException if <code>field</code> is |
* @exception IllegalArgumentException if <code>field</code> is |
859 |
* <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or invalid; or |
* <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or invalid; or |
860 |
* if <code>amount</code> contains an out-of-range value and the calendar |
* if <code>amount</code> contains an out-of-range value and the calendar |
861 |
* is not in lenient mode. |
* is not in lenient mode. |
890 |
case DAY_OF_MONTH: |
case DAY_OF_MONTH: |
891 |
case DAY_OF_YEAR: |
case DAY_OF_YEAR: |
892 |
case DAY_OF_WEEK: |
case DAY_OF_WEEK: |
893 |
if (!isTimeSet) |
if (! isTimeSet) |
894 |
computeTime(); |
computeTime(); |
895 |
time += amount * (24 * 60 * 60 * 1000L); |
time += amount * (24 * 60 * 60 * 1000L); |
896 |
areFieldsSet = false; |
areFieldsSet = false; |
898 |
case WEEK_OF_YEAR: |
case WEEK_OF_YEAR: |
899 |
case WEEK_OF_MONTH: |
case WEEK_OF_MONTH: |
900 |
case DAY_OF_WEEK_IN_MONTH: |
case DAY_OF_WEEK_IN_MONTH: |
901 |
if (!isTimeSet) |
if (! isTimeSet) |
902 |
computeTime(); |
computeTime(); |
903 |
time += amount * (7 * 24 * 60 * 60 * 1000L); |
time += amount * (7 * 24 * 60 * 60 * 1000L); |
904 |
areFieldsSet = false; |
areFieldsSet = false; |
905 |
break; |
break; |
906 |
case AM_PM: |
case AM_PM: |
907 |
if (!isTimeSet) |
if (! isTimeSet) |
908 |
computeTime(); |
computeTime(); |
909 |
time += amount * (12 * 60 * 60 * 1000L); |
time += amount * (12 * 60 * 60 * 1000L); |
910 |
areFieldsSet = false; |
areFieldsSet = false; |
911 |
break; |
break; |
912 |
case HOUR: |
case HOUR: |
913 |
case HOUR_OF_DAY: |
case HOUR_OF_DAY: |
914 |
if (!isTimeSet) |
if (! isTimeSet) |
915 |
computeTime(); |
computeTime(); |
916 |
time += amount * (60 * 60 * 1000L); |
time += amount * (60 * 60 * 1000L); |
917 |
areFieldsSet = false; |
areFieldsSet = false; |
918 |
break; |
break; |
919 |
case MINUTE: |
case MINUTE: |
920 |
if (!isTimeSet) |
if (! isTimeSet) |
921 |
computeTime(); |
computeTime(); |
922 |
time += amount * (60 * 1000L); |
time += amount * (60 * 1000L); |
923 |
areFieldsSet = false; |
areFieldsSet = false; |
924 |
break; |
break; |
925 |
case SECOND: |
case SECOND: |
926 |
if (!isTimeSet) |
if (! isTimeSet) |
927 |
computeTime(); |
computeTime(); |
928 |
time += amount * (1000L); |
time += amount * (1000L); |
929 |
areFieldsSet = false; |
areFieldsSet = false; |
930 |
break; |
break; |
931 |
case MILLISECOND: |
case MILLISECOND: |
932 |
if (!isTimeSet) |
if (! isTimeSet) |
933 |
computeTime(); |
computeTime(); |
934 |
time += amount; |
time += amount; |
935 |
areFieldsSet = false; |
areFieldsSet = false; |
936 |
break; |
break; |
937 |
case ZONE_OFFSET: |
case ZONE_OFFSET: |
938 |
case DST_OFFSET: |
case DST_OFFSET:default: |
|
default: |
|
939 |
throw new IllegalArgumentException("Invalid or unknown field"); |
throw new IllegalArgumentException("Invalid or unknown field"); |
940 |
} |
} |
941 |
} |
} |
942 |
|
|
|
|
|
943 |
/** |
/** |
944 |
* Rolls the specified time field up or down. This means add one |
* Rolls the specified time field up or down. This means add one |
945 |
* to the specified field, but don't change the other fields. If |
* to the specified field, but don't change the other fields. If |
946 |
* the maximum for this field is reached, start over with the |
* the maximum for this field is reached, start over with the |
947 |
* minimum value. |
* minimum value. |
948 |
* |
* |
949 |
* <strong>Note:</strong> There may be situation, where the other |
* <strong>Note:</strong> There may be situation, where the other |
950 |
* fields must be changed, e.g rolling the month on May, 31. |
* fields must be changed, e.g rolling the month on May, 31. |
951 |
* The date June, 31 is automatically converted to July, 1. |
* The date June, 31 is automatically converted to July, 1. |
952 |
* This requires lenient settings. |
* This requires lenient settings. |
953 |
* |
* |
954 |
* @param field the time field. One of the time field constants. |
* @param field the time field. One of the time field constants. |
990 |
isSet[DAY_OF_YEAR] = false; |
isSet[DAY_OF_YEAR] = false; |
991 |
isSet[WEEK_OF_YEAR] = false; |
isSet[WEEK_OF_YEAR] = false; |
992 |
break; |
break; |
|
|
|
993 |
case DAY_OF_MONTH: |
case DAY_OF_MONTH: |
994 |
isSet[WEEK_OF_MONTH] = false; |
isSet[WEEK_OF_MONTH] = false; |
995 |
isSet[DAY_OF_WEEK] = false; |
isSet[DAY_OF_WEEK] = false; |
998 |
isSet[WEEK_OF_YEAR] = false; |
isSet[WEEK_OF_YEAR] = false; |
999 |
time += delta * (24 * 60 * 60 * 1000L); |
time += delta * (24 * 60 * 60 * 1000L); |
1000 |
break; |
break; |
|
|
|
1001 |
case WEEK_OF_MONTH: |
case WEEK_OF_MONTH: |
1002 |
isSet[DAY_OF_MONTH] = false; |
isSet[DAY_OF_MONTH] = false; |
1003 |
isSet[DAY_OF_WEEK_IN_MONTH] = false; |
isSet[DAY_OF_WEEK_IN_MONTH] = false; |
1029 |
isSet[DAY_OF_YEAR] = false; |
isSet[DAY_OF_YEAR] = false; |
1030 |
time += delta * (7 * 24 * 60 * 60 * 1000L); |
time += delta * (7 * 24 * 60 * 60 * 1000L); |
1031 |
break; |
break; |
|
|
|
1032 |
case AM_PM: |
case AM_PM: |
1033 |
isSet[HOUR_OF_DAY] = false; |
isSet[HOUR_OF_DAY] = false; |
1034 |
time += delta * (12 * 60 * 60 * 1000L); |
time += delta * (12 * 60 * 60 * 1000L); |
1042 |
isSet[AM_PM] = false; |
isSet[AM_PM] = false; |
1043 |
time += delta * (60 * 60 * 1000L); |
time += delta * (60 * 60 * 1000L); |
1044 |
break; |
break; |
|
|
|
1045 |
case MINUTE: |
case MINUTE: |
1046 |
time += delta * (60 * 1000L); |
time += delta * (60 * 1000L); |
1047 |
break; |
break; |
1061 |
* with the minimum value and vice versa for negative amounts. |
* with the minimum value and vice versa for negative amounts. |
1062 |
* |
* |
1063 |
* <strong>Note:</strong> There may be situation, where the other |
* <strong>Note:</strong> There may be situation, where the other |
1064 |
* fields must be changed, e.g rolling the month on May, 31. |
* fields must be changed, e.g rolling the month on May, 31. |
1065 |
* The date June, 31 is automatically corrected to June, 30. |
* The date June, 31 is automatically corrected to June, 30. |
1066 |
* |
* |
1067 |
* @param field the time field. One of the time field constants. |
* @param field the time field. One of the time field constants. |
1098 |
/** |
/** |
1099 |
* The minimum values for the calendar fields. |
* The minimum values for the calendar fields. |
1100 |
*/ |
*/ |
1101 |
private static final int[] minimums = |
private static final int[] minimums = |
1102 |
{ BC, 1, 0, 0, 1, 1, 1, SUNDAY, 1, |
{ |
1103 |
AM, 1, 0, 1, 1, 1, -(12*60*60*1000), 0 }; |
BC, 1, 0, 0, 1, 1, 1, SUNDAY, 1, AM, |
1104 |
|
1, 0, 1, 1, 1, -(12 * 60 * 60 * 1000), |
1105 |
|
0 |
1106 |
|
}; |
1107 |
|
|
1108 |
/** |
/** |
1109 |
* The maximum values for the calendar fields. |
* The maximum values for the calendar fields. |
1110 |
*/ |
*/ |
1111 |
private static final int[] maximums = |
private static final int[] maximums = |
1112 |
{ AD, 5000000, 11, 53, 5, 31, 366, SATURDAY, 5, |
{ |
1113 |
PM, 12, 23, 59, 59, 999, +(12*60*60*1000), (12*60*60*1000) }; |
AD, 5000000, 11, 53, 5, 31, 366, |
1114 |
|
SATURDAY, 5, PM, 12, 23, 59, 59, 999, |
1115 |
|
+(12 * 60 * 60 * 1000), |
1116 |
|
(12 * 60 * 60 * 1000) |
1117 |
|
}; |
1118 |
|
|
1119 |
/** |
/** |
1120 |
* Gets the smallest value that is allowed for the specified field. |
* Gets the smallest value that is allowed for the specified field. |
1138 |
return maximums[field]; |
return maximums[field]; |
1139 |
} |
} |
1140 |
|
|
|
|
|
1141 |
/** |
/** |
1142 |
* Gets the greatest minimum value that is allowed for the specified field. |
* Gets the greatest minimum value that is allowed for the specified field. |
1143 |
* This is the largest value returned by the <code>getActualMinimum(int)</code> |
* This is the largest value returned by the <code>getActualMinimum(int)</code> |
1162 |
* 28 days). |
* 28 days). |
1163 |
* |
* |
1164 |
* @param field the time field. One of the time field constants. |
* @param field the time field. One of the time field constants. |
1165 |
* @return the least maximum value. |
* @return the least maximum value. |
1166 |
* @see #getActualMaximum(int) |
* @see #getActualMaximum(int) |
1167 |
* @since 1.2 |
* @since 1.2 |
1168 |
*/ |
*/ |
1202 |
int min = getMinimalDaysInFirstWeek(); |
int min = getMinimalDaysInFirstWeek(); |
1203 |
if (min == 0) |
if (min == 0) |
1204 |
return 1; |
return 1; |
1205 |
if (!areFieldsSet || !isSet[ERA] || !isSet[YEAR]) |
if (! areFieldsSet || ! isSet[ERA] || ! isSet[YEAR]) |
1206 |
complete(); |
complete(); |
1207 |
|
|
1208 |
int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR]; |
int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR]; |
1223 |
* 29, rather than 28. |
* 29, rather than 28. |
1224 |
* |
* |
1225 |
* @param field the time field. One of the time field constants. |
* @param field the time field. One of the time field constants. |
1226 |
* @return the actual maximum value. |
* @return the actual maximum value. |
1227 |
*/ |
*/ |
1228 |
public int getActualMaximum(int field) |
public int getActualMaximum(int field) |
1229 |
{ |
{ |
1230 |
switch (field) |
switch (field) |
1231 |
{ |
{ |
1232 |
case WEEK_OF_YEAR: |
case WEEK_OF_YEAR: |
1233 |
{ |
{ |
1234 |
if (!areFieldsSet || !isSet[ERA] || !isSet[YEAR]) |
if (! areFieldsSet || ! isSet[ERA] || ! isSet[YEAR]) |
1235 |
complete(); |
complete(); |
1236 |
|
|
1237 |
// This is wrong for the year that contains the gregorian change. |
// This is wrong for the year that contains the gregorian change. |
1238 |
// I.e it gives the weeks in the julian year or in the gregorian |
// I.e it gives the weeks in the julian year or in the gregorian |
1239 |
// year in that case. |
// year in that case. |
1240 |
int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR]; |
int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR]; |
1241 |
int lastDay = isLeapYear(year) ? 366 : 365; |
int lastDay = isLeapYear(year) ? 366 : 365; |
1242 |
int weekday = getWeekDay(year, lastDay); |
int weekday = getWeekDay(year, lastDay); |
1243 |
int week = (lastDay + 6 |
int week = (lastDay + 6 - (7 + weekday - getFirstDayOfWeek()) % 7) / 7; |
|
- (7 + weekday - getFirstDayOfWeek()) % 7) / 7; |
|
1244 |
|
|
1245 |
int minimalDays = getMinimalDaysInFirstWeek(); |
int minimalDays = getMinimalDaysInFirstWeek(); |
1246 |
int firstWeekday = getWeekDay(year, minimalDays); |
int firstWeekday = getWeekDay(year, minimalDays); |
1247 |
/* |
/* |
1248 |
* Is there a set of days at the beginning of the year, before the |
* Is there a set of days at the beginning of the year, before the |
1249 |
* first day of the week, equal to or greater than the minimum number |
* first day of the week, equal to or greater than the minimum number |
1250 |
* of days required in the first week? |
* of days required in the first week? |
1251 |
*/ |
*/ |
1252 |
if (minimalDays - (7 + firstWeekday - getFirstDayOfWeek()) % 7 < 1) |
if (minimalDays - (7 + firstWeekday - getFirstDayOfWeek()) % 7 < 1) |
1253 |
return week + 1; /* Add week 1: firstWeekday through to firstDayOfWeek */ |
return week + 1; /* Add week 1: firstWeekday through to firstDayOfWeek */ |
1254 |
} |
} |
1255 |
case DAY_OF_MONTH: |
case DAY_OF_MONTH: |
1256 |
{ |
{ |
1257 |
if (!areFieldsSet || !isSet[MONTH]) |
if (! areFieldsSet || ! isSet[MONTH]) |
1258 |
complete(); |
complete(); |
1259 |
int month = fields[MONTH]; |
int month = fields[MONTH]; |
1260 |
|
|
1261 |
// If you change this, you should also change |
// If you change this, you should also change |
1262 |
// SimpleTimeZone.getDaysInMonth(); |
// SimpleTimeZone.getDaysInMonth(); |
1263 |
if (month == FEBRUARY) |
if (month == FEBRUARY) |
1264 |
{ |
{ |
1265 |
if (!isSet[YEAR] || !isSet[ERA]) |
if (! isSet[YEAR] || ! isSet[ERA]) |
1266 |
complete(); |
complete(); |
1267 |
int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR]; |
int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR]; |
1268 |
return isLeapYear(year) ? 29 : 28; |
return isLeapYear(year) ? 29 : 28; |
1271 |
return 31 - (month & 1); |
return 31 - (month & 1); |
1272 |
else |
else |
1273 |
return 30 + (month & 1); |
return 30 + (month & 1); |
1274 |
} |
} |
1275 |
case DAY_OF_YEAR: |
case DAY_OF_YEAR: |
1276 |
{ |
{ |
1277 |
if (!areFieldsSet || !isSet[ERA] || !isSet[YEAR]) |
if (! areFieldsSet || ! isSet[ERA] || ! isSet[YEAR]) |
1278 |
complete(); |
complete(); |
1279 |
int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR]; |
int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR]; |
1280 |
return isLeapYear(year) ? 366 : 365; |
return isLeapYear(year) ? 366 : 365; |
1281 |
} |
} |
1282 |
case DAY_OF_WEEK_IN_MONTH: |
case DAY_OF_WEEK_IN_MONTH: |
1283 |
{ |
{ |
1284 |
// This is wrong for the month that contains the gregorian change. |
// This is wrong for the month that contains the gregorian change. |
1285 |
int daysInMonth = getActualMaximum(DAY_OF_MONTH); |
int daysInMonth = getActualMaximum(DAY_OF_MONTH); |
1286 |
|
|
1287 |
// That's black magic, I know |
// That's black magic, I know |
1288 |
return (daysInMonth - (fields[DAY_OF_MONTH] - 1) % 7 + 6) / 7; |
return (daysInMonth - (fields[DAY_OF_MONTH] - 1) % 7 + 6) / 7; |
1289 |
} |
} |
1290 |
case WEEK_OF_MONTH: |
case WEEK_OF_MONTH: |
1291 |
{ |
{ |
1292 |
int daysInMonth = getActualMaximum(DAY_OF_MONTH); |
int daysInMonth = getActualMaximum(DAY_OF_MONTH); |
1293 |
int weekday = (daysInMonth - fields[DAY_OF_MONTH] |
int weekday = (daysInMonth - fields[DAY_OF_MONTH] |
1294 |
+ fields[DAY_OF_WEEK] - SUNDAY) % 7 + SUNDAY; |
+ fields[DAY_OF_WEEK] - SUNDAY) % 7 + SUNDAY; |
1295 |
return (daysInMonth + 6 |
return (daysInMonth + 6 - (7 + weekday - getFirstDayOfWeek()) % 7) / 7; |
1296 |
- (7 + weekday - getFirstDayOfWeek()) % 7) / 7; |
} |
|
} |
|
1297 |
default: |
default: |
1298 |
return maximums[field]; |
return maximums[field]; |
1299 |
} |
} |
1300 |
} |
} |
|
|
|
|
|
|
1301 |
} |
} |