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