home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / zip201.zip / mktime.c < prev    next >
C/C++ Source or Header  |  1992-08-20  |  4KB  |  108 lines

  1. /* free mktime function
  2.    Copyright 1988, 1989 by David MacKenzie <djm@ai.mit.edu>
  3.    and Michael Haertel <mike@ai.mit.edu>
  4.    Unlimited distribution permitted provided this copyright notice is
  5.    retained and any functional modifications are prominently identified.  */
  6.  
  7. /* Note: This version of mktime is ignorant of the tzfile; it does not
  8.    return correct results during the few hours around when daylight savings
  9.    time goes in to or out of effect.  It also does not allow or adjust
  10.    for invalid values in any of the fields, contrary to the ANSI C
  11.    specification. */
  12.  
  13. #ifdef MKTIME_MISSING
  14. #include <sys/types.h>
  15. #include <time.h>
  16.  
  17. time_t mkgmtime ();
  18.  
  19. /* Return the equivalent in seconds past 12:00:00 a.m. Jan 1, 1970 GMT
  20.    of the local time and date in the exploded time structure `tm',
  21.    and set `tm->tm_yday', `tm->tm_wday', and `tm->tm_isdst'.
  22.    Return -1 if any of the other fields in `tm' has an invalid value. */
  23.  
  24. time_t
  25. mktime (tm)
  26.      struct tm *tm;
  27. {
  28.   struct tm save_tm;            /* Copy of contents of `*tm'. */
  29.   struct tm *ltm;               /* Local time. */
  30.   time_t then;                  /* The time to return. */
  31.  
  32.   then = mkgmtime (tm);
  33.   if (then == -1)
  34.     return -1;
  35.  
  36.   /* In case `tm' points to the static area used by localtime,
  37.      save its contents and restore them later. */
  38.   save_tm = *tm;
  39.   /* Correct for the timezone and any daylight savings time.
  40.      If a change to or from daylight savings time occurs between when
  41.      it is the time in `tm' locally and when it is that time in Greenwich,
  42.      the change to or from dst is ignored, but that is a rare case. */
  43.   then += then - mkgmtime (localtime (&then));
  44.  
  45.   ltm = localtime (&then);
  46.   save_tm.tm_yday = ltm->tm_yday;
  47.   save_tm.tm_wday = ltm->tm_wday;
  48.   save_tm.tm_isdst = ltm->tm_isdst;
  49.   *tm = save_tm;
  50.  
  51.   return then;
  52. }
  53.  
  54. /* Nonzero if `y' is a leap year, else zero. */
  55. #define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
  56.  
  57. /* Number of leap years from 1970 to `y' (not including `y' itself). */
  58. #define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
  59.  
  60. /* Number of days in each month of the year. */
  61. static char monlens[] =
  62. {
  63.   31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  64. };
  65.  
  66. /* Return the equivalent in seconds past 12:00:00 a.m. Jan 1, 1970 GMT
  67.    of the Greenwich Mean time and date in the exploded time structure `tm',
  68.    and set `tm->tm_yday', `tm->tm_wday', and `tm->tm_isdst'.
  69.    Return -1 if any of the other fields in `tm' has an invalid value. */
  70.  
  71. time_t
  72. mkgmtime (tm)
  73.      struct tm *tm;
  74. {
  75.   int years, months, days, hours, minutes, seconds;
  76.  
  77.   years = tm->tm_year + 1900;   /* year - 1900 -> year */
  78.   months = tm->tm_mon;          /* 0..11 */
  79.   days = tm->tm_mday - 1;       /* 1..31 -> 0..30 */
  80.   hours = tm->tm_hour;          /* 0..23 */
  81.   minutes = tm->tm_min;         /* 0..59 */
  82.   seconds = tm->tm_sec;         /* 0..61 in ANSI C. */
  83.  
  84.   if (years < 1970
  85.       || months < 0 || months > 11
  86.       || days < 0
  87.       || days > monlens[months] + (months == 1 && leap (years)) - 1
  88.       || hours < 0 || hours > 23
  89.       || minutes < 0 || minutes > 59
  90.       || seconds < 0 || seconds > 61)
  91.   return -1;
  92.  
  93.   /* Set `days' to the number of days into the year. */
  94.   if (months > 1 && leap (years))
  95.     ++days;
  96.   while (months-- > 0)
  97.     days += monlens[months];
  98.   tm->tm_yday = days;
  99.  
  100.   /* Now set `days' to the number of days since Jan 1, 1970. */
  101.   days += 365 * (years - 1970) + nleap (years);
  102.   tm->tm_wday = (days + 4) % 7; /* Jan 1, 1970 was Thursday. */
  103.   tm->tm_isdst = 0;
  104.  
  105.   return 86400 * days + 3600 * hours + 60 * minutes + seconds;
  106. }
  107. #endif
  108.