]>
Commit | Line | Data |
---|---|---|
89c4ed63 A |
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 | } |