📄 datedb.c
字号:
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;
}
// 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: FindNextRepeat
*
* DESCRIPTION: This routine computes the date of the next
* occurrence of a repeating appointment.
*
* PARAMETERS: apptRec - a pointer to an appointment record
* date - passed: date to start from
* returned: date of next occurrence
* searchForward - search for the next occurrence before or after the
* specified date
*
* RETURNED: true if an occurrence was found
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 6/14/95 Initial Revision
* gap 09/25/00 Add capability to search for the most recent previous occurrence
* (needed for attention manager support)
* gap 02/14/01 fix some problems in the weekly repeating event
* reverse search code.
*
***********************************************************************/
static Boolean FindNextRepeat (ApptDBRecordPtr apptRec, DatePtr dateP, Boolean searchForward)
{
Int16 i;
Int32 adjust;
Int32 daysTilNext;
Int32 monthsTilNext;
UInt16 day;
UInt16 freq;
UInt16 year;
UInt16 weeksDiff;
UInt16 monthsDiff;
UInt16 daysInMonth;
UInt16 dayOfWeek;
UInt16 apptWeekDay;
UInt16 firstDayOfWeek;
UInt32 dateInDays;
UInt32 startInDays;
DateType start;
DateType date;
DateType next;
date = *dateP;
if (searchForward)
{
// Is the date passed after the end date of the appointment?
if (DateCompare (date, apptRec->repeat->repeatEndDate) > 0)
return (false);
// Is the date passed before the start date of the appointment?
if (DateCompare (date, apptRec->when->date) < 0)
date = apptRec->when->date;
}
else
{
// Is the date passed is before the start date of the appointment?
// return false now
if (DateCompare (date, apptRec->when->date) < 0)
return (false);
// Is the date passed after the end date of the appointment?
// search backwards from repeat end date for first valid occurrence.
if (DateCompare (date, apptRec->repeat->repeatEndDate) > 0)
date = apptRec->repeat->repeatEndDate;
}
// apptRec->repeat->repeatEndDate can be passed into this routine
// or be set in the else case above. Since apptNoEndDate is not a
// valid date (month is 15) set it must be set to the last date
// support by the current OS 12/31/31
if ( DateToInt(date) == apptNoEndDate)
date.month = 12;
// Get the frequency on occurrecne (ex: every 2nd day, every 3rd month, etc).
freq = apptRec->repeat->repeatFrequency;
// Get the date of the first occurrecne of the appointment.
start = apptRec->when->date;
switch (apptRec->repeat->repeatType)
{
// Daily repeating appointment.
case repeatDaily:
dateInDays = DateToDays (date);
startInDays = DateToDays (start);
if (searchForward)
daysTilNext = (dateInDays - startInDays + freq - 1) / freq * freq;
else
daysTilNext = (dateInDays - startInDays) / freq * freq;
if (startInDays + daysTilNext > (UInt32) maxDays)
return (false);
DateDaysToDate (startInDays + daysTilNext, &next);
break;
// Weekly repeating appointment (ex: every Monday and Friday).
// Yes, weekly repeating appointment can occur more then once a
// week.
case repeatWeekly:
dateInDays = DateToDays (date);
startInDays = DateToDays (start);
firstDayOfWeek = (DayOfWeek (1, 1, firstYear) -
apptRec->repeat->repeatStartOfWeek + daysInWeek) % daysInWeek;
dayOfWeek = DayOfWeek (date.month, date.day, date.year+firstYear);
apptWeekDay = (dayOfWeek - apptRec->repeat->repeatStartOfWeek +
daysInWeek) % daysInWeek;
// 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.
weeksDiff = (((dateInDays + firstDayOfWeek) / daysInWeek) -
((startInDays + firstDayOfWeek) / daysInWeek)) %freq;
if (weeksDiff)
{
if (searchForward)
{
adjust = ((freq - weeksDiff) * daysInWeek) - apptWeekDay;
apptWeekDay = 0;
dayOfWeek = (dayOfWeek + adjust) % daysInWeek;
}
else
{
adjust = (weeksDiff * daysInWeek) - ( (daysInWeek-1) - apptWeekDay);
apptWeekDay = 6;
dayOfWeek = (dayOfWeek - (adjust % daysInWeek) + daysInWeek) % daysInWeek;
}
}
else
adjust = 0;
// Find the next day on which the appointment repeats.
if (searchForward)
{
for (i = 0; i < daysInWeek; i++)
{
if (apptRec->repeat->repeatOn & (1 << dayOfWeek)) break;
adjust++;
if (++dayOfWeek == daysInWeek)
dayOfWeek = 0;
if (++apptWeekDay == daysInWeek)
adjust += (freq - 1) * daysInWeek;
}
if (dateInDays + adjust > (UInt32) maxDays)
return (false);
DateDaysToDate (dateInDays + adjust, &next);
}
else
{
for (i = 0; i < daysInWeek; i++)
{
if (apptRec->repeat->repeatOn & (1 << dayOfWeek)) break;
adjust++;
if (dayOfWeek == 0)
dayOfWeek = daysInWeek-1;
else
dayOfWeek--;
if (apptWeekDay == 0)
{
adjust += (freq - 1) * daysInWeek;
apptWeekDay = daysInWeek-1;
}
else
apptWeekDay --;
}
// determine if date goes past first day (unsigned int wraps around)
if (dateInDays - adjust > dateInDays)
return (false);
DateDaysToDate (dateInDays - adjust, &next);
}
break;
// Monthly-by-day repeating appointment (ex: the 3rd Friday of every
// month).
case repeatMonthlyByDay:
// Compute the number of month until the appointment repeats again.
if (searchForward)
monthsTilNext = ((((date.year - start.year) * monthsInYear) + (date.month - start.month)) + freq - 1) /freq * freq;
else
monthsTilNext = (((date.year - start.year) * monthsInYear) + (date.month - start.month)) /freq * freq;
while (true)
{
year = start.year + (start.month - 1 + monthsTilNext) / monthsInYear;
if (year >= numberOfYears)
return (false);
next.year = year;
next.month = (start.month - 1 + monthsTilNext) % monthsInYear + 1;
dayOfWeek = DayOfWeek (next.month, 1, next.year+firstYear);
if ((apptRec->repeat->repeatOn % daysInWeek) >= dayOfWeek)
day = apptRec->repeat->repeatOn - dayOfWeek + 1;
else
day = apptRec->repeat->repeatOn + daysInWeek - dayOfWeek + 1;
// If repeat-on day is between the last sunday and the last
// saturday, make sure we're not passed the end of the month.
if ( (apptRec->repeat->repeatOn >= domLastSun) &&
(day > DaysInMonth (next.month, next.year+firstYear)))
{
day -= daysInWeek;
}
next.day = day;
// Its posible that "next date" calculated above is
// before the date passed. If so, move forward
// by the length of the repeat freguency and perform
// the calculation again.
if (searchForward)
{
if ( DateToInt(date) > DateToInt (next))
monthsTilNext += freq;
else
break;
}
else
{
if ( DateToInt(date) < DateToInt (next))
monthsTilNext -= freq;
else
break;
}
}
break;
// Monthly-by-date repeating appointment (ex: the 15th of every
// month).
case repeatMonthlyByDate:
// Compute the number of month until the appointment repeats again.
monthsDiff = ((date.year - start.year) * monthsInYear) + (date.month - start.month);
if (searchForward)
{
monthsTilNext = (monthsDiff + freq - 1) / freq * freq;
if ((date.day > start.day) && (!(monthsDiff % freq)))
monthsTilNext += freq;
}
else
{
monthsTilNext = monthsDiff / freq * freq;
if ((date.day < start.day) && (!(monthsDiff % freq)))
monthsTilNext -= freq;
}
year = start.year + (start.month - 1 + monthsTilNext) / monthsInYear;
if (year >= numberOfYears)
return (false);
next.year = year;
next.month = (start.month - 1 + monthsTilNext) % monthsInYear + 1;
next.day = start.day;
// Make sure we're not passed the last day of the month.
daysInMonth = DaysInMonth (next.month, next.year+firstYear);
if (next.day > daysInMonth)
next.day = daysInMonth;
break;
// Yearly repeating appointment.
case repeatYearly:
next.day = start.day;
next.month = start.month;
if (searchForward)
{
year = start.year + ((date.year - start.year + freq - 1) / freq * freq);
if ( (date.month > start.month) ||
((date.month == start.month) && (date.day > start.day)) )
year += freq;
}
else
{
year = start.year + ((date.year - start.year) / freq * freq);
if ( (date.month < start.month) ||
((date.month == start.month) && (date.day < start.day)) )
year -= freq;
}
// Specal leap day processing.
if ( (next.month == february) && (next.day == 29) &&
(next.day > DaysInMonth (next.month, year+firstYear)))
{
next.day = DaysInMonth (next.month, year+firstYear);
}
if (year >= numberOfYears)
return (false);
next.year = year;
break;
}
if (searchForward)
{
// Is the next occurrence after the end date of the appointment?
if (DateCompare (next, apptRec->repeat->repeatEndDate) > 0)
return (false);
ErrFatalDisplayIf ((DateToInt (next) < DateToInt (*dateP)),
"Calculation error");
}
else
{
// Is the next occurrence before the start date of the appointment?
if (DateCompare (next, apptRec->when->date) < 0)
return (false);
}
*dateP = next;
return (true);
}
/***********************************************************************
*
* FUNCTION: NextRepeat
*
* DESCRIPTION: This routine computes the date of the next
* occurrence of a repeating appointment.
*
* PARAMETERS: apptRec - a pointer to an appointment record
* date - passed: date to start from
* returned: date of next occurrence
*
* RETURNED: true if the appointment occurs again
*
* REVISION HISTORY:
* Name Date Description
* ---- ---- -----------
* art 6/14/95 Initial Revision
*
***********************************************************************/
/*
static Boolean NextRepeat (ApptDBRecordPtr apptRec, DatePtr dateP)
{
Int16 i;
UInt16 day;
UInt16 freq;
UInt16 year;
UInt16 adjust;
UInt16 weeksDiff;
UInt16 monthsDiff;
UInt16 daysInMonth;
UInt16 dayOfWeek;
UInt16 apptWeekDay;
UInt16 firstDayOfWeek;
UInt16 daysTilNext;
UInt16 monthsTilNext;
UInt32 dateInDays;
UInt32 startInDays;
DateType start;
DateType date;
DateType next;
date = *dateP;
// Is the date passed after the end date of the appointment?
if (DateCompare (date, apptRec->repeat->repeatEndDate) > 0)
return (false);
// Is the date passed before the start date of the appointment?
if (DateCompare (date, apptRec->when->date) < 0)
date = apptRec->when->date;
// Get the frequency on occurrecne (ex: every 2nd day, every 3rd month, etc).
freq = apptRec->repeat->repeatFrequency;
// Get the date of the first occurrecne of the appointment.
start = apptRec->when->date;
switch (apptRec->repeat->repeatType)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -