home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / Samples / CSAPE32.ARJ / SOURCE / OWLSCR / TMADD.C < prev    next >
Encoding:
C/C++ Source or Header  |  1990-10-23  |  7.9 KB  |  332 lines

  1. /*
  2.     tmadd.c    2/7/87
  3.  
  4.     % tm_AddSecs, tm_AddDays, tm_Adjust, tm_DaysInMonth, tm_DayOfWeek
  5.       tm_WeekDay, tm_IsValid
  6.  
  7.     Written by John Cooke.
  8.  
  9.     OWL 1.2
  10.     Copyright (c) 1986-1989, by Oakland Group, Inc.
  11.     ALL RIGHTS RESERVED.
  12.  
  13.     Revision History:
  14.     -----------------
  15.     10/02/87 jmd    added tm_Now() function.
  16.      3/04/88 jdc    fixed tm_mday == 0 bug in tm_Adjust.    
  17.      8/20/88 jmd    removed some unused variables
  18.      9/17/88 jmd    added tm_DayOfWeek and tm_DaysInMonth, preened
  19.  
  20.      6/25/89 jmd    added OEXTERNs
  21.      7/18/89 pmcm   fixed tm_AddDays offby 1 calc of days f/367+ add t/a leap yr
  22.  
  23.      8/07/89 jmd    renamed from cstime.c
  24.      3/28/90 jmd    ansi-fied
  25.      6/25/90 jdc    fixed starting leapyear AddDays bug
  26.      6/27/90 mla    fixed pmcm's initials, but not the length thereof
  27.      7/04/90 jdc    merged
  28.      8/01/90 ted    Moved to OWL; include oaktime.h not cstime.h.
  29.     10/23/90 jmd    fixed leapyear (jan 2101) bug in tm_WeekDay
  30. */
  31.  
  32. #include "oakhead.h"
  33. #include "ostdlib.h"    /* for oabs() */
  34.  
  35. #include <time.h>
  36. #include "oaktime.h"
  37.  
  38. OSTATIC struct tm *tm_WeekDay(struct tm *t);
  39.  
  40. struct tm *tm_AddSecs(struct tm *t, long seconds)
  41. /*
  42. DESCRIPTION:
  43.     The tm_AddSecs function adds an elapsed time in seconds to
  44.     t and places the new adjusted time in the static 
  45.     result structure.
  46. RETURNS:
  47.     Returns the result pointer.
  48. NOTE:
  49.     the function uses a statically allocated structure to hold
  50.     its result.  Subsequent calls to certain tm functions will 
  51.     destroy the    results of previous calls.  If a result is needed
  52.     copy it to another tm struct.
  53. */
  54. {
  55.     result = &time_result;
  56.     
  57.     tm_Copy(result,t);
  58.     result->tm_mday += (int) (seconds/(60L*60L*24L));
  59.     seconds = seconds%(60L*60L*24L);
  60.  
  61.     result->tm_hour += (int) (seconds/(60L*60L));
  62.     seconds = seconds%(60L*60L);
  63.  
  64.     result->tm_sec += (int) seconds;
  65.     
  66.     return(tm_Adjust(result));
  67. }
  68.  
  69. struct tm *tm_AddDays(struct tm *t, long days)
  70. /*
  71. DESCRIPTION:
  72.     The tm_AddDays function adds an elapsed time in days to
  73.     t and places the new adjusted time in the static 
  74.     result structure.  If the t is zero then the
  75.     function returns the broken down elapsed time. 
  76. RETURNS:
  77.     Returns the result pointer.
  78. NOTE:
  79.     the function uses a statically allocated structure to hold
  80.     its result.  Subsequent calls to certain tm functions will 
  81.     destroy the    results of previous calls.  If a result is needed
  82.     copy it to another tm struct.
  83. */
  84. {
  85.     register int i;
  86.     int leap, years, leapyears, mod;
  87.  
  88.     result = &time_result;
  89.     
  90.     if (tm_IsValid(t) == FALSE && t->tm_year != 0) tm_Adjust(t); 
  91.     tm_Copy(result,t);
  92.     
  93.     leap = tm_LeapYear(t->tm_year);
  94.     if (days > 366) {
  95.         if (leap && t->tm_mon > 1) {
  96.             leap=0;
  97.         }
  98.         if (leap && t->tm_mon == 1 && t->tm_mday == 29) {
  99.             leap=0;
  100.         }
  101.         years = (int)(days/365L);
  102.         result->tm_year += years;
  103.         leapyears = years/4;
  104.         if ((mod = (years%4)-1) >= 0) {
  105.             for (i = 0; i <= mod; i++) {
  106.                 if (tm_LeapYear(t->tm_year+i)) leapyears++;
  107.             }
  108.         }
  109.         years -= leapyears;
  110.         days -= (leapyears*366L + years*365L);
  111.     }
  112.     if (days < -366) {
  113.         if (leap && t->tm_mon <= 1) leap=0;
  114.         years = (int)(days/365L);
  115.         result->tm_year += years;
  116.         leapyears = years/4;
  117.         if ((mod = (years%4)) < 0) {
  118.             for (i = -1; i >= mod; i--) {
  119.                 if (tm_LeapYear(t->tm_year+i)) {
  120.                     leapyears--;
  121.                 }
  122.                 if (i == mod && t->tm_mon >= 2 && tm_LeapYear(t->tm_year+i)) {
  123.                     leapyears++;
  124.                 }
  125.             }
  126.         }
  127.         years -= leapyears;
  128.         days -= (leapyears*366L + years*365L + leap);
  129.     }
  130.  
  131.     result->tm_mday += (int)days;
  132.     return(tm_Adjust(result));
  133. }
  134.  
  135. struct tm *tm_Adjust(struct tm *t)
  136. /*
  137. DESCRIPTION:
  138.     The tm_Adjust function adjusts all the elements of t so that
  139.     it contains a valid date.  The routine starts with the smallest
  140.     units and adjusts overflows until everything is correct.  Then
  141.     it calculates wday (day of the week), yday (day of the year), and
  142.     sets the tm_isdst (is daylight savings time) flag.
  143. NOTE:
  144.     this function makes use of the static result structure.
  145. */
  146. {
  147.     int overflow, leap;
  148.  
  149.     result = &time_result;
  150.     overflow = 0;
  151.     
  152.     if (t->tm_sec >= 60) {
  153.         overflow = t->tm_sec/60;
  154.         t->tm_sec =    t->tm_sec%60;
  155.     }
  156.     if (t->tm_sec < 0) {
  157.         overflow = (t->tm_sec/60)-1;
  158.         t->tm_sec += oabs(overflow*60);
  159.     }
  160.     t->tm_min += overflow;
  161.     overflow = 0;
  162.     if (t->tm_min >= 60) {
  163.         overflow = t->tm_min/60;
  164.         t->tm_min = t->tm_min%60;
  165.     }
  166.     if (t->tm_min < 0) {
  167.         overflow = (t->tm_min/60)-1;
  168.         t->tm_min += oabs(overflow*60);
  169.     }
  170.     t->tm_hour += overflow;
  171.     overflow = 0;
  172.     if (t->tm_hour >= 24) {
  173.         overflow = t->tm_hour/24;
  174.         t->tm_hour = t->tm_hour%24;
  175.     }
  176.     if (t->tm_hour < 0) {
  177.         overflow = (t->tm_hour/24)-1;
  178.         t->tm_hour += oabs(overflow*24);
  179.     }
  180.     if (t->tm_mon >= 12) {
  181.         t->tm_year += t->tm_mon/12;
  182.         t->tm_mon = t->tm_mon%12;
  183.     }
  184.     if (t->tm_mon < 0) {
  185.         t->tm_year += (t->tm_mon/12)-1;
  186.         t->tm_mon = (t->tm_mon%12)+12;
  187.     }
  188.  
  189.     t->tm_mday += overflow;
  190.     leap = tm_LeapYear(t->tm_year);
  191.     while (t->tm_mday > tm_daytab[leap][t->tm_mon]) {
  192.         t->tm_mday -= tm_daytab[leap][t->tm_mon];
  193.         t->tm_mon++;
  194.         if (t->tm_mon == 12) {
  195.             t->tm_year++;
  196.             leap = tm_LeapYear(t->tm_year);
  197.             t->tm_mon = 0;
  198.         } 
  199.     }            
  200.     while (t->tm_mday <= 0) {
  201.         t->tm_mon--;
  202.         if (t->tm_mon == -1) {
  203.             t->tm_year--;
  204.             leap = tm_LeapYear(t->tm_year);
  205.             t->tm_mon = 11;
  206.         } 
  207.         t->tm_mday += tm_daytab[leap][t->tm_mon];
  208.     }            
  209.  
  210.     if (t->tm_mday > 0) {
  211.         t->tm_wday = tm_WeekDay(t)->tm_wday;
  212.         t->tm_yday = result->tm_yday;
  213.         t->tm_isdst = FALSE;
  214.  
  215.     /* set daylight savings time flag 
  216.        ---warning--- this code is subject to the whim of congress */
  217.  
  218.         if (t->tm_mon > 3 && t->tm_mon < 9) {
  219.             t->tm_isdst = TRUE;
  220.         }
  221.         if (t->tm_mon == 3 && t->tm_mday >= 28) {
  222.             t->tm_isdst = TRUE;
  223.         }
  224.         if (t->tm_mon == 9 && t->tm_mday < 28) {
  225.             t->tm_isdst = TRUE;
  226.         }
  227.     }
  228.  
  229.     return(t);
  230. }
  231.  
  232. int tm_DaysInMonth(int month, int year)
  233. /*
  234.     Returns the number of days in the given month.
  235. */
  236. {
  237.     return(tm_daytab[tm_LeapYear(year)][month]);
  238. }
  239.  
  240. int tm_DayOfWeek(int mday, int month, int year)
  241. /*
  242.     (Gregorian date function)
  243.     Returns the week day of the given day in the given month in the given year.
  244.     (0 - 6) 0 = Sunday.
  245. */
  246. {
  247.     struct tm time;
  248.  
  249.     tm_Zero(&time);
  250.  
  251.     time.tm_year = year;
  252.     time.tm_mon = month;
  253.     time.tm_mday = mday;
  254.  
  255.     tm_Adjust(&time);
  256.  
  257.     return(time.tm_wday);
  258. }
  259.  
  260. boolean tm_IsValid(struct tm *t)
  261. /*
  262. DESCRIPTION:
  263.     The tm_IsValid function checks the validity of the time stored in
  264.     struct tm *t.
  265.     A valid date must meet the following criteria:
  266.         tm_sec            (0-59)
  267.         tm_min            (0-59)
  268.         tm_hour            (0-23)
  269.         tm_mday            (1-28,29,30,31)  varies according to month and year.
  270.         tm_mon            (0-11)
  271.         tm_year            (>=0)
  272.         tm_wday            (0-6)
  273.         tm_yday            (0-364/365)    varies according to year.
  274.         tm_isdst        ignored.
  275. RETURNS:
  276.     Returns TRUE if the date is valid and FALSE otherwise.
  277. NOTE:
  278.     this function makes use of the static result structure.
  279. */
  280. {
  281.     result = &time_result;
  282.  
  283.     if (tm_IsTimeValid(t) == FALSE || 
  284.         tm_IsDateValid(t) == FALSE ||
  285.         t->tm_mday == 0 ||
  286.         t->tm_wday != tm_WeekDay(t)->tm_wday ||
  287.         t->tm_yday != result->tm_yday ) {
  288.  
  289.         return(FALSE);
  290.     }
  291.  
  292.     return (TRUE);
  293. }
  294.  
  295. static struct tm *tm_WeekDay(struct tm *t)
  296. /*
  297.     places the proper weekday and yearday in the static result structure
  298.     when passed a tm pointer, and returns the result pointer.
  299. */
  300. {
  301.     register int i;
  302.     int leap, leapyears, ydays, years;
  303.     long days;
  304.     result = &time_result;
  305.  
  306. /* old 
  307.     leap = tm_LeapYear(t->tm_year);
  308.     leapyears = ((t->tm_year-START_YEAR-1)/4);
  309.     ydays = 0;
  310.     days = leapyears*366L + (t->tm_year-START_YEAR-leapyears-1)*365L;
  311. */
  312.  
  313.     leap = tm_LeapYear(t->tm_year);
  314.     ydays = 0;
  315.     years = t->tm_year - 1;
  316.  
  317.     /* compute number of leapyears since starting time (year 0) */
  318.     leapyears = (years / 4) - (years / 100) + (years / 400);
  319.  
  320.     /* now compute number of days since starting time */
  321.     days = (long) leapyears + (years * 365L);
  322.  
  323.     for (i = 0; i < t->tm_mon; i++) {
  324.         ydays += tm_daytab[leap][i];
  325.     }
  326.     ydays += t->tm_mday;
  327.     days += (long)ydays;
  328.     result->tm_wday =(int)((days+START_DAY)%7);
  329.     result->tm_yday = ydays-1;
  330.     return(result);
  331. }
  332.