home *** CD-ROM | disk | FTP | other *** search
/ Unix System Administration Handbook 1997 October / usah_oct97.iso / news / cnews.tar / libcnews / fakeftime.c < prev    next >
C/C++ Source or Header  |  1995-04-27  |  3KB  |  112 lines

  1. /*
  2.  * fake ftime, assumes you have gettimeofday
  3.  */
  4.  
  5. #include <sys/types.h>
  6. #include <sys/time.h>
  7. /* <sys/time.h> should have included <time.h>, cross your fingers... */
  8. #include <sys/timeb.h>
  9. #include <stdlib.h>
  10.  
  11. #define    DUNNO    1000000L    /* impossible seconds timezone offset */
  12.  
  13. /*
  14.  - secswest - intuit the timezone, portably
  15.  */
  16. static long            /* seconds west of GMT, or DUNNO */
  17. secswest(now, localp)
  18. time_t now;
  19. struct tm *localp;        /* result of localtime(&now) */
  20. {
  21.     struct tm localt;
  22.     struct tm gmt;
  23.     register struct tm *a;
  24.     register struct tm *b;
  25. #    define    LG    a = &localt, b = &gmt
  26. #    define    GL    a = &gmt, b = &localt
  27.     register long sw;
  28.     register char *newstz;
  29.  
  30.     /* special hack primarily for testing */
  31.     newstz = getenv("NEWSTZ");
  32.     if (newstz != NULL)
  33.         return(atol(newstz));
  34.  
  35.     /* get local and GMT, broken down */
  36.     localt = *localp;
  37.     gmt = *gmtime(&now);
  38.  
  39.     /* simplify things: decide whether local is ahead of or behind GMT */
  40.     if (localt.tm_year < gmt.tm_year)
  41.         LG;                /* local first */
  42.     else if (localt.tm_year > gmt.tm_year)
  43.         GL;                /* GMT first */
  44.     else if (localt.tm_yday < gmt.tm_yday)
  45.         LG;
  46.     else if (localt.tm_yday > gmt.tm_yday)
  47.         GL;
  48.     else if (localt.tm_hour < gmt.tm_hour)
  49.         LG;
  50.     else if (localt.tm_hour > gmt.tm_hour)
  51.         GL;
  52.     else if (localt.tm_min < gmt.tm_min)
  53.         LG;
  54.     else if (localt.tm_min > gmt.tm_min)
  55.         GL;
  56.     else if (localt.tm_sec < gmt.tm_sec)
  57.         LG;
  58.     else if (localt.tm_sec > gmt.tm_sec)
  59.         GL;
  60.     else
  61.         return(0);        /* no difference -- local is GMT! */
  62.     /* a is now the earlier time, b the later */
  63.  
  64.     /* deal with year boundaries */
  65.     if (a->tm_year != b->tm_year && a->tm_yday >= 364 && b->tm_yday == 0)
  66.         a->tm_yday = -1;    /* Dec 31 == Jan 0 */
  67.     else if (a->tm_year != b->tm_year)
  68.         return(DUNNO);        /* something strange here */
  69.  
  70.     /* we're now in the same year; deal with day boundaries */
  71.     if (a->tm_yday != b->tm_yday && a->tm_yday == b->tm_yday - 1)
  72.         a->tm_hour -= 24;    /* 2200 Sun == -0200 Mon */
  73.     else if (a->tm_yday != b->tm_yday)
  74.         return(DUNNO);
  75.  
  76.     /* we're now in the same day, so now it's easy */
  77.     sw = (b->tm_hour - a->tm_hour)*3600L + (b->tm_min - a->tm_min)*60L +
  78.                         (b->tm_sec - a->tm_sec);
  79.  
  80.     /* and get the sign right */
  81.     if (a == &gmt)            /* local ahead, i.e. east, of GMT */
  82.         return(-sw);
  83.     else
  84.         return(sw);
  85. }
  86.  
  87. int
  88. ftime(tb)
  89. struct timeb *tb;
  90. {
  91.     struct timeval tv;
  92.     int ret;
  93.     struct tm *nowp;
  94.     long sw;
  95.  
  96.     ret = gettimeofday(&tv, (struct timezone *)NULL);
  97.  
  98.     tb->time = tv.tv_sec;
  99.     tb->millitm = (tv.tv_usec + 500) / 1000;
  100.  
  101.     nowp = localtime(&tb->time);
  102.     tb->dstflag = nowp->tm_isdst;
  103.  
  104.     sw = secswest(tb->time, nowp);
  105.     if (sw != DUNNO)
  106.         tb->timezone = (sw + 30) / 60;
  107.     else
  108.         tb->timezone = 0;    /* for lack of anything better to do */
  109.  
  110.     return(ret);
  111. }
  112.