]> git.saurik.com Git - apple/network_cmds.git/blob - unbound/compat/gmtime_r.c
19eb637e3c9b85562f120d5aa66be887e4173f32
[apple/network_cmds.git] / unbound / compat / gmtime_r.c
1 /*
2 * Taken from FreeBSD src / lib / libc / stdtime / localtime.c 1.43 revision.
3 * localtime.c 7.78.
4 * tzfile.h 1.8
5 * adapted to be replacement gmtime_r.
6 */
7 #include "config.h"
8
9 #ifdef HAVE_TIME_H
10 #include <time.h>
11 #endif
12
13 #define MONSPERYEAR 12
14 #define DAYSPERNYEAR 365
15 #define DAYSPERLYEAR 366
16 #define SECSPERMIN 60
17 #define SECSPERHOUR (60*60)
18 #define SECSPERDAY (24*60*60)
19 #define DAYSPERWEEK 7
20 #define TM_SUNDAY 0
21 #define TM_MONDAY 1
22 #define TM_TUESDAY 2
23 #define TM_WEDNESDAY 3
24 #define TM_THURSDAY 4
25 #define TM_FRIDAY 5
26 #define TM_SATURDAY 6
27
28 #define TM_YEAR_BASE 1900
29
30 #define EPOCH_YEAR 1970
31 #define EPOCH_WDAY TM_THURSDAY
32
33 #define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
34
35 static const int mon_lengths[2][MONSPERYEAR] = {
36 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
37 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
38 };
39
40 static const int year_lengths[2] = {
41 DAYSPERNYEAR, DAYSPERLYEAR
42 };
43
44 static void
45 timesub(timep, offset, tmp)
46 const time_t * const timep;
47 const long offset;
48 struct tm * const tmp;
49 {
50 long days;
51 long rem;
52 long y;
53 int yleap;
54 const int * ip;
55
56 days = *timep / SECSPERDAY;
57 rem = *timep % SECSPERDAY;
58 rem += (offset);
59 while (rem < 0) {
60 rem += SECSPERDAY;
61 --days;
62 }
63 while (rem >= SECSPERDAY) {
64 rem -= SECSPERDAY;
65 ++days;
66 }
67 tmp->tm_hour = (int) (rem / SECSPERHOUR);
68 rem = rem % SECSPERHOUR;
69 tmp->tm_min = (int) (rem / SECSPERMIN);
70 /*
71 ** A positive leap second requires a special
72 ** representation. This uses "... ??:59:60" et seq.
73 */
74 tmp->tm_sec = (int) (rem % SECSPERMIN) ;
75 tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
76 if (tmp->tm_wday < 0)
77 tmp->tm_wday += DAYSPERWEEK;
78 y = EPOCH_YEAR;
79 #define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
80 while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
81 long newy;
82
83 newy = y + days / DAYSPERNYEAR;
84 if (days < 0)
85 --newy;
86 days -= (newy - y) * DAYSPERNYEAR +
87 LEAPS_THRU_END_OF(newy - 1) -
88 LEAPS_THRU_END_OF(y - 1);
89 y = newy;
90 }
91 tmp->tm_year = y - TM_YEAR_BASE;
92 tmp->tm_yday = (int) days;
93 ip = mon_lengths[yleap];
94 for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
95 days = days - (long) ip[tmp->tm_mon];
96 tmp->tm_mday = (int) (days + 1);
97 tmp->tm_isdst = 0;
98 }
99
100 /*
101 * Re-entrant version of gmtime.
102 */
103 struct tm * gmtime_r(const time_t* timep, struct tm *tm)
104 {
105 timesub(timep, 0L, tm);
106 return tm;
107 }