Listing 2 xttotm.c

/* _Ttotm and_Daysto functions */
#include "xtime.h"

             /* macros */
#define MONTAB(year)    \
       ((year) & 03 || (year) == 0 ? mos : lmos)

              /* static data */
static const short lmos[] = {0, 31, 60, 91, 121, 152,
       182, 213, 244, 274, 305, 335};
static const short mos[] = {0, 31, 59, 90, 120, 151,
       181, 212, 243, 273, 304, 334};

int _Daysto(int year, int mon)
       {       /* compute extra days to start of month */
       int days;

       if (0 < year)  /* correct for leap year: 1801-2099 */
              days = (year - 1) / 4;
       else if (year <= -4)
              days = 1 + (4 - year) / 4;
       else
              days = 0;
       return (days + MONTAB(year)[mon]);
       }

struct tm *_Ttotm(struct tm *t, time_t secsarg, int isdst)
       {      /* convert scalar time to time structure */
       int year;
       long days;
       time_t secs;
       static struct tm ts;

       secsarg += _TBIAS;
       if (t == NULL)
              t = &ts;
       t->tm_isdst = isdst;
       for (secs = secsarg; ; secs = secsarg + 3600)
              {       /* loop to correct for DST */
              days = secs / 86400;
              t->tm_wday = (days + WDAY) % 7;
               {      /* determine year */
               long i;

               for (year = days / 365; days < (i = _Daysto(year, 0) + 365L * year); )
                       --year; /* correct guess and recheck */
               days -= i;
               t->tm_year = year;
               t->tm_yday = days;
               }
               {      /* determine month */
               int mon;
               const short *pm = MONTAB(year);

               for (mon = 12; days < pm[--mon]; )
                      ;
               t->tm_mon = mon;
               t->tm_mday = days - pm[mon] + 1;
               }
              secs %= 86400;
              t->tm_hour =secs / 3600;
              secs %= 3600;
              t->tm_min = secs / 60;
              t->tm_sec = secs % 60;
              if (0 <= t->tm_isdst || (t->tm_isdst = _Isdst(t)) <= 0)
                     return (t);     /* loop only if <0 => 1     */
              }
       }
/* End of File */