void MonthDayRuleTest::test_lifecycle_invalid() { //test: MontDayRule::MonthDayRule(const Month& month, const DayOfMonth& dayOfMonth); try{ MonthDayRule rule("Rule", Month(4), DayOfMonth(31)); } catch (BaseException& ex) { std::cout << "Caught expected exception (invalid month, day in month combination); details: " << ex.what() << std::endl; } }
/*********************************************************************** * * FUNCTION: ApptRepeatsOnDate * * DESCRIPTION: This routine returns true if a repeating appointment * occurrs on the specified date. * * PARAMETERS: apptRec - a pointer to an appointment record * date - date to check * * RETURNED: true if the appointment occurs on the date specified * * REVISION HISTORY: * Name Date Description * ---- ---- ----------- * art 6/14/95 Initial Revision * ***********************************************************************/ Boolean ApptRepeatsOnDate (ApptDBRecordPtr apptRec, DateType date) { Int16 i; UInt16 freq; UInt16 weeksDiff; UInt16 dayInMonth; UInt16 dayOfWeek; UInt16 dayOfMonth; UInt16 firstDayOfWeek; long dateInDays; long startInDays; Boolean onDate = false; DatePtr exceptions; DateType startDate; // Is the date passed before the start date of the appointment? if (DateCompare (date, apptRec->when->date) < 0) return (false); // Is the date passed after the end date of the appointment? if (DateCompare (date, apptRec->repeat->repeatEndDate) > 0) return (false); // Get the frequency of occurrecne // (ex: every 2nd day, every 3rd month, etc.). freq = apptRec->repeat->repeatFrequency; // Get the date of the first occurrecne of the appointment. startDate = apptRec->when->date; switch (apptRec->repeat->repeatType) { // Daily repeating appointment. case repeatDaily: dateInDays = DateToDays (date); startInDays = DateToDays (startDate); onDate = ((dateInDays - startInDays) % freq) == 0; break; // Weekly repeating appointment (ex: every Monday and Friday). // Yes, weekly repeating appointment can occur more then once a // week. case repeatWeekly: // Are we on a day of the week that the appointment repeats on. dayOfWeek = DayOfWeek (date.month, date.day, date.year+firstYear); onDate = ((1 << dayOfWeek) & apptRec->repeat->repeatOn); if (! onDate) break; // Are we in a week in which the appointment occurrs, if not // move to that start of the next week in which the appointment // does occur. dateInDays = DateToDays (date); startInDays = DateToDays (startDate); firstDayOfWeek = (DayOfWeek (1, 1, firstYear) - apptRec->repeat->repeatStartOfWeek + daysInWeek) % daysInWeek; weeksDiff = (((dateInDays + firstDayOfWeek) / daysInWeek) - ((startInDays + firstDayOfWeek) / daysInWeek)) %freq; onDate = (weeksDiff == 0); break; // // Compute the first occurrence of the appointment that occurs // // on the same day of the week as the date passed. // startDayOfWeek = DayOfWeek (startDate.month, startDate.day, // startDate.year+firstYear); // startInDays = DateToDays (startDate); // if (startDayOfWeek < dayOfWeek) // startInDays += dayOfWeek - startDayOfWeek; // else if (startDayOfWeek > dayOfWeek) // startInDays += dayOfWeek+ (daysInWeek *freq) - startDayOfWeek; // // // Are we in a week in which the appointment repeats. // dateInDays = DateToDays (date); // onDate = (((dateInDays - startInDays) / daysInWeek) % freq) == 0; // break; // Monthly-by-day repeating appointment (ex: the 3rd Friday of every // month). case repeatMonthlyByDay: // Are we in a month in which the appointment repeats. onDate = ((((date.year - startDate.year) * monthsInYear) + (date.month - startDate.month)) % freq) == 0; if (! onDate) break; // Do the days of the month match (ex: 3rd Friday) dayOfMonth = DayOfMonth (date.month, date.day, date.year+firstYear); onDate = (dayOfMonth == apptRec->repeat->repeatOn); if (onDate) break; // If the appointment repeats on one of the last days of the month, // check if the date passed is also one of the last days of the // month. By last days of the month we mean: last sunday, // last monday, etc. if ((apptRec->repeat->repeatOn >= domLastSun) && (dayOfMonth >= dom4thSun)) { dayOfWeek = DayOfWeek (date.month, date.day, date.year+firstYear); dayInMonth = DaysInMonth (date.month, date.year+firstYear); onDate = (((date.day + daysInWeek) > dayInMonth) && (dayOfWeek == (apptRec->repeat->repeatOn % daysInWeek))); } break; // Monthly-by-date repeating appointment (ex: the 15th of every // month). case repeatMonthlyByDate: // Are we in a month in which the appointment repeats. onDate = ((((date.year - startDate.year) * monthsInYear) + (date.month - startDate.month)) % freq) == 0; if (! onDate) break; // Are we on the same day of the month as the start date. onDate = (date.day == startDate.day); if (onDate) break; // If the staring day of the appointment is greater then the // number of day in the month passed, and the day passed is the // last day of the month, then the appointment repeats on the day. dayInMonth = DaysInMonth (date.month, date.year+firstYear); onDate = ((startDate.day > dayInMonth) && (date.day == dayInMonth)); break; // Yearly repeating appointment. case repeatYearly: // Are we in a year in which the appointment repeats. onDate = ((date.year - startDate.year) % freq) == 0; if (! onDate) break; // Are we on the month and day that the appointment repeats. onDate = (date.month == startDate.month) && (date.day == startDate.day); if (onDate) break; // Specal leap day processing. if ( (startDate.month == february) && (startDate.day == 29) && (date.month == february) && (date.day == DaysInMonth (date.month, date.year+firstYear))) { onDate = true; } break; default: break; } // Check for an exception. if ((onDate) && (apptRec->exceptions)) { exceptions = &apptRec->exceptions->exception; for (i = 0; i < apptRec->exceptions->numExceptions; i++) { if (DateCompare (date, exceptions[i]) == 0) { onDate = false; break; } } } return (onDate); }
/*********************************************************************** * * FUNCTION: RepeatChangeType * * DESCRIPTION: This routine changes the ui gadgets in the repeat dialog * such that they match the newly selected repeat type. The * routine is called when one of the repeat type push buttons * are pushed. * * PARAMETERS: event - pointer to and event * * RETURNED: nothing * ***********************************************************************/ static void RepeatChangeType(EventType* event) { UInt16 id; FormType* frm = FrmGetFormPtr(RepeatForm); const RepeatType oldType = d.repeat_event_type; RepeatType newType; RepeatInfoType repeat; /* If the type if monthly default to monthly-by-date. */ newType = (RepeatType) (event->data.ctlSelect.controlID - RepeatNone); if (newType > repeatWeekly) newType++; if (oldType == newType) return; /* Initialize the UI gadgets. */ if (newType == d.tmp_repeat.repeatType) { RepeatSetUIValues(frm, &d.tmp_repeat); /* ** If reselecting current repeat type, reset d.repeat_end_date global ** to current date so if user attemps to "choose" a new day, the ** default matches date displayed as opposed to last date picked ** last in choose form. */ d.repeat_end_date = d.tmp_repeat.repeatEndDate; } else { repeat.repeatType = newType; /* ** When switching to a repeat type different from the current ** setting, always start user with default end date and frequency ** settings. */ DateToInt(repeat.repeatEndDate) = defaultRepeatEndDate; DateToInt(d.repeat_end_date) = defaultRepeatEndDate; repeat.repeatFrequency = defaultRepeatFrequency; repeat.repeatStartOfWeek = PrefGetPreference(prefWeekStartDay); if (newType == repeatWeekly) { repeat.repeatOn = (1 << DayOfWeek(d.frm_date.month, d.frm_date.day, d.frm_date.year/*+firstYear*/)); } else if (newType == repeatMonthlyByDay) { repeat.repeatOn = DayOfMonth(d.frm_date.month, d.frm_date.day, d.frm_date.year/* + firstYear*/); } else { repeat.repeatOn = 0; } RepeatSetUIValues (frm, &repeat); } /* ** Hide the UI gadgets that are unique to the repeat type we are ** no longer editing. */ switch (oldType) { case repeatNone: HideObject(frm, RepeatNoRepeatLabel); break; case repeatHourly: HideObject(frm, RepeatHoursLabel); break; case repeatDaily: HideObject(frm, RepeatDaysLabel); break; case repeatWeekly: HideObject(frm, RepeatWeeksLabel); for (id = RepeatRepeatOnLabel; id <= RepeatDayOfWeek7PushButton; id++) HideObject (frm, id); break; case repeatMonthlyByDay: case repeatMonthlyByDate: HideObject(frm, RepeatMonthsLabel); for (id = RepeatByLabel; id <= RepeatByDatePushButton; id++) HideObject (frm, id); break; case repeatYearly: HideObject(frm, RepeatYearsLabel); break; } /* Handle switching to or from "no" repeat. */ if (oldType == repeatNone) { ShowObject(frm, RepeatEveryLabel); ShowObject(frm, RepeatFrequenceField); ShowObject(frm, RepeatEndOnLabel); ShowObject(frm, RepeatEndOnTrigger); } else if (newType == repeatNone) { HideObject(frm, RepeatEveryLabel); HideObject(frm, RepeatFrequenceField); HideObject(frm, RepeatEndOnLabel); HideObject(frm, RepeatEndOnTrigger); } /* Show the UI object that are appropriate for the new repeat type. */ switch (newType) { case repeatNone: ShowObject(frm, RepeatNoRepeatLabel); break; case repeatHourly: ShowObject(frm, RepeatHoursLabel); break; case repeatDaily: ShowObject(frm, RepeatDaysLabel); break; case repeatWeekly: ShowObject(frm, RepeatWeeksLabel); ShowObject(frm, RepeatRepeatOnLabel); for (id = RepeatRepeatOnLabel; id <= RepeatDayOfWeek7PushButton; id++) ShowObject(frm, id); break; case repeatMonthlyByDay: case repeatMonthlyByDate: ShowObject(frm, RepeatMonthsLabel); ShowObject(frm, RepeatByLabel); ShowObject(frm, RepeatByDayPushButton); ShowObject(frm, RepeatByDatePushButton); break; case repeatYearly: ShowObject(frm, RepeatYearsLabel); break; } d.repeat_event_type = newType; /* Update the display of the repeat descrition. */ RepeatDrawDescription(frm); }
void MonthDayRuleTest::test_utilities() { int yearIndex; SetDate date; Year year ( DateUtil::year()); Date newYearDate (year, Month(1), DayOfMonth(1)); Date july4Date (year, Month(7), DayOfMonth(4)); Date christmasDate(year, Month(12), DayOfMonth(25)); //test: MontDayRule::virtual Date calcDate(const Year& year) const ; MonthDayRule newYearRule ("Rule", Month(1), DayOfMonth(1)); date = newYearRule.calcDate(year); CPPUNIT_ASSERT(newYearDate == *date.begin()); for (yearIndex = year.getValue(); yearIndex <= year.getValue() + 50; ++yearIndex){ date = newYearRule.calcDate(Year(yearIndex)); CPPUNIT_ASSERT(newYearDate == *date.begin()); newYearDate.addYear(1); } MonthDayRule july4Rule ("July4Rule", Month(7), DayOfMonth(4)); date = july4Rule.calcDate(year); CPPUNIT_ASSERT(july4Date == *date.begin()); MonthDayRule christmasRule("ChristmasRule", Month(12), DayOfMonth(25)); date = christmasRule.calcDate(year); CPPUNIT_ASSERT(christmasDate == *date.begin()); //Test for weekendAdjustment WeekendRuleSharedPtr weekendRulePtr(new WeekendRule("WeekendRule")); weekendRulePtr->addDay(WeekDay::Saturday); weekendRulePtr->addDay(WeekDay::Sunday); MonthDayRule adjustingNewYearRule ("AdjustingNewYear", Month(1), DayOfMonth(1)); adjustingNewYearRule.setStartEffectiveDate(20110101); adjustingNewYearRule.setWeekendAdjustment(WeekendAdjustment::ClosestWeekDay); adjustingNewYearRule.setWeekendRule(weekendRulePtr); //First check for Saturday -> prior Friday date = adjustingNewYearRule.calcDate(Year(2011)); CPPUNIT_ASSERT(Date(20101231) == *date.begin()); //First check for Sunday -> next Monday date = adjustingNewYearRule.calcDate(Year(2012)); CPPUNIT_ASSERT(Date(20120102) == *date.begin()); //Check for no adjustment is required date = adjustingNewYearRule.calcDate(Year(2013)); CPPUNIT_ASSERT(Date(20130101) == *date.begin()); //Rule is disabled try{ newYearRule.setEnabledFlag(false); newYearRule.calcDate(year); } catch (BaseException& ex){ CAUGHT_EXCEPTION(ex,"Calculation called on disabled rule"); } newYearRule.setEnabledFlag(true); //Rule start date year > calc year try{ newYearRule.calcDate(Year(2010)); } catch (BaseException& ex){ CAUGHT_EXCEPTION(ex,"Calculation called for year before rule is in effect"); } //Rule calc year > rule end date year try{ newYearRule.setEndEffectiveDate(20121231); newYearRule.calcDate(Year(2030)); } catch (BaseException& ex){ CAUGHT_EXCEPTION(ex,"Calculation called for year after rule is in effect"); } }
/*********************************************************************** * * FUNCTION: RepeatGetUIValues * * DESCRIPTION: This routine gets the current repeat settings of the * ui gadgets in the repeat dialog box * * * PARAMETERS: frm - pointer to the repeat dialog * repeatP - RepeatInfoType structure (fill-in by this routine) * * RETURNED: nothing * ***********************************************************************/ void RepeatGetUIValues (FormType* frm, RepeatInfoType* repeatP) { UInt16 freq; UInt16 i; UInt16 id; UInt16 index; Char* str = NULL; /* Get the repeat type. */ index = FrmGetControlGroupSelection(frm, RepeatTypeGroup); id = FrmGetObjectId(frm, index); if (id == RepeatYearly) { repeatP->repeatType = repeatYearly; } else if (id <= RepeatWeekly) { repeatP->repeatType = (RepeatType) (id - RepeatNone); } else { index = FrmGetControlGroupSelection(frm, RepeatByGroup); id = FrmGetObjectId(frm, index); if (id == RepeatByDayPushButton) repeatP->repeatType = repeatMonthlyByDay; else repeatP->repeatType = repeatMonthlyByDate; } /* Get the repeat end date. */ repeatP->repeatEndDate = d.repeat_end_date; /* Get the repeat frequency. */ str = FldGetTextPtr(GetObjectPointer(frm, RepeatFrequenceField)); if (str) freq = StrAToI(str); else freq = 0; if (freq) repeatP->repeatFrequency = freq; else repeatP->repeatFrequency = 1; /* ** Get the start day of week. If the original repeat type, that is the ** repeat type when the dialog was first displayed, is weekly then ** use the start date in the repeat info (the unedit data), otherwise ** use the current start of week. */ if (repeatP->repeatType == repeatWeekly) { if (d.tmp_repeat.repeatType == repeatWeekly) repeatP->repeatStartOfWeek = d.tmp_repeat.repeatStartOfWeek; else repeatP->repeatStartOfWeek = PrefGetPreference(prefWeekStartDay); } else { /* For all other repeat types, the repeatStartOfWeek field is meaningless. */ repeatP->repeatStartOfWeek = 0; } /* If the repeat type is weekly, get the day of the week the event repeats on. */ if (repeatP->repeatType == repeatWeekly) { repeatP->repeatOn = 0; index = FrmGetObjectIndex(frm, RepeatDayOfWeek1PushButton); for (i = 0; i < daysInWeek ; i++) { if (FrmGetControlValue(frm, index + ((i - d.repeat_start_of_week + daysInWeek) % daysInWeek))) repeatP->repeatOn |= (1 << i); } } else if (repeatP->repeatType == repeatMonthlyByDay) { /* ** If the repeat type is monthly by day, get the day of the month (ex: ** first Friday) of the start date of the event. */ if (d.tmp_repeat.repeatType == repeatMonthlyByDay) repeatP->repeatOn = d.tmp_repeat.repeatOn; else repeatP->repeatOn = DayOfMonth (d.frm_date.month, d.frm_date.day, d.frm_date.year); } else { /* For all other repeat types, the repeatOn field is meaningless. */ repeatP->repeatOn = 0; } }