"Fossies" - the Fresh Open Source Software Archive

Member "netxms-3.8.166/src/libnetxms/timegm.c" (23 Feb 2021, 3194 Bytes) of package /linux/misc/netxms-3.8.166.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "timegm.c" see the Fossies "Dox" file reference documentation.

    1 /*  $NetBSD: timegm.c,v 1.3 2007/08/07 02:07:01 lukem Exp $ */
    2 /*  from    ?   */
    3 
    4 #include "libnetxms.h"
    5 
    6 #if !HAVE_TIMEGM
    7 
    8 #ifndef TM_YEAR_BASE
    9 #define TM_YEAR_BASE 1900
   10 #endif
   11 
   12 #ifndef EPOCH_YEAR
   13 #define EPOCH_YEAR   1970
   14 #endif
   15 
   16 /*
   17  * UTC version of mktime(3)
   18  */
   19 
   20 /*
   21  * This code is not portable, but works on most Unix-like systems.
   22  * If the local timezone has no summer time, using mktime(3) function
   23  * and adjusting offset would be usable (adjusting leap seconds
   24  * is still required, though), but the assumption is not always true.
   25  *
   26  * Anyway, no portable and correct implementation of UTC to time_t
   27  * conversion exists....
   28  */
   29 
   30 static time_t sub_mkgmt(struct tm *_tm)
   31 {
   32     int y, nleapdays;
   33     time_t t;
   34     /* days before the month */
   35     static const unsigned short moff[12] = {
   36         0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
   37     };
   38 
   39     /*
   40      * XXX: This code assumes the given time to be normalized.
   41      * Normalizing here is impossible in case the given time is a leap
   42      * second but the local time library is ignorant of leap seconds.
   43      */
   44 
   45     /* minimal sanity checking not to access outside of the array */
   46     if ((unsigned) _tm->tm_mon >= 12)
   47         return (time_t) -1;
   48     if (_tm->tm_year < EPOCH_YEAR - TM_YEAR_BASE)
   49         return (time_t) -1;
   50 
   51     y = _tm->tm_year + TM_YEAR_BASE - (_tm->tm_mon < 2);
   52     nleapdays = y / 4 - y / 100 + y / 400 -
   53         ((EPOCH_YEAR-1) / 4 - (EPOCH_YEAR-1) / 100 + (EPOCH_YEAR-1) / 400);
   54     t = ((((time_t) (_tm->tm_year - (EPOCH_YEAR - TM_YEAR_BASE)) * 365 +
   55             moff[_tm->tm_mon] + _tm->tm_mday - 1 + nleapdays) * 24 +
   56         _tm->tm_hour) * 60 + _tm->tm_min) * 60 + _tm->tm_sec;
   57 
   58     return (t < 0 ? (time_t) -1 : t);
   59 }
   60 
   61 time_t LIBNETXMS_EXPORTABLE timegm(struct tm *_tm)
   62 {
   63     time_t t, t2;
   64     struct tm *tm2;
   65     int sec;
   66 
   67     /* Do the first guess. */
   68     if ((t = sub_mkgmt(_tm)) == (time_t) -1)
   69         return (time_t) -1;
   70 
   71     /* save value in case *_tm is overwritten by gmtime() */
   72     sec = _tm->tm_sec;
   73 
   74     tm2 = gmtime(&t);
   75     if ((t2 = sub_mkgmt(tm2)) == (time_t) -1)
   76         return (time_t) -1;
   77 
   78     if (t2 < t || tm2->tm_sec != sec) {
   79         /*
   80          * Adjust for leap seconds.
   81          *
   82          *     real time_t time
   83          *           |
   84          *          tm
   85          *         /    ... (a) first sub_mkgmt() conversion
   86          *       t
   87          *       |
   88          *      tm2
   89          *     /    ... (b) second sub_mkgmt() conversion
   90          *   t2
   91          *          --->time
   92          */
   93         /*
   94          * Do the second guess, assuming (a) and (b) are almost equal.
   95          */
   96         t += t - t2;
   97         tm2 = gmtime(&t);
   98 
   99         /*
  100          * Either (a) or (b), may include one or two extra
  101          * leap seconds.  Try t, t + 2, t - 2, t + 1, and t - 1.
  102          */
  103         if (tm2->tm_sec == sec
  104             || (t += 2, tm2 = gmtime(&t), tm2->tm_sec == sec)
  105             || (t -= 4, tm2 = gmtime(&t), tm2->tm_sec == sec)
  106             || (t += 3, tm2 = gmtime(&t), tm2->tm_sec == sec)
  107             || (t -= 2, tm2 = gmtime(&t), tm2->tm_sec == sec))
  108             ;   /* found */
  109         else {
  110             /*
  111              * Not found.
  112              */
  113             if (sec >= 60)
  114                 /*
  115                  * The given time is a leap second
  116                  * (sec 60 or 61), but the time library
  117                  * is ignorant of the leap second.
  118                  */
  119                 ;   /* treat sec 60 as 59,
  120                        sec 61 as 0 of the next minute */
  121             else
  122                 /* The given time may not be normalized. */
  123                 t++;    /* restore t */
  124         }
  125     }
  126 
  127     return (t < 0 ? (time_t) -1 : t);
  128 }
  129 
  130 #endif