10Sigor@sysoev.ru 20Sigor@sysoev.ru /* 30Sigor@sysoev.ru * Copyright (C) Igor Sysoev 40Sigor@sysoev.ru * Copyright (C) NGINX, Inc. 50Sigor@sysoev.ru */ 60Sigor@sysoev.ru 70Sigor@sysoev.ru #ifndef _NXT_UNIX_TIME_H_INCLUDED_ 80Sigor@sysoev.ru #define _NXT_UNIX_TIME_H_INCLUDED_ 90Sigor@sysoev.ru 100Sigor@sysoev.ru 110Sigor@sysoev.ru typedef uint64_t nxt_nsec_t; 120Sigor@sysoev.ru typedef int64_t nxt_nsec_int_t; 130Sigor@sysoev.ru #define NXT_INFINITE_NSEC ((nxt_nsec_t) -1) 140Sigor@sysoev.ru 150Sigor@sysoev.ru 160Sigor@sysoev.ru typedef struct { 170Sigor@sysoev.ru nxt_time_t sec; 180Sigor@sysoev.ru nxt_uint_t nsec; 190Sigor@sysoev.ru } nxt_realtime_t; 200Sigor@sysoev.ru 210Sigor@sysoev.ru 220Sigor@sysoev.ru /* 230Sigor@sysoev.ru * nxt_monotonic_time_t includes nxt_realtime_t to eliminate 240Sigor@sysoev.ru * surplus gettimeofday() call on platform without monotonic time. 250Sigor@sysoev.ru */ 260Sigor@sysoev.ru 270Sigor@sysoev.ru typedef struct { 280Sigor@sysoev.ru nxt_realtime_t realtime; 290Sigor@sysoev.ru nxt_nsec_t monotonic; 300Sigor@sysoev.ru nxt_nsec_t update; 310Sigor@sysoev.ru 320Sigor@sysoev.ru #if !(NXT_HAVE_CLOCK_MONOTONIC || NXT_SOLARIS || NXT_HPUX || NXT_MACOSX) 330Sigor@sysoev.ru nxt_nsec_t previous; 340Sigor@sysoev.ru #endif 350Sigor@sysoev.ru } nxt_monotonic_time_t; 360Sigor@sysoev.ru 370Sigor@sysoev.ru 380Sigor@sysoev.ru NXT_EXPORT void nxt_realtime(nxt_realtime_t *now); 390Sigor@sysoev.ru NXT_EXPORT void nxt_monotonic_time(nxt_monotonic_time_t *now); 400Sigor@sysoev.ru NXT_EXPORT void nxt_localtime(nxt_time_t s, struct tm *tm); 410Sigor@sysoev.ru NXT_EXPORT void nxt_timezone_update(void); 420Sigor@sysoev.ru 430Sigor@sysoev.ru /* 440Sigor@sysoev.ru * Both localtime() and localtime_r() are not Async-Signal-Safe, therefore, 450Sigor@sysoev.ru * they can not be used in signal handlers. Since Daylight Saving Time (DST) 460Sigor@sysoev.ru * state changes no more than twice a year, a simple workaround is to use 470Sigor@sysoev.ru * a previously cached GMT offset value and nxt_gmtime(): 480Sigor@sysoev.ru * 490Sigor@sysoev.ru * nxt_gmtime(GMT seconds + GMT offset, tm); 500Sigor@sysoev.ru * 510Sigor@sysoev.ru * GMT offset with account of current DST state can be obtained only 520Sigor@sysoev.ru * using localtime()'s struct tm because: 530Sigor@sysoev.ru * 540Sigor@sysoev.ru * 1) gettimeofday() does not return GMT offset at almost all platforms. 550Sigor@sysoev.ru * MacOSX returns a value cached after the first localtime() call. 560Sigor@sysoev.ru * AIX returns GMT offset without account of DST state and indicates 570Sigor@sysoev.ru * only that timezone has DST, but does not indicate current DST state. 580Sigor@sysoev.ru * 590Sigor@sysoev.ru * 2) There are the "timezone" and "daylight" variables on Linux, Solaris, 600Sigor@sysoev.ru * HP-UX, IRIX, and other systems. The "daylight" variable indicates 610Sigor@sysoev.ru * only that timezone has DST, but does not indicate current DST state. 620Sigor@sysoev.ru * 630Sigor@sysoev.ru * 3) Solaris and IRIX have the "altzone" variable which contains GMT offset 640Sigor@sysoev.ru * for timezone with DST applied, but without account of DST state. 650Sigor@sysoev.ru * 660Sigor@sysoev.ru * 4) There is the "struct tm.tm_gmtoff" field on BSD systems and modern Linux. 670Sigor@sysoev.ru * This field contains GMT offset with account of DST state. 680Sigor@sysoev.ru * 690Sigor@sysoev.ru * 5) The "struct tm.tm_isdst" field returned by localtime() indicates 700Sigor@sysoev.ru * current DST state on all platforms. This field may have three values: 710Sigor@sysoev.ru * positive means DST in effect, zero means DST is not in effect, and 720Sigor@sysoev.ru * negative means DST state is unknown. 730Sigor@sysoev.ru */ 740Sigor@sysoev.ru 750Sigor@sysoev.ru #if (NXT_HAVE_TM_GMTOFF) 760Sigor@sysoev.ru 77*2084Salx.manpages@gmail.com #define nxt_timezone(tm) \ 780Sigor@sysoev.ru ((tm)->tm_gmtoff) 790Sigor@sysoev.ru 800Sigor@sysoev.ru #elif (NXT_HAVE_ALTZONE) 810Sigor@sysoev.ru 82*2084Salx.manpages@gmail.com #define nxt_timezone(tm) \ 830Sigor@sysoev.ru (-(((tm)->tm_isdst > 0) ? altzone : timezone)) 840Sigor@sysoev.ru 850Sigor@sysoev.ru #else 860Sigor@sysoev.ru 87*2084Salx.manpages@gmail.com #define nxt_timezone(tm) \ 880Sigor@sysoev.ru (-(((tm)->tm_isdst > 0) ? timezone + 3600 : timezone)) 890Sigor@sysoev.ru 900Sigor@sysoev.ru #endif 910Sigor@sysoev.ru 920Sigor@sysoev.ru 930Sigor@sysoev.ru typedef uint32_t nxt_msec_t; 940Sigor@sysoev.ru typedef int32_t nxt_msec_int_t; 950Sigor@sysoev.ru #define NXT_INFINITE_MSEC ((nxt_msec_t) -1) 960Sigor@sysoev.ru 970Sigor@sysoev.ru 980Sigor@sysoev.ru /* 990Sigor@sysoev.ru * Since nxt_msec_t values are stored just in 32 bits, they overflow 1000Sigor@sysoev.ru * every 49 days. This signed subtraction takes into account that overflow. 1010Sigor@sysoev.ru * "nxt_msec_diff(m1, m2) < 0" means that m1 is lesser than m2. 1020Sigor@sysoev.ru */ 103*2084Salx.manpages@gmail.com #define nxt_msec_diff(m1, m2) \ 1040Sigor@sysoev.ru ((int32_t) ((m1) - (m2))) 1050Sigor@sysoev.ru 1060Sigor@sysoev.ru 1070Sigor@sysoev.ru #endif /* _NXT_UNIX_TIME_H_INCLUDED_ */ 108