void HebrewCalendar::validateField(UCalendarDateFields field, UErrorCode &status) { if (field == UCAL_MONTH && !isLeapYear(handleGetExtendedYear()) && internalGet(UCAL_MONTH) == ADAR_1) { status = U_ILLEGAL_ARGUMENT_ERROR; return; } Calendar::validateField(field, status); }
void BuddhistCalendar::handleComputeFields(int32_t julianDay, UErrorCode& status) { GregorianCalendar::handleComputeFields(julianDay, status); int32_t y = internalGet(UCAL_EXTENDED_YEAR) - kBuddhistEraStart; internalSet(UCAL_ERA, 0); internalSet(UCAL_YEAR, y); }
int32_t CopticCalendar::handleGetExtendedYear() { int32_t eyear; if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR) { eyear = internalGet(UCAL_EXTENDED_YEAR, 1); // Default to year 1 } else { // The year defaults to the epoch start, the era to CE int32_t era = internalGet(UCAL_ERA, CE); if (era == BCE) { eyear = 1 - internalGet(UCAL_YEAR, 1); // Convert to extended year } else { eyear = internalGet(UCAL_YEAR, 1); // Default to year 1 } } return eyear; }
int32_t BuddhistCalendar::monthLength(int32_t month) const { UErrorCode status = U_ZERO_ERROR; int32_t year = internalGet(UCAL_YEAR); // ignore era return GregorianCalendar::monthLength(month, getGregorianYear(status)); }
/** * Return the Julian day number of day before the first day of the * given month in the given extended year. * * <p>Note: This method reads the IS_LEAP_MONTH field to determine * whether the given month is a leap month. * @param eyear the extended year * @param month the zero-based month. The month is also determined * by reading the IS_LEAP_MONTH field. * @return the Julian day number of the day before the first * day of the given month and year * @stable ICU 2.8 */ int32_t ChineseCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, UBool useMonth) const { ChineseCalendar *nonConstThis = (ChineseCalendar*)this; // cast away const // If the month is out of range, adjust it into range, and // modify the extended year value accordingly. if (month < 0 || month > 11) { double m = month; eyear += (int32_t)ClockMath::floorDivide(m, 12.0, m); month = (int32_t)m; } int32_t gyear = eyear + fEpochYear - 1; // Gregorian year int32_t theNewYear = newYear(gyear); int32_t newMoon = newMoonNear(theNewYear + month * 29, TRUE); int32_t julianDay = newMoon + kEpochStartAsJulianDay; // Save fields for later restoration int32_t saveMonth = internalGet(UCAL_MONTH); int32_t saveIsLeapMonth = internalGet(UCAL_IS_LEAP_MONTH); // Ignore IS_LEAP_MONTH field if useMonth is false int32_t isLeapMonth = useMonth ? saveIsLeapMonth : 0; UErrorCode status = U_ZERO_ERROR; nonConstThis->computeGregorianFields(julianDay, status); if (U_FAILURE(status)) return 0; // This will modify the MONTH and IS_LEAP_MONTH fields (only) nonConstThis->computeChineseFields(newMoon, getGregorianYear(), getGregorianMonth(), FALSE); if (month != internalGet(UCAL_MONTH) || isLeapMonth != internalGet(UCAL_IS_LEAP_MONTH)) { newMoon = newMoonNear(newMoon + SYNODIC_GAP, TRUE); julianDay = newMoon + kEpochStartAsJulianDay; } nonConstThis->internalSet(UCAL_MONTH, saveMonth); nonConstThis->internalSet(UCAL_IS_LEAP_MONTH, saveIsLeapMonth); return julianDay - 1; }
int32_t GregorianCalendar::handleGetExtendedYearFromWeekFields(int32_t yearWoy, int32_t woy) { // convert year to extended form int32_t era = internalGet(UCAL_ERA, AD); if(era == BC) { yearWoy = 1 - yearWoy; } return Calendar::handleGetExtendedYearFromWeekFields(yearWoy, woy); }
int32_t JapaneseCalendar::handleGetExtendedYear() { // EXTENDED_YEAR in JapaneseCalendar is a Gregorian year // The default value of EXTENDED_YEAR is 1970 (Showa 45) int32_t year; if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR && newerField(UCAL_EXTENDED_YEAR, UCAL_ERA) == UCAL_EXTENDED_YEAR) { year = internalGet(UCAL_EXTENDED_YEAR, kGregorianEpoch); } else { // Subtract one because year starts at 1 year = internalGet(UCAL_YEAR) + kEraInfo[internalGetEra()].year - 1; } return year; }
int32_t TaiwanCalendar::handleGetExtendedYear() { // EXTENDED_YEAR in TaiwanCalendar is a Gregorian year // The default value of EXTENDED_YEAR is 1970 (Minguo 59) int32_t year = kGregorianEpoch; if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR && newerField(UCAL_EXTENDED_YEAR, UCAL_ERA) == UCAL_EXTENDED_YEAR) { year = internalGet(UCAL_EXTENDED_YEAR, kGregorianEpoch); } else { int32_t era = internalGet(UCAL_ERA, MINGUO); if(era == MINGUO) { year = internalGet(UCAL_YEAR, 1) + kTaiwanEraStart; } else if(era == BEFORE_MINGUO) { year = 1 - internalGet(UCAL_YEAR, 1) + kTaiwanEraStart; } } return year; }
UBool GregorianCalendar::inDaylightTime(UErrorCode& status) const { if (U_FAILURE(status) || !getTimeZone().useDaylightTime()) return FALSE; // Force an update of the state of the Calendar. ((GregorianCalendar*)this)->complete(status); // cast away const return (UBool)(U_SUCCESS(status) ? (internalGet(UCAL_DST_OFFSET) != 0) : FALSE); }
bool SkBitSet::orBits(const SkBitSet& source) { if (fBitCount != source.fBitCount) { return false; } uint32_t* targetBitmap = internalGet(0); uint32_t* sourceBitmap = source.internalGet(0); for (size_t i = 0; i < fDwordCount; ++i) { targetBitmap[i] |= sourceBitmap[i]; } return true; }
void BuddhistCalendar::timeToFields(UDate theTime, UBool quick, UErrorCode& status) { //Calendar::timeToFields(theTime, quick, status); int32_t era = internalGet(UCAL_ERA); int32_t year = internalGet(UCAL_YEAR); if(era == GregorianCalendar::BC) { year = 1-year; era = BuddhistCalendar::BE; } else if(era == GregorianCalendar::AD) { era = BuddhistCalendar::BE; } else { status = U_INTERNAL_PROGRAM_ERROR; } year = year - kBuddhistEraStart; internalSet(UCAL_ERA, era); internalSet(UCAL_YEAR, year); }
UBool IslamicCalendar::inDaylightTime(UErrorCode & status) const { // copied from GregorianCalendar if (U_FAILURE(status) || (&(getTimeZone()) == NULL && !getTimeZone().useDaylightTime())) { return FALSE; } // Force an update of the state of the Calendar. ((IslamicCalendar *)this)->complete(status); // cast away const return (UBool)(U_SUCCESS(status) ? (internalGet(UCAL_DST_OFFSET) != 0) : FALSE); }
void TaiwanCalendar::handleComputeFields(int32_t julianDay, UErrorCode& status) { GregorianCalendar::handleComputeFields(julianDay, status); int32_t y = internalGet(UCAL_EXTENDED_YEAR) - kTaiwanEraStart; if(y>0) { internalSet(UCAL_ERA, MINGUO); internalSet(UCAL_YEAR, y); } else { internalSet(UCAL_ERA, BEFORE_MINGUO); internalSet(UCAL_YEAR, 1-y); } }
int32_t EthiopicCalendar::handleGetExtendedYear() { // Ethiopic calendar uses EXTENDED_YEAR aligned to // Amelete Hihret year always. int32_t eyear; if (newerField(UCAL_EXTENDED_YEAR, UCAL_YEAR) == UCAL_EXTENDED_YEAR) { eyear = internalGet(UCAL_EXTENDED_YEAR, 1); // Default to year 1 } else if (isAmeteAlemEra()) { eyear = internalGet(UCAL_YEAR, 1 + AMETE_MIHRET_DELTA) - AMETE_MIHRET_DELTA; // Default to year 1 of Amelete Mihret } else { // The year defaults to the epoch start, the era to AMETE_MIHRET int32_t era = internalGet(UCAL_ERA, AMETE_MIHRET); if (era == AMETE_MIHRET) { eyear = internalGet(UCAL_YEAR, 1); // Default to year 1 } else { eyear = internalGet(UCAL_YEAR, 1) - AMETE_MIHRET_DELTA; } } return eyear; }
UBool GregorianCalendar::validateFields() const { for (int32_t field = 0; field < UCAL_FIELD_COUNT; field++) { // Ignore DATE and DAY_OF_YEAR which are handled below if (field != UCAL_DATE && field != UCAL_DAY_OF_YEAR && isSet((UCalendarDateFields)field) && ! boundsCheck(internalGet((UCalendarDateFields)field), (UCalendarDateFields)field)) return FALSE; } // Values differ in Least-Maximum and Maximum should be handled // specially. if (isSet(UCAL_DATE)) { int32_t date = internalGet(UCAL_DATE); if (date < getMinimum(UCAL_DATE) || date > monthLength(internalGet(UCAL_MONTH))) { return FALSE; } } if (isSet(UCAL_DAY_OF_YEAR)) { int32_t days = internalGet(UCAL_DAY_OF_YEAR); if (days < 1 || days > yearLength()) { return FALSE; } } // Handle DAY_OF_WEEK_IN_MONTH, which must not have the value zero. // We've checked against minimum and maximum above already. if (isSet(UCAL_DAY_OF_WEEK_IN_MONTH) && 0 == internalGet(UCAL_DAY_OF_WEEK_IN_MONTH)) { return FALSE; } return TRUE; }
int32_t GregorianCalendar::handleGetExtendedYear() { // the year to return int32_t year = kEpochYear; // year field to use int32_t yearField = UCAL_EXTENDED_YEAR; // There are three separate fields which could be used to // derive the proper year. Use the one most recently set. if (fStamp[yearField] < fStamp[UCAL_YEAR]) yearField = UCAL_YEAR; if (fStamp[yearField] < fStamp[UCAL_YEAR_WOY]) yearField = UCAL_YEAR_WOY; // based on the "best" year field, get the year switch(yearField) { case UCAL_EXTENDED_YEAR: year = internalGet(UCAL_EXTENDED_YEAR, kEpochYear); break; case UCAL_YEAR: { // The year defaults to the epoch start, the era to AD int32_t era = internalGet(UCAL_ERA, AD); if (era == BC) { year = 1 - internalGet(UCAL_YEAR, 1); // Convert to extended year } else { year = internalGet(UCAL_YEAR, kEpochYear); } } break; case UCAL_YEAR_WOY: year = handleGetExtendedYearFromWeekFields(internalGet(UCAL_YEAR_WOY), internalGet(UCAL_WEEK_OF_YEAR)); #if defined (U_DEBUG_CAL) // if(internalGet(UCAL_YEAR_WOY) != year) { fprintf(stderr, "%s:%d: hGEYFWF[%d,%d] -> %d\n", __FILE__, __LINE__,internalGet(UCAL_YEAR_WOY),internalGet(UCAL_WEEK_OF_YEAR),year); //} #endif break; default: year = kEpochYear; } return year; }
void BuddhistCalendar::add(UCalendarDateFields field, int32_t amount, UErrorCode& status) { if (U_FAILURE(status)) return; if (amount == 0) return; // Do nothing! if(field == UCAL_YEAR /* || field == UCAL_YEAR_WOY */) { int32_t year = internalGet(field); int32_t era = internalGetEra(); year += amount; set(field,year); pinDayOfMonth(); } else { GregorianCalendar::add(field,amount,status); } }
int32_t GregorianCalendar::yearLength() const { return isLeapYear(internalGet(UCAL_YEAR)) ? 366 : 365; }
int32_t BuddhistCalendar::internalGetEra() const { return isSet(UCAL_ERA) ? internalGet(UCAL_ERA) : BE; }
bool SkBitSet::isBitSet(int index) const { uint32_t mask = 1 << (index % 32); return 0 != (*internalGet(index) & mask); }
/** * Return the ERA. We need a special method for this because the * default ERA is AD, but a zero (unset) ERA is BC. */ int32_t GregorianCalendar::internalGetEra() const { return isSet(UCAL_ERA) ? internalGet(UCAL_ERA) : (int32_t)AD; }
void JapaneseCalendar::handleComputeFields(int32_t julianDay, UErrorCode & status) { //Calendar::timeToFields(theTime, quick, status); GregorianCalendar::handleComputeFields(julianDay, status); int32_t year = internalGet(UCAL_EXTENDED_YEAR); // Gregorian year int32_t low = 0; // Short circuit for recent years. Most modern computations will // occur in the current era and won't require the binary search. // Note that if the year is == the current era year, then we use // the binary search to handle the month/dom comparison. #ifdef U_DEBUG_JCAL fprintf(stderr, "== %d \n", year); #endif if (year > kEraInfo[kCurrentEra].year) { low = kCurrentEra; #ifdef U_DEBUG_JCAL fprintf(stderr, " low=%d (special)\n", low); #endif } else { // Binary search int32_t high = kEraCount; #ifdef U_DEBUG_JCAL fprintf(stderr, " high=%d\n", high); #endif while (low < high - 1) { int32_t i = (low + high) / 2; int32_t diff = year - kEraInfo[i].year; #ifdef U_DEBUG_JCAL fprintf(stderr, " d=%d low=%d, high=%d. Considering %d:M%d D%d Y%d. { we are ?:M%d D%d Y%d }\n", diff, low, high, i, kEraInfo[i].month - 1, kEraInfo[i].day, kEraInfo[i].year, internalGet(UCAL_MONTH), internalGet(UCAL_DATE), year); #endif // If years are the same, then compare the months, and if those // are the same, compare days of month. In the ERAS array // months are 1-based for easier maintenance. if (diff == 0) { diff = internalGet(UCAL_MONTH) - (kEraInfo[i].month - 1); #ifdef U_DEBUG_JCAL fprintf(stderr, "diff now %d (M) = %d - %d - 1\n", diff, internalGet(UCAL_MONTH), kEraInfo[i].month); #endif if (diff == 0) { diff = internalGet(UCAL_DATE) - kEraInfo[i].day; #ifdef U_DEBUG_JCAL fprintf(stderr, "diff now %d (D)\n", diff); #endif } } if (diff >= 0) { low = i; } else { high = i; } #ifdef U_DEBUG_JCAL fprintf(stderr, ". low=%d, high=%d, i=%d, diff=%d.. %d\n", low, high, i, diff, year); #endif } } #ifdef U_DEBUG_JCAL fprintf(stderr, " low[era]=%d,.. %d\n", low, year); #endif // Now we've found the last era that starts before this date, so // adjust the year to count from the start of that era. Note that // all dates before the first era will fall into the first era by // the algorithm. internalSet(UCAL_ERA, low); internalSet(UCAL_YEAR, year - kEraInfo[low].year + 1); #ifdef U_DEBUG_JCAL fprintf(stderr, " Set ERA=%d, year=%d\n", low, year - kEraInfo[low].year + 1); #endif }
int32_t GregorianCalendar::monthLength(int32_t month) const { int32_t year = internalGet(UCAL_EXTENDED_YEAR); return handleGetMonthLength(year, month); }
int32_t JapaneseCalendar::internalGetEra() const { return internalGet(UCAL_ERA, kCurrentEra); }
void GregorianCalendar::roll(UCalendarDateFields field, int32_t amount, UErrorCode& status) { if((amount == 0) || U_FAILURE(status)) { return; } // J81 processing. (gregorian cutover) UBool inCutoverMonth = FALSE; int32_t cMonthLen=0; // 'c' for cutover; in days int32_t cDayOfMonth=0; // no discontinuity: [0, cMonthLen) double cMonthStart=0.0; // in ms // Common code - see if we're in the cutover month of the cutover year if(get(UCAL_EXTENDED_YEAR, status) == fGregorianCutoverYear) { switch (field) { case UCAL_DAY_OF_MONTH: case UCAL_WEEK_OF_MONTH: { int32_t max = monthLength(internalGet(UCAL_MONTH)); UDate t = internalGetTime(); // We subtract 1 from the DAY_OF_MONTH to make it zero-based, and an // additional 10 if we are after the cutover. Thus the monthStart // value will be correct iff we actually are in the cutover month. cDayOfMonth = internalGet(UCAL_DAY_OF_MONTH) - ((t >= fGregorianCutover) ? 10 : 0); cMonthStart = t - ((cDayOfMonth - 1) * kOneDay); // A month containing the cutover is 10 days shorter. if ((cMonthStart < fGregorianCutover) && (cMonthStart + (cMonthLen=(max-10))*kOneDay >= fGregorianCutover)) { inCutoverMonth = TRUE; } } default: ; } } switch (field) { case UCAL_WEEK_OF_YEAR: { // Unlike WEEK_OF_MONTH, WEEK_OF_YEAR never shifts the day of the // week. Also, rolling the week of the year can have seemingly // strange effects simply because the year of the week of year // may be different from the calendar year. For example, the // date Dec 28, 1997 is the first day of week 1 of 1998 (if // weeks start on Sunday and the minimal days in first week is // <= 3). int32_t woy = get(UCAL_WEEK_OF_YEAR, status); // Get the ISO year, which matches the week of year. This // may be one year before or after the calendar year. int32_t isoYear = get(UCAL_YEAR_WOY, status); int32_t isoDoy = internalGet(UCAL_DAY_OF_YEAR); if (internalGet(UCAL_MONTH) == UCAL_JANUARY) { if (woy >= 52) { isoDoy += handleGetYearLength(isoYear); } } else { if (woy == 1) { isoDoy -= handleGetYearLength(isoYear - 1); } } woy += amount; // Do fast checks to avoid unnecessary computation: if (woy < 1 || woy > 52) { // Determine the last week of the ISO year. // We do this using the standard formula we use // everywhere in this file. If we can see that the // days at the end of the year are going to fall into // week 1 of the next year, we drop the last week by // subtracting 7 from the last day of the year. int32_t lastDoy = handleGetYearLength(isoYear); int32_t lastRelDow = (lastDoy - isoDoy + internalGet(UCAL_DAY_OF_WEEK) - getFirstDayOfWeek()) % 7; if (lastRelDow < 0) lastRelDow += 7; if ((6 - lastRelDow) >= getMinimalDaysInFirstWeek()) lastDoy -= 7; int32_t lastWoy = weekNumber(lastDoy, lastRelDow + 1); woy = ((woy + lastWoy - 1) % lastWoy) + 1; } set(UCAL_WEEK_OF_YEAR, woy); set(UCAL_YEAR_WOY,isoYear); return; } case UCAL_DAY_OF_MONTH: if( !inCutoverMonth ) { Calendar::roll(field, amount, status); return; } else { // [j81] 1582 special case for DOM // The default computation works except when the current month // contains the Gregorian cutover. We handle this special case // here. [j81 - aliu] double monthLen = cMonthLen * kOneDay; double msIntoMonth = uprv_fmod(internalGetTime() - cMonthStart + amount * kOneDay, monthLen); if (msIntoMonth < 0) { msIntoMonth += monthLen; } #if defined (U_DEBUG_CAL) fprintf(stderr, "%s:%d: roll DOM %d -> %.0lf ms \n", __FILE__, __LINE__,amount, cMonthLen, cMonthStart+msIntoMonth); #endif setTimeInMillis(cMonthStart + msIntoMonth, status); return; } case UCAL_WEEK_OF_MONTH: if( !inCutoverMonth ) { Calendar::roll(field, amount, status); return; } else { #if defined (U_DEBUG_CAL) fprintf(stderr, "%s:%d: roll WOM %d ??????????????????? \n", __FILE__, __LINE__,amount); #endif // NOTE: following copied from the old // GregorianCalendar::roll( WEEK_OF_MONTH ) code // This is tricky, because during the roll we may have to shift // to a different day of the week. For example: // s m t w r f s // 1 2 3 4 5 // 6 7 8 9 10 11 12 // When rolling from the 6th or 7th back one week, we go to the // 1st (assuming that the first partial week counts). The same // thing happens at the end of the month. // The other tricky thing is that we have to figure out whether // the first partial week actually counts or not, based on the // minimal first days in the week. And we have to use the // correct first day of the week to delineate the week // boundaries. // Here's our algorithm. First, we find the real boundaries of // the month. Then we discard the first partial week if it // doesn't count in this locale. Then we fill in the ends with // phantom days, so that the first partial week and the last // partial week are full weeks. We then have a nice square // block of weeks. We do the usual rolling within this block, // as is done elsewhere in this method. If we wind up on one of // the phantom days that we added, we recognize this and pin to // the first or the last day of the month. Easy, eh? // Another wrinkle: To fix jitterbug 81, we have to make all this // work in the oddball month containing the Gregorian cutover. // This month is 10 days shorter than usual, and also contains // a discontinuity in the days; e.g., the default cutover month // is Oct 1582, and goes from day of month 4 to day of month 15. // Normalize the DAY_OF_WEEK so that 0 is the first day of the week // in this locale. We have dow in 0..6. int32_t dow = internalGet(UCAL_DAY_OF_WEEK) - getFirstDayOfWeek(); if (dow < 0) dow += 7; // Find the day of month, compensating for cutover discontinuity. int32_t dom = cDayOfMonth; // Find the day of the week (normalized for locale) for the first // of the month. int32_t fdm = (dow - dom + 1) % 7; if (fdm < 0) fdm += 7; // Get the first day of the first full week of the month, // including phantom days, if any. Figure out if the first week // counts or not; if it counts, then fill in phantom days. If // not, advance to the first real full week (skip the partial week). int32_t start; if ((7 - fdm) < getMinimalDaysInFirstWeek()) start = 8 - fdm; // Skip the first partial week else start = 1 - fdm; // This may be zero or negative // Get the day of the week (normalized for locale) for the last // day of the month. int32_t monthLen = cMonthLen; int32_t ldm = (monthLen - dom + dow) % 7; // We know monthLen >= DAY_OF_MONTH so we skip the += 7 step here. // Get the limit day for the blocked-off rectangular month; that // is, the day which is one past the last day of the month, // after the month has already been filled in with phantom days // to fill out the last week. This day has a normalized DOW of 0. int32_t limit = monthLen + 7 - ldm; // Now roll between start and (limit - 1). int32_t gap = limit - start; int32_t newDom = (dom + amount*7 - start) % gap; if (newDom < 0) newDom += gap; newDom += start; // Finally, pin to the real start and end of the month. if (newDom < 1) newDom = 1; if (newDom > monthLen) newDom = monthLen; // Set the DAY_OF_MONTH. We rely on the fact that this field // takes precedence over everything else (since all other fields // are also set at this point). If this fact changes (if the // disambiguation algorithm changes) then we will have to unset // the appropriate fields here so that DAY_OF_MONTH is attended // to. // If we are in the cutover month, manipulate ms directly. Don't do // this in general because it doesn't work across DST boundaries // (details, details). This takes care of the discontinuity. setTimeInMillis(cMonthStart + (newDom-1)*kOneDay, status); return; } default: Calendar::roll(field, amount, status); return; } }