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