xref: /unit/src/nxt_time.h (revision 2084:7d479274f334)
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