/** * Return JD of start of given month/year. * @internal */ int32_t HebrewCalendar::handleComputeMonthStart(int32_t eyear, int32_t month, UBool /*useMonth*/) const { UErrorCode status = U_ZERO_ERROR; // Resolve out-of-range months. This is necessary in order to // obtain the correct year. We correct to // a 12- or 13-month year (add/subtract 12 or 13, depending // on the year) but since we _always_ number from 0..12, and // the leap year determines whether or not month 5 (Adar 1) // is present, we allow 0..12 in any given year. while (month < 0) { month += monthsInYear(--eyear); } // Careful: allow 0..12 in all years while (month > 12) { month -= monthsInYear(eyear++); } int32_t day = startOfYear(eyear, status); if(U_FAILURE(status)) { return 0; } if (month != 0) { if (isLeapYear(eyear)) { day += LEAP_MONTH_START[month][yearType(eyear)]; } else { day += MONTH_START[month][yearType(eyear)]; } } return (int) (day + 347997); }
/** * Returns the length of the given month in the given year * @internal */ int32_t HebrewCalendar::handleGetMonthLength(int32_t extendedYear, int32_t month) const { // Resolve out-of-range months. This is necessary in order to // obtain the correct year. We correct to // a 12- or 13-month year (add/subtract 12 or 13, depending // on the year) but since we _always_ number from 0..12, and // the leap year determines whether or not month 5 (Adar 1) // is present, we allow 0..12 in any given year. while (month < 0) { month += monthsInYear(--extendedYear); } // Careful: allow 0..12 in all years while (month > 12) { month -= monthsInYear(extendedYear++); } switch (month) { case HESHVAN: case KISLEV: // These two month lengths can vary return MONTH_LENGTH[month][yearType(extendedYear)]; default: // The rest are a fixed length return MONTH_LENGTH[month][0]; } }
// Ok int KCalendarSystemHebrew::weeksInYear(int year) const { TQDate temp; setYMD(temp, year, 1, 1); // don't pass an uninitialized TQDate to // monthsInYear in the next call setYMD(temp, year, monthsInYear(temp), hndays(monthsInYear(temp), year) ); int nWeekNumber = weekNumber(temp); if(nWeekNumber == 1) // last week belongs to next year { temp = TQT_TQDATE_OBJECT(temp.addDays(-7)); nWeekNumber = weekNumber(temp); } return nWeekNumber; }
int KCalendarSystem::daysInMonth( const QDate &date ) const { // Days In Month = jd of first day of next month minus jd of first day of this month // Use setAnyDate() to allow correct calculation in last valid year if ( isValid( date ) ) { QDate firstDayOfThisMonth, firstDayOfNextMonth; int thisYear = year( date ); int thisMonth = month( date ); setDate( firstDayOfThisMonth, thisYear, thisMonth, 1 ); //check if next month falls in next year if ( thisMonth < monthsInYear( date ) ) { setDate( firstDayOfNextMonth, thisYear, thisMonth + 1, 1 ); } else { d->setAnyDate( firstDayOfNextMonth, thisYear + 1, 1, 1 ); } return ( firstDayOfNextMonth.toJulianDay() - firstDayOfThisMonth.toJulianDay() ); } return -1; }
/** * Rolls (up/down) a specified amount time on the given field. For * example, to roll the current date up by three days, you can call * <code>roll(Calendar.DATE, 3)</code>. If the * field is rolled past its maximum allowable value, it will "wrap" back * to its minimum and continue rolling. * For example, calling <code>roll(Calendar.DATE, 10)</code> * on a Hebrew calendar set to "25 Av 5758" will result in the date "5 Av 5758". * <p> * When rolling certain fields, the values of other fields may conflict and * need to be changed. For example, when rolling the {@link #MONTH MONTH} field * upward by one for the date "30 Av 5758", the {@link #DAY_OF_MONTH DAY_OF_MONTH} field * must be adjusted so that the result is "29 Elul 5758" rather than the invalid * "30 Elul". * <p> * This method is able to roll * all fields except for {@link #ERA ERA}, {@link #DST_OFFSET DST_OFFSET}, * and {@link #ZONE_OFFSET ZONE_OFFSET}. Subclasses may, of course, add support for * additional fields in their overrides of <code>roll</code>. * <p> * <b>Note:</b> You should always use roll and {@link #add add} rather * than attempting to perform arithmetic operations directly on the fields * of a <tt>HebrewCalendar</tt>. Since the {@link #MONTH MONTH} field behaves * discontinuously in non-leap years, simple arithmetic can give invalid results. * <p> * @param field the time field. * @param amount the amount by which the field should be rolled. * * @exception IllegalArgumentException if the field is invalid or refers * to a field that cannot be handled by this method. * @internal */ void HebrewCalendar::roll(UCalendarDateFields field, int32_t amount, UErrorCode& status) { if(U_FAILURE(status)) { return; } switch (field) { case UCAL_MONTH: { int32_t month = get(UCAL_MONTH, status); int32_t year = get(UCAL_YEAR, status); UBool leapYear = isLeapYear(year); int32_t yearLength = monthsInYear(year); int32_t newMonth = month + (amount % yearLength); // // If it's not a leap year and we're rolling past the missing month // of ADAR_1, we need to roll an extra month to make up for it. // if (!leapYear) { if (amount > 0 && month < ADAR_1 && newMonth >= ADAR_1) { newMonth++; } else if (amount < 0 && month > ADAR_1 && newMonth <= ADAR_1) { newMonth--; } } set(UCAL_MONTH, (newMonth + 13) % 13); pinField(UCAL_DAY_OF_MONTH, status); return; } default: Calendar::roll(field, amount, status); } }
QDate KCalendarSystem::addMonths( const QDate &date, int numMonths ) const { if ( isValid( date ) ) { int originalYear, originalMonth, originalDay; int newYear, newMonth, newDay; int monthsInOriginalYear, daysInNewMonth; QDate firstOfNewMonth, newDate; julianDayToDate( date.toJulianDay(), originalYear, originalMonth, originalDay ); monthsInOriginalYear = monthsInYear( date ); newYear = originalYear + ( ( originalMonth + numMonths ) / monthsInOriginalYear ); newMonth = ( originalMonth + numMonths ) % monthsInOriginalYear; if ( newMonth == 0 ) { newYear = newYear - 1; newMonth = monthsInOriginalYear; } if ( newMonth < 0 ) { newYear = newYear - 1; newMonth = newMonth + monthsInOriginalYear; } //Adjust day number if new month has fewer days than old month if ( setDate( firstOfNewMonth, newYear, newMonth, 1 ) ) { daysInNewMonth = daysInMonth( firstOfNewMonth ); newDay = ( daysInNewMonth < originalDay ) ? daysInNewMonth : originalDay; if ( setDate( newDate, newYear, newMonth, newDay ) ) { return newDate; } } } //Is QDate's way of saying is invalid return QDate::fromJulianDay( 0 ); }