/** * 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; }
/** * Override Calendar to compute several fields specific to the Chinese * calendar system. These are: * * <ul><li>ERA * <li>YEAR * <li>MONTH * <li>DAY_OF_MONTH * <li>DAY_OF_YEAR * <li>EXTENDED_YEAR</ul> * * The DAY_OF_WEEK and DOW_LOCAL fields are already set when this * method is called. The getGregorianXxx() methods return Gregorian * calendar equivalents for the given Julian day. * * <p>Compute the ChineseCalendar-specific field IS_LEAP_MONTH. * @stable ICU 2.8 */ void ChineseCalendar::handleComputeFields(int32_t julianDay, UErrorCode &/*status*/) { computeChineseFields(julianDay - kEpochStartAsJulianDay, // local days getGregorianYear(), getGregorianMonth(), TRUE); // set all fields }
void GregorianCalendar::handleComputeFields(int32_t julianDay, UErrorCode& status) { int32_t eyear, month, dayOfMonth, dayOfYear, unusedRemainder; if(U_FAILURE(status)) { return; } #if defined (U_DEBUG_CAL) fprintf(stderr, "%s:%d: jd%d- (greg's %d)- [cut=%d]\n", __FILE__, __LINE__, julianDay, getGregorianDayOfYear(), fCutoverJulianDay); #endif if (julianDay >= fCutoverJulianDay) { month = getGregorianMonth(); dayOfMonth = getGregorianDayOfMonth(); dayOfYear = getGregorianDayOfYear(); eyear = getGregorianYear(); } else { // The Julian epoch day (not the same as Julian Day) // is zero on Saturday December 30, 0 (Gregorian). int32_t julianEpochDay = julianDay - (kJan1_1JulianDay - 2); eyear = (int32_t) ClockMath::floorDivide((4.0*julianEpochDay) + 1464.0, (int32_t) 1461, unusedRemainder); // Compute the Julian calendar day number for January 1, eyear int32_t january1 = 365*(eyear-1) + ClockMath::floorDivide(eyear-1, (int32_t)4); dayOfYear = (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 // computatinally cleaner proleptic calendar, which assumes // consistent 4-year cycles throughout time. UBool isLeap = ((eyear&0x3) == 0); // equiv. to (eyear%4 == 0) // Common Julian/Gregorian calculation int32_t correction = 0; int32_t march1 = isLeap ? 60 : 59; // zero-based DOY for March 1 if (dayOfYear >= march1) { correction = isLeap ? 1 : 2; } month = (12 * (dayOfYear + correction) + 6) / 367; // zero-based month dayOfMonth = dayOfYear - (isLeap?kLeapNumDays[month]:kNumDays[month]) + 1; // one-based DOM ++dayOfYear; #if defined (U_DEBUG_CAL) // fprintf(stderr, "%d - %d[%d] + 1\n", dayOfYear, isLeap?kLeapNumDays[month]:kNumDays[month], month ); // fprintf(stderr, "%s:%d: greg's HCF %d -> %d/%d/%d not %d/%d/%d\n", // __FILE__, __LINE__,julianDay, // eyear,month,dayOfMonth, // getGregorianYear(), getGregorianMonth(), getGregorianDayOfMonth() ); fprintf(stderr, "%s:%d: doy %d (greg's %d)- [cut=%d]\n", __FILE__, __LINE__, dayOfYear, getGregorianDayOfYear(), fCutoverJulianDay); #endif } // [j81] if we are after the cutover in its year, shift the day of the year if((eyear == fGregorianCutoverYear) && (julianDay >= fCutoverJulianDay)) { //from handleComputeMonthStart int32_t gregShift = Grego::gregorianShift(eyear); #if defined (U_DEBUG_CAL) fprintf(stderr, "%s:%d: gregorian shift %d ::: doy%d => %d [cut=%d]\n", __FILE__, __LINE__,gregShift, dayOfYear, dayOfYear+gregShift, fCutoverJulianDay); #endif dayOfYear += gregShift; } internalSet(UCAL_MONTH, month); internalSet(UCAL_DAY_OF_MONTH, dayOfMonth); internalSet(UCAL_DAY_OF_YEAR, dayOfYear); internalSet(UCAL_EXTENDED_YEAR, eyear); int32_t era = AD; if (eyear < 1) { era = BC; eyear = 1 - eyear; } internalSet(UCAL_ERA, era); internalSet(UCAL_YEAR, eyear); }