home *** CD-ROM | disk | FTP | other *** search
- /* Date calculation routines for Reminder and ReminderCheck */
-
- /* $Id: CalcDate.c,v 1.1 1993/04/04 13:37:45 Matti_Rintala Exp $ */
-
- #include "Constants.h"
- #include "CalcDate.h"
-
- #define min(a,b) (((a)<(b)) ? (a) : (b))
-
- static monthlen[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
- /* makedate calculates next date that satisfies given conditions */
- void makedate(time_t *date, time_t *today,
- short dday, short dmonth, short dyear, short dwday) {
-
- struct tm d;
- int found;
- short year, month, day;
- short year_max, month_max, day_max;
- short year_now, month_now, day_now;
-
- d = *localtime(today); /* Current date */
- day_now = d.tm_mday;
- month_now = d.tm_mon + 1;
- year_now = d.tm_year + 1900;
-
- found = FALSE;
- year = dyear;
- if (year != 0)
- year_max = year; /* Year is not wildcard */
- else {
- year = year_now; /* Otherwise start form now */
- year_max = MAXYEAR;
- }
-
- /* Go through all possible years */
- for (; year <= year_max; year++) {
- /* If we are in the past, try another */
- if (year < year_now)
- continue;
-
- month = dmonth;
- if (month != 0)
- month_max = month; /* Month is not wildcard */
- else {
- month = (year == year_now) ? month_now : 1; /* Start from now */
- month_max = 12;
- }
-
- /* If we are in the past, try another year */
- if (year == year_now && month_max < month_now)
- continue;
-
- /* Go through all possible months */
- for (; month <= month_max; month++) {
- day = dday;
- day_max = monthlen[month-1] + ((year%4 == 0) ?
- ((year%400 == 0) ? 0 : 1) : 0);
- if (day != 0) {
- if (dwday == 0)
- day_max = day; /* No wildcards in day */
- else {
- day = min(day, day_max);
- day_max = min(day+6, day_max); /* Scope is one week */
- }
- }
- else { /* Day is a wildcard */
- day = (year == year_now && month == month_now) ? day_now : 1;
- }
-
- /* If we are in the past, try another month */
- if (year == year_now && month == month_now && day_max < day_now)
- continue;
-
- /* We should not start earlier than present */
- if (year == year_now && month == month_now && day < day_now)
- day = day_now;
-
- /* We have to find the day */
- for (; day <= day_max; day++) {
- if (dwday == 0 || dwday == weekday(day, month, year)) {
- found =TRUE;
- break;
- }
- }
- if (found) break;
- }
- if (found) break;
- }
-
- /* If found, use the date */
- if (found) {
- /* Now calculate the date */
- d.tm_sec = d.tm_min = d.tm_hour = 0;
- d.tm_mday = day;
- d.tm_mon = month - 1;
- d.tm_year = year - 1900;
-
- *date = mktime(&d); /* Make the date */
- }
- else {
- /* Else try previous one */
- makeprevdate(date, today, dday, dmonth, dyear, dwday);
- }
- }
-
- /* makeprevdate calculates previous date that satisfies given conditions */
- void makeprevdate(time_t *date, time_t *today,
- short dday, short dmonth, short dyear, short dwday) {
-
- struct tm d;
- int found;
- short year, month, day;
- short year_min, month_min, day_min;
- short year_now, month_now, day_now;
-
- d = *localtime(today); /* Current date */
- day_now = d.tm_mday;
- month_now = d.tm_mon + 1;
- year_now = d.tm_year + 1900;
-
- found = FALSE;
- year = dyear;
- if (year != 0)
- year_min = year; /* Year is not wildcard */
- else {
- year = year_now; /* Otherwise start form now */
- year_min = MINYEAR;
- }
-
- /* Go through all possible years */
- for (; year >= year_min; year--) {
- /* If we are in the future, try next */
- if (year > year_now)
- continue;
-
- month = dmonth;
- if (month != 0)
- month_min = month; /* Month is not wildcard */
- else {
- month = (year == year_now) ? month_now : 12; /* Start from now */
- month_min = 1;
- }
-
- /* If we are in the future, try another year */
- if (year == year_now && month_min > month_now)
- continue;
-
- /* Go through all possible months */
- for (; month >= month_min; month--) {
- day_min = dday;
- day = monthlen[month-1] + ((year%4 == 0) ?
- ((year%400 == 0) ? 0 : 1) : 0);
- if (day_min != 0) {
- if (dwday == 0)
- day = day_min; /* No wildcards in day */
- else {
- day = min(day_min+6, day); /* Scope is one week */
- }
- }
- else { /* Day is a wildcard */
- day = (year == year_now && month == month_now) ? day_now : day;
- day_min = 1;
- }
-
- /* If we are in the future, try another month */
- if (year == year_now && month == month_now && day_min > day_now)
- continue;
-
- /* We should not start later than present */
- if (year == year_now && month == month_now && day > day_now)
- day = day_now;
-
- /* We have to find the day */
- for (; day >= day_min; day--) {
- if (dwday == 0 || dwday == weekday(day, month, year)) {
- found =TRUE;
- break;
- }
- }
- if (found) break;
- }
- if (found) break;
- }
-
- d.tm_sec = d.tm_min = d.tm_hour = 0;
-
- /* If date found */
- if (found) {
- /* Now calculate the date */
- d.tm_mday = day;
- d.tm_mon = month - 1;
- d.tm_year = year - 1900;
- }
- else {
- /* Else use 1.1.1990 */
- d.tm_mday = 1;
- d.tm_mon = 0;
- d.tm_year = 90;
- }
-
- *date = mktime(&d); /* Make the date */
- }
-
- /* weekday gives the day of the week */
- short weekday(short day, short month, short year) {
-
- struct tm date;
- time_t time;
-
- date.tm_sec = date.tm_min = date.tm_hour = 0;
- date.tm_mday = day;
- date.tm_mon = month - 1;
- date.tm_year = year - 1900;
- time = mktime(&date); /* Make a time_t */
- date = *localtime(&time); /* Calculate back to struct */
-
- /* Day of the week is now in date */
- return (short)((date.tm_wday == 0) ? 7 : date.tm_wday);
- }
-
- /* gettoday gets today's date (without time of day) */
- void gettoday(time_t *today) {
-
- struct tm *tmptr;
-
- time(today); /* Get date */
-
- tmptr = localtime(today); /* Change to struct */
- /* Now zero all time of day fields */
- tmptr->tm_sec = tmptr->tm_min = tmptr->tm_hour = 0;
- *today = mktime(tmptr); /* Convert back to time_t */
- }
-
-