1*0Sigor@sysoev.ru 2*0Sigor@sysoev.ru /* 3*0Sigor@sysoev.ru * Copyright (C) Igor Sysoev 4*0Sigor@sysoev.ru * Copyright (C) NGINX, Inc. 5*0Sigor@sysoev.ru */ 6*0Sigor@sysoev.ru 7*0Sigor@sysoev.ru #ifndef _NXT_UNIX_TIME_H_INCLUDED_ 8*0Sigor@sysoev.ru #define _NXT_UNIX_TIME_H_INCLUDED_ 9*0Sigor@sysoev.ru 10*0Sigor@sysoev.ru 11*0Sigor@sysoev.ru typedef uint64_t nxt_nsec_t; 12*0Sigor@sysoev.ru typedef int64_t nxt_nsec_int_t; 13*0Sigor@sysoev.ru #define NXT_INFINITE_NSEC ((nxt_nsec_t) -1) 14*0Sigor@sysoev.ru 15*0Sigor@sysoev.ru 16*0Sigor@sysoev.ru typedef struct { 17*0Sigor@sysoev.ru nxt_time_t sec; 18*0Sigor@sysoev.ru nxt_uint_t nsec; 19*0Sigor@sysoev.ru } nxt_realtime_t; 20*0Sigor@sysoev.ru 21*0Sigor@sysoev.ru 22*0Sigor@sysoev.ru /* 23*0Sigor@sysoev.ru * nxt_monotonic_time_t includes nxt_realtime_t to eliminate 24*0Sigor@sysoev.ru * surplus gettimeofday() call on platform without monotonic time. 25*0Sigor@sysoev.ru */ 26*0Sigor@sysoev.ru 27*0Sigor@sysoev.ru typedef struct { 28*0Sigor@sysoev.ru nxt_realtime_t realtime; 29*0Sigor@sysoev.ru nxt_nsec_t monotonic; 30*0Sigor@sysoev.ru nxt_nsec_t update; 31*0Sigor@sysoev.ru 32*0Sigor@sysoev.ru #if !(NXT_HAVE_CLOCK_MONOTONIC || NXT_SOLARIS || NXT_HPUX || NXT_MACOSX) 33*0Sigor@sysoev.ru nxt_nsec_t previous; 34*0Sigor@sysoev.ru #endif 35*0Sigor@sysoev.ru } nxt_monotonic_time_t; 36*0Sigor@sysoev.ru 37*0Sigor@sysoev.ru 38*0Sigor@sysoev.ru NXT_EXPORT void nxt_realtime(nxt_realtime_t *now); 39*0Sigor@sysoev.ru NXT_EXPORT void nxt_monotonic_time(nxt_monotonic_time_t *now); 40*0Sigor@sysoev.ru NXT_EXPORT void nxt_localtime(nxt_time_t s, struct tm *tm); 41*0Sigor@sysoev.ru NXT_EXPORT void nxt_timezone_update(void); 42*0Sigor@sysoev.ru 43*0Sigor@sysoev.ru /* 44*0Sigor@sysoev.ru * Both localtime() and localtime_r() are not Async-Signal-Safe, therefore, 45*0Sigor@sysoev.ru * they can not be used in signal handlers. Since Daylight Saving Time (DST) 46*0Sigor@sysoev.ru * state changes no more than twice a year, a simple workaround is to use 47*0Sigor@sysoev.ru * a previously cached GMT offset value and nxt_gmtime(): 48*0Sigor@sysoev.ru * 49*0Sigor@sysoev.ru * nxt_gmtime(GMT seconds + GMT offset, tm); 50*0Sigor@sysoev.ru * 51*0Sigor@sysoev.ru * GMT offset with account of current DST state can be obtained only 52*0Sigor@sysoev.ru * using localtime()'s struct tm because: 53*0Sigor@sysoev.ru * 54*0Sigor@sysoev.ru * 1) gettimeofday() does not return GMT offset at almost all platforms. 55*0Sigor@sysoev.ru * MacOSX returns a value cached after the first localtime() call. 56*0Sigor@sysoev.ru * AIX returns GMT offset without account of DST state and indicates 57*0Sigor@sysoev.ru * only that timezone has DST, but does not indicate current DST state. 58*0Sigor@sysoev.ru * 59*0Sigor@sysoev.ru * 2) There are the "timezone" and "daylight" variables on Linux, Solaris, 60*0Sigor@sysoev.ru * HP-UX, IRIX, and other systems. The "daylight" variable indicates 61*0Sigor@sysoev.ru * only that timezone has DST, but does not indicate current DST state. 62*0Sigor@sysoev.ru * 63*0Sigor@sysoev.ru * 3) Solaris and IRIX have the "altzone" variable which contains GMT offset 64*0Sigor@sysoev.ru * for timezone with DST applied, but without account of DST state. 65*0Sigor@sysoev.ru * 66*0Sigor@sysoev.ru * 4) There is the "struct tm.tm_gmtoff" field on BSD systems and modern Linux. 67*0Sigor@sysoev.ru * This field contains GMT offset with account of DST state. 68*0Sigor@sysoev.ru * 69*0Sigor@sysoev.ru * 5) The "struct tm.tm_isdst" field returned by localtime() indicates 70*0Sigor@sysoev.ru * current DST state on all platforms. This field may have three values: 71*0Sigor@sysoev.ru * positive means DST in effect, zero means DST is not in effect, and 72*0Sigor@sysoev.ru * negative means DST state is unknown. 73*0Sigor@sysoev.ru */ 74*0Sigor@sysoev.ru 75*0Sigor@sysoev.ru #if (NXT_HAVE_TM_GMTOFF) 76*0Sigor@sysoev.ru 77*0Sigor@sysoev.ru #define \ 78*0Sigor@sysoev.ru nxt_timezone(tm) \ 79*0Sigor@sysoev.ru ((tm)->tm_gmtoff) 80*0Sigor@sysoev.ru 81*0Sigor@sysoev.ru #elif (NXT_HAVE_ALTZONE) 82*0Sigor@sysoev.ru 83*0Sigor@sysoev.ru #define \ 84*0Sigor@sysoev.ru nxt_timezone(tm) \ 85*0Sigor@sysoev.ru (-(((tm)->tm_isdst > 0) ? altzone : timezone)) 86*0Sigor@sysoev.ru 87*0Sigor@sysoev.ru #else 88*0Sigor@sysoev.ru 89*0Sigor@sysoev.ru #define \ 90*0Sigor@sysoev.ru nxt_timezone(tm) \ 91*0Sigor@sysoev.ru (-(((tm)->tm_isdst > 0) ? timezone + 3600 : timezone)) 92*0Sigor@sysoev.ru 93*0Sigor@sysoev.ru #endif 94*0Sigor@sysoev.ru 95*0Sigor@sysoev.ru 96*0Sigor@sysoev.ru typedef uint32_t nxt_msec_t; 97*0Sigor@sysoev.ru typedef int32_t nxt_msec_int_t; 98*0Sigor@sysoev.ru #define NXT_INFINITE_MSEC ((nxt_msec_t) -1) 99*0Sigor@sysoev.ru 100*0Sigor@sysoev.ru 101*0Sigor@sysoev.ru /* 102*0Sigor@sysoev.ru * Since nxt_msec_t values are stored just in 32 bits, they overflow 103*0Sigor@sysoev.ru * every 49 days. This signed subtraction takes into account that overflow. 104*0Sigor@sysoev.ru * "nxt_msec_diff(m1, m2) < 0" means that m1 is lesser than m2. 105*0Sigor@sysoev.ru */ 106*0Sigor@sysoev.ru #define \ 107*0Sigor@sysoev.ru nxt_msec_diff(m1, m2) \ 108*0Sigor@sysoev.ru ((int32_t) ((m1) - (m2))) 109*0Sigor@sysoev.ru 110*0Sigor@sysoev.ru 111*0Sigor@sysoev.ru #endif /* _NXT_UNIX_TIME_H_INCLUDED_ */ 112