home *** CD-ROM | disk | FTP | other *** search
- /*
- tmadd.c 2/7/87
-
- % tm_AddSecs, tm_AddDays, tm_Adjust, tm_DaysInMonth, tm_DayOfWeek
- tm_WeekDay, tm_IsValid
-
- Written by John Cooke.
-
- OWL 1.2
- Copyright (c) 1986-1989, by Oakland Group, Inc.
- ALL RIGHTS RESERVED.
-
- Revision History:
- -----------------
- 10/02/87 jmd added tm_Now() function.
- 3/04/88 jdc fixed tm_mday == 0 bug in tm_Adjust.
- 8/20/88 jmd removed some unused variables
- 9/17/88 jmd added tm_DayOfWeek and tm_DaysInMonth, preened
-
- 6/25/89 jmd added OEXTERNs
- 7/18/89 pmcm fixed tm_AddDays offby 1 calc of days f/367+ add t/a leap yr
-
- 8/07/89 jmd renamed from cstime.c
- 3/28/90 jmd ansi-fied
- 6/25/90 jdc fixed starting leapyear AddDays bug
- 6/27/90 mla fixed pmcm's initials, but not the length thereof
- 7/04/90 jdc merged
- 8/01/90 ted Moved to OWL; include oaktime.h not cstime.h.
- 10/23/90 jmd fixed leapyear (jan 2101) bug in tm_WeekDay
- */
-
- #include "oakhead.h"
- #include "ostdlib.h" /* for oabs() */
-
- #include <time.h>
- #include "oaktime.h"
-
- OSTATIC struct tm *tm_WeekDay(struct tm *t);
-
- struct tm *tm_AddSecs(struct tm *t, long seconds)
- /*
- DESCRIPTION:
- The tm_AddSecs function adds an elapsed time in seconds to
- t and places the new adjusted time in the static
- result structure.
- RETURNS:
- Returns the result pointer.
- NOTE:
- the function uses a statically allocated structure to hold
- its result. Subsequent calls to certain tm functions will
- destroy the results of previous calls. If a result is needed
- copy it to another tm struct.
- */
- {
- result = &time_result;
-
- tm_Copy(result,t);
- result->tm_mday += (int) (seconds/(60L*60L*24L));
- seconds = seconds%(60L*60L*24L);
-
- result->tm_hour += (int) (seconds/(60L*60L));
- seconds = seconds%(60L*60L);
-
- result->tm_sec += (int) seconds;
-
- return(tm_Adjust(result));
- }
-
- struct tm *tm_AddDays(struct tm *t, long days)
- /*
- DESCRIPTION:
- The tm_AddDays function adds an elapsed time in days to
- t and places the new adjusted time in the static
- result structure. If the t is zero then the
- function returns the broken down elapsed time.
- RETURNS:
- Returns the result pointer.
- NOTE:
- the function uses a statically allocated structure to hold
- its result. Subsequent calls to certain tm functions will
- destroy the results of previous calls. If a result is needed
- copy it to another tm struct.
- */
- {
- register int i;
- int leap, years, leapyears, mod;
-
- result = &time_result;
-
- if (tm_IsValid(t) == FALSE && t->tm_year != 0) tm_Adjust(t);
- tm_Copy(result,t);
-
- leap = tm_LeapYear(t->tm_year);
- if (days > 366) {
- if (leap && t->tm_mon > 1) {
- leap=0;
- }
- if (leap && t->tm_mon == 1 && t->tm_mday == 29) {
- leap=0;
- }
- years = (int)(days/365L);
- result->tm_year += years;
- leapyears = years/4;
- if ((mod = (years%4)-1) >= 0) {
- for (i = 0; i <= mod; i++) {
- if (tm_LeapYear(t->tm_year+i)) leapyears++;
- }
- }
- years -= leapyears;
- days -= (leapyears*366L + years*365L);
- }
- if (days < -366) {
- if (leap && t->tm_mon <= 1) leap=0;
- years = (int)(days/365L);
- result->tm_year += years;
- leapyears = years/4;
- if ((mod = (years%4)) < 0) {
- for (i = -1; i >= mod; i--) {
- if (tm_LeapYear(t->tm_year+i)) {
- leapyears--;
- }
- if (i == mod && t->tm_mon >= 2 && tm_LeapYear(t->tm_year+i)) {
- leapyears++;
- }
- }
- }
- years -= leapyears;
- days -= (leapyears*366L + years*365L + leap);
- }
-
- result->tm_mday += (int)days;
- return(tm_Adjust(result));
- }
-
- struct tm *tm_Adjust(struct tm *t)
- /*
- DESCRIPTION:
- The tm_Adjust function adjusts all the elements of t so that
- it contains a valid date. The routine starts with the smallest
- units and adjusts overflows until everything is correct. Then
- it calculates wday (day of the week), yday (day of the year), and
- sets the tm_isdst (is daylight savings time) flag.
- NOTE:
- this function makes use of the static result structure.
- */
- {
- int overflow, leap;
-
- result = &time_result;
- overflow = 0;
-
- if (t->tm_sec >= 60) {
- overflow = t->tm_sec/60;
- t->tm_sec = t->tm_sec%60;
- }
- if (t->tm_sec < 0) {
- overflow = (t->tm_sec/60)-1;
- t->tm_sec += oabs(overflow*60);
- }
- t->tm_min += overflow;
- overflow = 0;
- if (t->tm_min >= 60) {
- overflow = t->tm_min/60;
- t->tm_min = t->tm_min%60;
- }
- if (t->tm_min < 0) {
- overflow = (t->tm_min/60)-1;
- t->tm_min += oabs(overflow*60);
- }
- t->tm_hour += overflow;
- overflow = 0;
- if (t->tm_hour >= 24) {
- overflow = t->tm_hour/24;
- t->tm_hour = t->tm_hour%24;
- }
- if (t->tm_hour < 0) {
- overflow = (t->tm_hour/24)-1;
- t->tm_hour += oabs(overflow*24);
- }
- if (t->tm_mon >= 12) {
- t->tm_year += t->tm_mon/12;
- t->tm_mon = t->tm_mon%12;
- }
- if (t->tm_mon < 0) {
- t->tm_year += (t->tm_mon/12)-1;
- t->tm_mon = (t->tm_mon%12)+12;
- }
-
- t->tm_mday += overflow;
- leap = tm_LeapYear(t->tm_year);
- while (t->tm_mday > tm_daytab[leap][t->tm_mon]) {
- t->tm_mday -= tm_daytab[leap][t->tm_mon];
- t->tm_mon++;
- if (t->tm_mon == 12) {
- t->tm_year++;
- leap = tm_LeapYear(t->tm_year);
- t->tm_mon = 0;
- }
- }
- while (t->tm_mday <= 0) {
- t->tm_mon--;
- if (t->tm_mon == -1) {
- t->tm_year--;
- leap = tm_LeapYear(t->tm_year);
- t->tm_mon = 11;
- }
- t->tm_mday += tm_daytab[leap][t->tm_mon];
- }
-
- if (t->tm_mday > 0) {
- t->tm_wday = tm_WeekDay(t)->tm_wday;
- t->tm_yday = result->tm_yday;
- t->tm_isdst = FALSE;
-
- /* set daylight savings time flag
- ---warning--- this code is subject to the whim of congress */
-
- if (t->tm_mon > 3 && t->tm_mon < 9) {
- t->tm_isdst = TRUE;
- }
- if (t->tm_mon == 3 && t->tm_mday >= 28) {
- t->tm_isdst = TRUE;
- }
- if (t->tm_mon == 9 && t->tm_mday < 28) {
- t->tm_isdst = TRUE;
- }
- }
-
- return(t);
- }
-
- int tm_DaysInMonth(int month, int year)
- /*
- Returns the number of days in the given month.
- */
- {
- return(tm_daytab[tm_LeapYear(year)][month]);
- }
-
- int tm_DayOfWeek(int mday, int month, int year)
- /*
- (Gregorian date function)
- Returns the week day of the given day in the given month in the given year.
- (0 - 6) 0 = Sunday.
- */
- {
- struct tm time;
-
- tm_Zero(&time);
-
- time.tm_year = year;
- time.tm_mon = month;
- time.tm_mday = mday;
-
- tm_Adjust(&time);
-
- return(time.tm_wday);
- }
-
- boolean tm_IsValid(struct tm *t)
- /*
- DESCRIPTION:
- The tm_IsValid function checks the validity of the time stored in
- struct tm *t.
- A valid date must meet the following criteria:
- tm_sec (0-59)
- tm_min (0-59)
- tm_hour (0-23)
- tm_mday (1-28,29,30,31) varies according to month and year.
- tm_mon (0-11)
- tm_year (>=0)
- tm_wday (0-6)
- tm_yday (0-364/365) varies according to year.
- tm_isdst ignored.
- RETURNS:
- Returns TRUE if the date is valid and FALSE otherwise.
- NOTE:
- this function makes use of the static result structure.
- */
- {
- result = &time_result;
-
- if (tm_IsTimeValid(t) == FALSE ||
- tm_IsDateValid(t) == FALSE ||
- t->tm_mday == 0 ||
- t->tm_wday != tm_WeekDay(t)->tm_wday ||
- t->tm_yday != result->tm_yday ) {
-
- return(FALSE);
- }
-
- return (TRUE);
- }
-
- static struct tm *tm_WeekDay(struct tm *t)
- /*
- places the proper weekday and yearday in the static result structure
- when passed a tm pointer, and returns the result pointer.
- */
- {
- register int i;
- int leap, leapyears, ydays, years;
- long days;
- result = &time_result;
-
- /* old
- leap = tm_LeapYear(t->tm_year);
- leapyears = ((t->tm_year-START_YEAR-1)/4);
- ydays = 0;
- days = leapyears*366L + (t->tm_year-START_YEAR-leapyears-1)*365L;
- */
-
- leap = tm_LeapYear(t->tm_year);
- ydays = 0;
- years = t->tm_year - 1;
-
- /* compute number of leapyears since starting time (year 0) */
- leapyears = (years / 4) - (years / 100) + (years / 400);
-
- /* now compute number of days since starting time */
- days = (long) leapyears + (years * 365L);
-
- for (i = 0; i < t->tm_mon; i++) {
- ydays += tm_daytab[leap][i];
- }
- ydays += t->tm_mday;
- days += (long)ydays;
- result->tm_wday =(int)((days+START_DAY)%7);
- result->tm_yday = ydays-1;
- return(result);
- }
-