Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 831 lines (652 sloc) 22.821 kb
e0ad44e Michael G. Schwern r60997@windhund: schwern | 2008-09-11 03:51:57 -0700
authored
1 /*
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
2
62ca646 Michael G. Schwern Update the year on copyright notices
authored
3 Copyright (c) 2007-2010 Michael G Schwern
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
4
e0ad44e Michael G. Schwern r60997@windhund: schwern | 2008-09-11 03:51:57 -0700
authored
5 This software originally derived from Paul Sheer's pivotal_gmtime_r.c.
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
6
e0ad44e Michael G. Schwern r60997@windhund: schwern | 2008-09-11 03:51:57 -0700
authored
7 The MIT License:
8
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to deal
11 in the Software without restriction, including without limitation the rights
12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
15
e0ad44e Michael G. Schwern r60997@windhund: schwern | 2008-09-11 03:51:57 -0700
authored
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 THE SOFTWARE.
26
27 */
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
28
29 /*
30
31 Programmers who have available to them 64-bit time values as a 'long
32 long' type can use localtime64_r() and gmtime64_r() which correctly
33 converts the time even on 32-bit systems. Whether you have 64-bit time
34 values will depend on the operating system.
35
36 localtime64_r() is a 64-bit equivalent of localtime_r().
37
38 gmtime64_r() is a 64-bit equivalent of gmtime_r().
39
40 */
41
42 #include <assert.h>
43 #include <stdlib.h>
44 #include <stdio.h>
75ef043 Michael G. Schwern r66468@windhund: schwern | 2008-09-26 00:48:07 -0400
authored
45 #include <string.h>
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
46 #include <time.h>
45e46b2 Michael G. Schwern r60995@windhund: schwern | 2008-09-11 03:38:17 -0700
authored
47 #include <errno.h>
f0726d9 Michael G. Schwern r67108@windhund: schwern | 2008-09-29 15:51:31 -0400
authored
48 #include "time64.h"
fc700c9 Michael G. Schwern mktime64() now has an accurate idea of what the system mktime can do.
authored
49 #include "time64_limits.h"
50
a71803a Michael G. Schwern Implement gmtime64() and localtime64(). Follow the requirement that
authored
51
52 /* Spec says except for stftime() and the _r() functions, these
53 all return static memory. Stabbings! */
54 static struct TM Static_Return_Date;
7caec0a Michael G. Schwern Implement asctime64() and asctime64_r()
authored
55 static char Static_Return_String[35];
a71803a Michael G. Schwern Implement gmtime64() and localtime64(). Follow the requirement that
authored
56
dae6fe3 bulk88 reduce size of const static tables in time64.c
bulk88 authored
57 static const char days_in_month[2][12] = {
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
58 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
59 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
60 };
61
dae6fe3 bulk88 reduce size of const static tables in time64.c
bulk88 authored
62 static const short julian_days_by_month[2][12] = {
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
63 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
64 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335},
65 };
66
c72c702 Michael G. Schwern Account for the null byte on strings. [github 3]
authored
67 static char wday_name[7][4] = {
7caec0a Michael G. Schwern Implement asctime64() and asctime64_r()
authored
68 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
69 };
70
c72c702 Michael G. Schwern Account for the null byte on strings. [github 3]
authored
71 static char mon_name[12][4] = {
7caec0a Michael G. Schwern Implement asctime64() and asctime64_r()
authored
72 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
73 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
74 };
75
dae6fe3 bulk88 reduce size of const static tables in time64.c
bulk88 authored
76 static const short length_of_year[2] = { 365, 366 };
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
77
f1eca1c Michael G. Schwern Implement mktime64()
authored
78 /* Some numbers relating to the gregorian cycle */
79 static const Year years_in_gregorian_cycle = 400;
80 #define days_in_gregorian_cycle ((365 * 400) + 100 - 4 + 1)
81 static const Time64_T seconds_in_gregorian_cycle = days_in_gregorian_cycle * 60LL * 60LL * 24LL;
3a879e9 Michael G. Schwern r60993@windhund: schwern | 2008-09-11 01:35:12 -0700
authored
82
b725508 Michael G. Schwern Change safe_year() so it picks the lowest possible year in the 1970 - 20...
authored
83 /* Year range we can trust the time funcitons with */
84 #define MAX_SAFE_YEAR 2037
85 #define MIN_SAFE_YEAR 1971
86
87 /* 28 year Julian calendar cycle */
12addb7 Michael G. Schwern r67139@windhund: schwern | 2008-10-02 14:43:35 -0400
authored
88 #define SOLAR_CYCLE_LENGTH 28
b725508 Michael G. Schwern Change safe_year() so it picks the lowest possible year in the 1970 - 20...
authored
89
90 /* Year cycle from MAX_SAFE_YEAR down. */
dae6fe3 bulk88 reduce size of const static tables in time64.c
bulk88 authored
91 static const short safe_years_high[SOLAR_CYCLE_LENGTH] = {
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
92 2016, 2017, 2018, 2019,
93 2020, 2021, 2022, 2023,
94 2024, 2025, 2026, 2027,
95 2028, 2029, 2030, 2031,
96 2032, 2033, 2034, 2035,
97 2036, 2037, 2010, 2011,
98 2012, 2013, 2014, 2015
99 };
100
b725508 Michael G. Schwern Change safe_year() so it picks the lowest possible year in the 1970 - 20...
authored
101 /* Year cycle from MIN_SAFE_YEAR up */
102 static const int safe_years_low[SOLAR_CYCLE_LENGTH] = {
103 1996, 1997, 1998, 1971,
104 1972, 1973, 1974, 1975,
105 1976, 1977, 1978, 1979,
106 1980, 1981, 1982, 1983,
107 1984, 1985, 1986, 1987,
108 1988, 1989, 1990, 1991,
109 1992, 1993, 1994, 1995,
110 };
111
112 /* This isn't used, but it's handy to look at */
dae6fe3 bulk88 reduce size of const static tables in time64.c
bulk88 authored
113 static const char dow_year_start[SOLAR_CYCLE_LENGTH] = {
24864cd Michael G. Schwern r61043@windhund: schwern | 2008-09-15 19:24:10 -0700
authored
114 5, 0, 1, 2, /* 0 2016 - 2019 */
115 3, 5, 6, 0, /* 4 */
b725508 Michael G. Schwern Change safe_year() so it picks the lowest possible year in the 1970 - 20...
authored
116 1, 3, 4, 5, /* 8 1996 - 1998, 1971*/
117 6, 1, 2, 3, /* 12 1972 - 1975 */
24864cd Michael G. Schwern r61043@windhund: schwern | 2008-09-15 19:24:10 -0700
authored
118 4, 6, 0, 1, /* 16 */
119 2, 4, 5, 6, /* 20 2036, 2037, 2010, 2011 */
120 0, 2, 3, 4 /* 24 2012, 2013, 2014, 2015 */
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
121 };
122
7c5ceaa Michael G. Schwern r61016@windhund: schwern | 2008-09-11 17:03:58 -0700
authored
123 /* Let's assume people are going to be looking for dates in the future.
124 Let's provide some cheats so you can skip ahead.
125 This has a 4x speed boost when near 2008.
126 */
127 /* Number of days since epoch on Jan 1st, 2008 GMT */
128 #define CHEAT_DAYS (1199145600 / 24 / 60 / 60)
129 #define CHEAT_YEARS 108
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
130
c1617a8 Michael G. Schwern Detabify
authored
131 #define IS_LEAP(n) ((!(((n) + 1900) % 400) || (!(((n) + 1900) % 4) && (((n) + 1900) % 100))) != 0)
132 #define WRAP(a,b,m) ((a) = ((a) < 0 ) ? ((b)--, (a) + (m)) : (a))
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
133
4d08c3c Michael G. Schwern Move user configuration stuff into a new file.
authored
134 #ifdef USE_SYSTEM_LOCALTIME
135 # define SHOULD_USE_SYSTEM_LOCALTIME(a) ( \
9dc7284 Michael G. Schwern r61033@windhund: schwern | 2008-09-14 14:39:16 -0700
authored
136 (a) <= SYSTEM_LOCALTIME_MAX && \
137 (a) >= SYSTEM_LOCALTIME_MIN \
138 )
4d08c3c Michael G. Schwern Move user configuration stuff into a new file.
authored
139 #else
140 # define SHOULD_USE_SYSTEM_LOCALTIME(a) (0)
141 #endif
142
143 #ifdef USE_SYSTEM_GMTIME
144 # define SHOULD_USE_SYSTEM_GMTIME(a) ( \
9dc7284 Michael G. Schwern r61033@windhund: schwern | 2008-09-14 14:39:16 -0700
authored
145 (a) <= SYSTEM_GMTIME_MAX && \
146 (a) >= SYSTEM_GMTIME_MIN \
147 )
4d08c3c Michael G. Schwern Move user configuration stuff into a new file.
authored
148 #else
149 # define SHOULD_USE_SYSTEM_GMTIME(a) (0)
150 #endif
e1e20af Michael G. Schwern r61024@windhund: schwern | 2008-09-13 04:17:41 -0700
authored
151
933caae Michael G. Schwern Eliminate multi-var macros, that's C99
authored
152 /* Multi varadic macros are a C99 thing, alas */
a6bdcd5 Michael G. Schwern Add some trace code to help with debugging.
authored
153 #ifdef TIME_64_DEBUG
1a0ba72 Craig A. Berry Give the TRACE macros specific names to avoid clashing with other librar...
craigberry authored
154 # define TIME64_TRACE(format) (fprintf(stderr, format))
155 # define TIME64_TRACE1(format, var1) (fprintf(stderr, format, var1))
156 # define TIME64_TRACE2(format, var1, var2) (fprintf(stderr, format, var1, var2))
157 # define TIME64_TRACE3(format, var1, var2, var3) (fprintf(stderr, format, var1, var2, var3))
a6bdcd5 Michael G. Schwern Add some trace code to help with debugging.
authored
158 #else
1a0ba72 Craig A. Berry Give the TRACE macros specific names to avoid clashing with other librar...
craigberry authored
159 # define TIME64_TRACE(format) ((void)0)
160 # define TIME64_TRACE1(format, var1) ((void)0)
161 # define TIME64_TRACE2(format, var1, var2) ((void)0)
162 # define TIME64_TRACE3(format, var1, var2, var3) ((void)0)
a6bdcd5 Michael G. Schwern Add some trace code to help with debugging.
authored
163 #endif
e1e20af Michael G. Schwern r61024@windhund: schwern | 2008-09-13 04:17:41 -0700
authored
164
a71803a Michael G. Schwern Implement gmtime64() and localtime64(). Follow the requirement that
authored
165
6209e94 Michael G. Schwern Change the last of the Int64 uses to more specific types.
authored
166 static int is_exception_century(Year year)
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
167 {
168 int is_exception = ((year % 100 == 0) && !(year % 400 == 0));
1a0ba72 Craig A. Berry Give the TRACE macros specific names to avoid clashing with other librar...
craigberry authored
169 TIME64_TRACE1("# is_exception_century: %s\n", is_exception ? "yes" : "no");
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
170
171 return(is_exception);
172 }
173
c86ccd8 Michael G. Schwern r61013@windhund: schwern | 2008-09-11 16:11:17 -0700
authored
174
fc700c9 Michael G. Schwern mktime64() now has an accurate idea of what the system mktime can do.
authored
175 /* Compare two dates.
176 The result is like cmp.
177 Ignores things like gmtoffset and dst
178 */
179 int cmp_date( const struct TM* left, const struct tm* right ) {
180 if( left->tm_year > right->tm_year )
181 return 1;
182 else if( left->tm_year < right->tm_year )
183 return -1;
184
185 if( left->tm_mon > right->tm_mon )
186 return 1;
187 else if( left->tm_mon < right->tm_mon )
188 return -1;
189
190 if( left->tm_mday > right->tm_mday )
191 return 1;
192 else if( left->tm_mday < right->tm_mday )
193 return -1;
194
195 if( left->tm_hour > right->tm_hour )
196 return 1;
197 else if( left->tm_hour < right->tm_hour )
198 return -1;
199
200 if( left->tm_min > right->tm_min )
201 return 1;
202 else if( left->tm_min < right->tm_min )
203 return -1;
204
205 if( left->tm_sec > right->tm_sec )
206 return 1;
207 else if( left->tm_sec < right->tm_sec )
208 return -1;
209
210 return 0;
211 }
212
213
214 /* Check if a date is safely inside a range.
215 The intention is to check if its a few days inside.
216 */
217 int date_in_safe_range( const struct TM* date, const struct tm* min, const struct tm* max ) {
218 if( cmp_date(date, min) == -1 )
219 return 0;
220
221 if( cmp_date(date, max) == 1 )
222 return 0;
223
224 return 1;
225 }
226
227
f1eca1c Michael G. Schwern Implement mktime64()
authored
228 /* timegm() is not in the C or POSIX spec, but it is such a useful
229 extension I would be remiss in leaving it out. Also I need it
230 for localtime64()
231 */
75d4f62 Michael G. Schwern Consting.
authored
232 Time64_T timegm64(const struct TM *date) {
f07ee21 Michael G. Schwern Fix timegm64() for distant times.
authored
233 Time64_T days = 0;
6209e94 Michael G. Schwern Change the last of the Int64 uses to more specific types.
authored
234 Time64_T seconds = 0;
235 Year year;
f07ee21 Michael G. Schwern Fix timegm64() for distant times.
authored
236 Year orig_year = (Year)date->tm_year;
237 int cycles = 0;
c86ccd8 Michael G. Schwern r61013@windhund: schwern | 2008-09-11 16:11:17 -0700
authored
238
f07ee21 Michael G. Schwern Fix timegm64() for distant times.
authored
239 if( orig_year > 100 ) {
240 cycles = (orig_year - 100) / 400;
241 orig_year -= cycles * 400;
242 days += (Time64_T)cycles * days_in_gregorian_cycle;
243 }
244 else if( orig_year < -300 ) {
245 cycles = (orig_year - 100) / 400;
246 orig_year -= cycles * 400;
247 days += (Time64_T)cycles * days_in_gregorian_cycle;
248 }
1a0ba72 Craig A. Berry Give the TRACE macros specific names to avoid clashing with other librar...
craigberry authored
249 TIME64_TRACE3("# timegm/ cycles: %d, days: %lld, orig_year: %lld\n", cycles, days, orig_year);
f07ee21 Michael G. Schwern Fix timegm64() for distant times.
authored
250
251 if( orig_year > 70 ) {
c86ccd8 Michael G. Schwern r61013@windhund: schwern | 2008-09-11 16:11:17 -0700
authored
252 year = 70;
f07ee21 Michael G. Schwern Fix timegm64() for distant times.
authored
253 while( year < orig_year ) {
c86ccd8 Michael G. Schwern r61013@windhund: schwern | 2008-09-11 16:11:17 -0700
authored
254 days += length_of_year[IS_LEAP(year)];
255 year++;
256 }
257 }
f07ee21 Michael G. Schwern Fix timegm64() for distant times.
authored
258 else if ( orig_year < 70 ) {
c86ccd8 Michael G. Schwern r61013@windhund: schwern | 2008-09-11 16:11:17 -0700
authored
259 year = 69;
260 do {
261 days -= length_of_year[IS_LEAP(year)];
262 year--;
f07ee21 Michael G. Schwern Fix timegm64() for distant times.
authored
263 } while( year >= orig_year );
c86ccd8 Michael G. Schwern r61013@windhund: schwern | 2008-09-11 16:11:17 -0700
authored
264 }
265
f07ee21 Michael G. Schwern Fix timegm64() for distant times.
authored
266 days += julian_days_by_month[IS_LEAP(orig_year)][date->tm_mon];
c86ccd8 Michael G. Schwern r61013@windhund: schwern | 2008-09-11 16:11:17 -0700
authored
267 days += date->tm_mday - 1;
268
f07ee21 Michael G. Schwern Fix timegm64() for distant times.
authored
269 seconds = days * 60 * 60 * 24;
e0dd59a Michael G. Schwern r61041@windhund: schwern | 2008-09-14 21:29:37 -0700
authored
270
c86ccd8 Michael G. Schwern r61013@windhund: schwern | 2008-09-11 16:11:17 -0700
authored
271 seconds += date->tm_hour * 60 * 60;
272 seconds += date->tm_min * 60;
273 seconds += date->tm_sec;
274
6209e94 Michael G. Schwern Change the last of the Int64 uses to more specific types.
authored
275 return(seconds);
c86ccd8 Michael G. Schwern r61013@windhund: schwern | 2008-09-11 16:11:17 -0700
authored
276 }
277
278
75f8055 Michael G. Schwern r67111@windhund: schwern | 2008-09-29 17:28:17 -0400
authored
279 static int check_tm(struct TM *tm)
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
280 {
281 /* Don't forget leap seconds */
34a9fd0 Michael G. Schwern r61030@windhund: schwern | 2008-09-13 06:12:42 -0700
authored
282 assert(tm->tm_sec >= 0);
27654fb Michael G. Schwern r61018@windhund: schwern | 2008-09-13 02:58:57 -0700
authored
283 assert(tm->tm_sec <= 61);
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
284
34a9fd0 Michael G. Schwern r61030@windhund: schwern | 2008-09-13 06:12:42 -0700
authored
285 assert(tm->tm_min >= 0);
27654fb Michael G. Schwern r61018@windhund: schwern | 2008-09-13 02:58:57 -0700
authored
286 assert(tm->tm_min <= 59);
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
287
27654fb Michael G. Schwern r61018@windhund: schwern | 2008-09-13 02:58:57 -0700
authored
288 assert(tm->tm_hour >= 0);
289 assert(tm->tm_hour <= 23);
290
291 assert(tm->tm_mday >= 1);
34a9fd0 Michael G. Schwern r61030@windhund: schwern | 2008-09-13 06:12:42 -0700
authored
292 assert(tm->tm_mday <= days_in_month[IS_LEAP(tm->tm_year)][tm->tm_mon]);
27654fb Michael G. Schwern r61018@windhund: schwern | 2008-09-13 02:58:57 -0700
authored
293
294 assert(tm->tm_mon >= 0);
295 assert(tm->tm_mon <= 11);
296
297 assert(tm->tm_wday >= 0);
298 assert(tm->tm_wday <= 6);
299
300 assert(tm->tm_yday >= 0);
34a9fd0 Michael G. Schwern r61030@windhund: schwern | 2008-09-13 06:12:42 -0700
authored
301 assert(tm->tm_yday <= length_of_year[IS_LEAP(tm->tm_year)]);
27654fb Michael G. Schwern r61018@windhund: schwern | 2008-09-13 02:58:57 -0700
authored
302
303 #ifdef HAS_TM_TM_GMTOFF
304 assert(tm->tm_gmtoff >= -24 * 60 * 60);
305 assert(tm->tm_gmtoff <= 24 * 60 * 60);
306 #endif
34a9fd0 Michael G. Schwern r61030@windhund: schwern | 2008-09-13 06:12:42 -0700
authored
307
308 return 1;
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
309 }
e1e20af Michael G. Schwern r61024@windhund: schwern | 2008-09-13 04:17:41 -0700
authored
310
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
311
312 /* The exceptional centuries without leap years cause the cycle to
313 shift by 16
314 */
75f8055 Michael G. Schwern r67111@windhund: schwern | 2008-09-29 17:28:17 -0400
authored
315 static Year cycle_offset(Year year)
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
316 {
a26825a Michael G. Schwern r66454@windhund: schwern | 2008-09-25 15:03:36 -0400
authored
317 const Year start_year = 2000;
318 Year year_diff = year - start_year;
319 Year exceptions;
24864cd Michael G. Schwern r61043@windhund: schwern | 2008-09-15 19:24:10 -0700
authored
320
321 if( year > start_year )
322 year_diff--;
323
9ae3981 Michael G. Schwern r66448@windhund: schwern | 2008-09-24 17:15:10 -0400
authored
324 exceptions = year_diff / 100;
325 exceptions -= year_diff / 400;
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
326
1a0ba72 Craig A. Berry Give the TRACE macros specific names to avoid clashing with other librar...
craigberry authored
327 TIME64_TRACE3("# year: %lld, exceptions: %lld, year_diff: %lld\n",
a6bdcd5 Michael G. Schwern Add some trace code to help with debugging.
authored
328 year, exceptions, year_diff);
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
329
330 return exceptions * 16;
331 }
332
333 /* For a given year after 2038, pick the latest possible matching
334 year in the 28 year calendar cycle.
e0dd59a Michael G. Schwern r61041@windhund: schwern | 2008-09-14 21:29:37 -0700
authored
335
336 A matching year...
337 1) Starts on the same day of the week.
338 2) Has the same leap year status.
339
340 This is so the calendars match up.
341
342 Also the previous year must match. When doing Jan 1st you might
343 wind up on Dec 31st the previous year when doing a -UTC time zone.
24864cd Michael G. Schwern r61043@windhund: schwern | 2008-09-15 19:24:10 -0700
authored
344
345 Finally, the next year must have the same start day of week. This
346 is for Dec 31st with a +UTC time zone.
347 It doesn't need the same leap year status since we only care about
348 January 1st.
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
349 */
b725508 Michael G. Schwern Change safe_year() so it picks the lowest possible year in the 1970 - 20...
authored
350 static int safe_year(const Year year)
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
351 {
352 int safe_year;
b725508 Michael G. Schwern Change safe_year() so it picks the lowest possible year in the 1970 - 20...
authored
353 Year year_cycle;
354
355 if( year >= MIN_SAFE_YEAR && year <= MAX_SAFE_YEAR ) {
356 return (int)year;
357 }
358
359 year_cycle = year + cycle_offset(year);
360
361 /* safe_years_low is off from safe_years_high by 8 years */
362 if( year < MIN_SAFE_YEAR )
363 year_cycle -= 8;
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
364
365 /* Change non-leap xx00 years to an equivalent */
db44efb Michael G. Schwern r67110@windhund: schwern | 2008-09-29 17:25:49 -0400
authored
366 if( is_exception_century(year) )
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
367 year_cycle += 11;
24864cd Michael G. Schwern r61043@windhund: schwern | 2008-09-15 19:24:10 -0700
authored
368
369 /* Also xx01 years, since the previous year will be wrong */
db44efb Michael G. Schwern r67110@windhund: schwern | 2008-09-29 17:25:49 -0400
authored
370 if( is_exception_century(year - 1) )
24864cd Michael G. Schwern r61043@windhund: schwern | 2008-09-15 19:24:10 -0700
authored
371 year_cycle += 17;
372
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
373 year_cycle %= SOLAR_CYCLE_LENGTH;
e0dd59a Michael G. Schwern r61041@windhund: schwern | 2008-09-14 21:29:37 -0700
authored
374 if( year_cycle < 0 )
375 year_cycle = SOLAR_CYCLE_LENGTH + year_cycle;
376
24864cd Michael G. Schwern r61043@windhund: schwern | 2008-09-15 19:24:10 -0700
authored
377 assert( year_cycle >= 0 );
378 assert( year_cycle < SOLAR_CYCLE_LENGTH );
b725508 Michael G. Schwern Change safe_year() so it picks the lowest possible year in the 1970 - 20...
authored
379 if( year < MIN_SAFE_YEAR )
380 safe_year = safe_years_low[year_cycle];
381 else if( year > MAX_SAFE_YEAR )
382 safe_year = safe_years_high[year_cycle];
383 else
384 assert(0);
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
385
1a0ba72 Craig A. Berry Give the TRACE macros specific names to avoid clashing with other librar...
craigberry authored
386 TIME64_TRACE3("# year: %lld, year_cycle: %lld, safe_year: %d\n",
a6bdcd5 Michael G. Schwern Add some trace code to help with debugging.
authored
387 year, year_cycle, safe_year);
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
388
b725508 Michael G. Schwern Change safe_year() so it picks the lowest possible year in the 1970 - 20...
authored
389 assert(safe_year <= MAX_SAFE_YEAR && safe_year >= MIN_SAFE_YEAR);
390
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
391 return safe_year;
392 }
393
75ef043 Michael G. Schwern r66468@windhund: schwern | 2008-09-26 00:48:07 -0400
authored
394
c1747bb Michael G. Schwern Apparently VMS's C compiler is case insensitive wrt function names. *he...
authored
395 void copy_tm_to_TM64(const struct tm *src, struct TM *dest) {
14b7965 Michael G. Schwern r67102@windhund: schwern | 2008-09-29 13:42:05 -0400
authored
396 if( src == NULL ) {
397 memset(dest, 0, sizeof(*dest));
398 }
399 else {
400 # ifdef USE_TM64
401 dest->tm_sec = src->tm_sec;
402 dest->tm_min = src->tm_min;
403 dest->tm_hour = src->tm_hour;
404 dest->tm_mday = src->tm_mday;
405 dest->tm_mon = src->tm_mon;
406 dest->tm_year = (Year)src->tm_year;
407 dest->tm_wday = src->tm_wday;
408 dest->tm_yday = src->tm_yday;
409 dest->tm_isdst = src->tm_isdst;
410
411 # ifdef HAS_TM_TM_GMTOFF
412 dest->tm_gmtoff = src->tm_gmtoff;
413 # endif
414
415 # ifdef HAS_TM_TM_ZONE
df06b71 Michael G. Schwern Turn on -Wconversion to catch conversion mistakes.
authored
416 dest->tm_zone = src->tm_zone;
14b7965 Michael G. Schwern r67102@windhund: schwern | 2008-09-29 13:42:05 -0400
authored
417 # endif
418
419 # else
420 /* They're the same type */
421 memcpy(dest, src, sizeof(*dest));
422 # endif
423 }
424 }
425
426
c1747bb Michael G. Schwern Apparently VMS's C compiler is case insensitive wrt function names. *he...
authored
427 void copy_TM64_to_tm(const struct TM *src, struct tm *dest) {
14b7965 Michael G. Schwern r67102@windhund: schwern | 2008-09-29 13:42:05 -0400
authored
428 if( src == NULL ) {
429 memset(dest, 0, sizeof(*dest));
430 }
431 else {
432 # ifdef USE_TM64
433 dest->tm_sec = src->tm_sec;
434 dest->tm_min = src->tm_min;
435 dest->tm_hour = src->tm_hour;
436 dest->tm_mday = src->tm_mday;
437 dest->tm_mon = src->tm_mon;
438 dest->tm_year = (int)src->tm_year;
439 dest->tm_wday = src->tm_wday;
440 dest->tm_yday = src->tm_yday;
441 dest->tm_isdst = src->tm_isdst;
442
443 # ifdef HAS_TM_TM_GMTOFF
444 dest->tm_gmtoff = src->tm_gmtoff;
445 # endif
446
447 # ifdef HAS_TM_TM_ZONE
df06b71 Michael G. Schwern Turn on -Wconversion to catch conversion mistakes.
authored
448 dest->tm_zone = src->tm_zone;
14b7965 Michael G. Schwern r67102@windhund: schwern | 2008-09-29 13:42:05 -0400
authored
449 # endif
450
451 # else
452 /* They're the same type */
453 memcpy(dest, src, sizeof(*dest));
454 # endif
455 }
456 }
457
458
75ef043 Michael G. Schwern r66468@windhund: schwern | 2008-09-26 00:48:07 -0400
authored
459 /* Simulate localtime_r() to the best of our ability */
c485091 Michael G. Schwern Turn on some more warnings suggested by "An Introduction to GCC" and fix...
authored
460 struct tm * fake_localtime_r(const time_t *time, struct tm *result) {
461 const struct tm *static_result = localtime(time);
75ef043 Michael G. Schwern r66468@windhund: schwern | 2008-09-26 00:48:07 -0400
authored
462
59f2c77 Michael G. Schwern r67096@windhund: schwern | 2008-09-29 10:28:04 -0400
authored
463 assert(result != NULL);
75ef043 Michael G. Schwern r66468@windhund: schwern | 2008-09-26 00:48:07 -0400
authored
464
59f2c77 Michael G. Schwern r67096@windhund: schwern | 2008-09-29 10:28:04 -0400
authored
465 if( static_result == NULL ) {
466 memset(result, 0, sizeof(*result));
467 return NULL;
468 }
469 else {
470 memcpy(result, static_result, sizeof(*result));
471 return result;
472 }
75ef043 Michael G. Schwern r66468@windhund: schwern | 2008-09-26 00:48:07 -0400
authored
473 }
474
475
476 /* Simulate gmtime_r() to the best of our ability */
c485091 Michael G. Schwern Turn on some more warnings suggested by "An Introduction to GCC" and fix...
authored
477 struct tm * fake_gmtime_r(const time_t *time, struct tm *result) {
478 const struct tm *static_result = gmtime(time);
75ef043 Michael G. Schwern r66468@windhund: schwern | 2008-09-26 00:48:07 -0400
authored
479
59f2c77 Michael G. Schwern r67096@windhund: schwern | 2008-09-29 10:28:04 -0400
authored
480 assert(result != NULL);
75ef043 Michael G. Schwern r66468@windhund: schwern | 2008-09-26 00:48:07 -0400
authored
481
59f2c77 Michael G. Schwern r67096@windhund: schwern | 2008-09-29 10:28:04 -0400
authored
482 if( static_result == NULL ) {
483 memset(result, 0, sizeof(*result));
484 return NULL;
485 }
486 else {
487 memcpy(result, static_result, sizeof(*result));
488 return result;
489 }
75ef043 Michael G. Schwern r66468@windhund: schwern | 2008-09-26 00:48:07 -0400
authored
490 }
491
492
f1eca1c Michael G. Schwern Implement mktime64()
authored
493 static Time64_T seconds_between_years(Year left_year, Year right_year) {
494 int increment = (left_year > right_year) ? 1 : -1;
495 Time64_T seconds = 0;
496 int cycles;
497
498 if( left_year > 2400 ) {
499 cycles = (left_year - 2400) / 400;
500 left_year -= cycles * 400;
501 seconds += cycles * seconds_in_gregorian_cycle;
502 }
f07ee21 Michael G. Schwern Fix timegm64() for distant times.
authored
503 else if( left_year < 1600 ) {
504 cycles = (left_year - 1600) / 400;
505 left_year += cycles * 400;
506 seconds += cycles * seconds_in_gregorian_cycle;
507 }
f1eca1c Michael G. Schwern Implement mktime64()
authored
508
509 while( left_year != right_year ) {
510 seconds += length_of_year[IS_LEAP(right_year - 1900)] * 60 * 60 * 24;
511 right_year += increment;
512 }
513
514 return seconds * increment;
515 }
516
517
0f1670b Michael G. Schwern Make mktime64() correct the incoming tm struct as ISO C requires. [googl...
authored
518 Time64_T mktime64(struct TM *input_date) {
f1eca1c Michael G. Schwern Implement mktime64()
authored
519 struct tm safe_date;
520 struct TM date;
521 Time64_T time;
522 Year year = input_date->tm_year + 1900;
523
fc700c9 Michael G. Schwern mktime64() now has an accurate idea of what the system mktime can do.
authored
524 if( date_in_safe_range(input_date, &SYSTEM_MKTIME_MIN, &SYSTEM_MKTIME_MAX) )
525 {
c1747bb Michael G. Schwern Apparently VMS's C compiler is case insensitive wrt function names. *he...
authored
526 copy_TM64_to_tm(input_date, &safe_date);
0f1670b Michael G. Schwern Make mktime64() correct the incoming tm struct as ISO C requires. [googl...
authored
527 time = (Time64_T)mktime(&safe_date);
528
529 /* Correct the possibly out of bound input date */
530 copy_tm_to_TM64(&safe_date, input_date);
531 return time;
f1eca1c Michael G. Schwern Implement mktime64()
authored
532 }
533
534 /* Have to make the year safe in date else it won't fit in safe_date */
535 date = *input_date;
536 date.tm_year = safe_year(year) - 1900;
c1747bb Michael G. Schwern Apparently VMS's C compiler is case insensitive wrt function names. *he...
authored
537 copy_TM64_to_tm(&date, &safe_date);
f1eca1c Michael G. Schwern Implement mktime64()
authored
538
539 time = (Time64_T)mktime(&safe_date);
540
0f1670b Michael G. Schwern Make mktime64() correct the incoming tm struct as ISO C requires. [googl...
authored
541 /* Correct the user's possibly out of bound input date */
542 copy_tm_to_TM64(&safe_date, input_date);
543
f1eca1c Michael G. Schwern Implement mktime64()
authored
544 time += seconds_between_years(year, (Year)(safe_date.tm_year + 1900));
545
546 return time;
547 }
548
549
96c7853 Michael G. Schwern timelocal64() alias to mktime64()
authored
550 /* Because I think mktime() is a crappy name */
0f1670b Michael G. Schwern Make mktime64() correct the incoming tm struct as ISO C requires. [googl...
authored
551 Time64_T timelocal64(struct TM *date) {
96c7853 Michael G. Schwern timelocal64() alias to mktime64()
authored
552 return mktime64(date);
553 }
554
555
14b7965 Michael G. Schwern r67102@windhund: schwern | 2008-09-29 13:42:05 -0400
authored
556 struct TM *gmtime64_r (const Time64_T *in_time, struct TM *p)
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
557 {
558 int v_tm_sec, v_tm_min, v_tm_hour, v_tm_mon, v_tm_wday;
9c13daf Michael G. Schwern we don't need to use floor() or ceil(), integer math takes care of that.
authored
559 Time64_T v_tm_tday;
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
560 int leap;
9c13daf Michael G. Schwern we don't need to use floor() or ceil(), integer math takes care of that.
authored
561 Time64_T m;
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
562 Time64_T time = *in_time;
a26825a Michael G. Schwern r66454@windhund: schwern | 2008-09-25 15:03:36 -0400
authored
563 Year year = 70;
d95058a Michael G. Schwern r67119@windhund: schwern | 2008-09-30 01:22:47 -0400
authored
564 int cycles = 0;
25eaa3d Michael G. Schwern r60992@windhund: schwern | 2008-09-10 23:34:22 -0700
authored
565
59f2c77 Michael G. Schwern r67096@windhund: schwern | 2008-09-29 10:28:04 -0400
authored
566 assert(p != NULL);
567
e1e20af Michael G. Schwern r61024@windhund: schwern | 2008-09-13 04:17:41 -0700
authored
568 /* Use the system gmtime() if time_t is small enough */
569 if( SHOULD_USE_SYSTEM_GMTIME(*in_time) ) {
d60e0f6 Silence Win32 compiler warnings.
Steve Hay authored
570 time_t safe_time = (time_t)*in_time;
14b7965 Michael G. Schwern r67102@windhund: schwern | 2008-09-29 13:42:05 -0400
authored
571 struct tm safe_date;
572 GMTIME_R(&safe_time, &safe_date);
573
c1747bb Michael G. Schwern Apparently VMS's C compiler is case insensitive wrt function names. *he...
authored
574 copy_tm_to_TM64(&safe_date, p);
db44efb Michael G. Schwern r67110@windhund: schwern | 2008-09-29 17:25:49 -0400
authored
575 assert(check_tm(p));
14b7965 Michael G. Schwern r67102@windhund: schwern | 2008-09-29 13:42:05 -0400
authored
576
e1e20af Michael G. Schwern r61024@windhund: schwern | 2008-09-13 04:17:41 -0700
authored
577 return p;
578 }
579
27654fb Michael G. Schwern r61018@windhund: schwern | 2008-09-13 02:58:57 -0700
authored
580 #ifdef HAS_TM_TM_GMTOFF
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
581 p->tm_gmtoff = 0;
25eaa3d Michael G. Schwern r60992@windhund: schwern | 2008-09-10 23:34:22 -0700
authored
582 #endif
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
583 p->tm_isdst = 0;
25eaa3d Michael G. Schwern r60992@windhund: schwern | 2008-09-10 23:34:22 -0700
authored
584
27654fb Michael G. Schwern r61018@windhund: schwern | 2008-09-13 02:58:57 -0700
authored
585 #ifdef HAS_TM_TM_ZONE
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
586 p->tm_zone = "UTC";
25eaa3d Michael G. Schwern r60992@windhund: schwern | 2008-09-10 23:34:22 -0700
authored
587 #endif
588
a26825a Michael G. Schwern r66454@windhund: schwern | 2008-09-25 15:03:36 -0400
authored
589 v_tm_sec = (int)(time % 60);
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
590 time /= 60;
a26825a Michael G. Schwern r66454@windhund: schwern | 2008-09-25 15:03:36 -0400
authored
591 v_tm_min = (int)(time % 60);
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
592 time /= 60;
a26825a Michael G. Schwern r66454@windhund: schwern | 2008-09-25 15:03:36 -0400
authored
593 v_tm_hour = (int)(time % 24);
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
594 time /= 24;
595 v_tm_tday = time;
a26825a Michael G. Schwern r66454@windhund: schwern | 2008-09-25 15:03:36 -0400
authored
596
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
597 WRAP (v_tm_sec, v_tm_min, 60);
598 WRAP (v_tm_min, v_tm_hour, 60);
599 WRAP (v_tm_hour, v_tm_tday, 24);
a26825a Michael G. Schwern r66454@windhund: schwern | 2008-09-25 15:03:36 -0400
authored
600
601 v_tm_wday = (int)((v_tm_tday + 4) % 7);
602 if (v_tm_wday < 0)
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
603 v_tm_wday += 7;
604 m = v_tm_tday;
3a879e9 Michael G. Schwern r60993@windhund: schwern | 2008-09-11 01:35:12 -0700
authored
605
7c5ceaa Michael G. Schwern r61016@windhund: schwern | 2008-09-11 17:03:58 -0700
authored
606 if (m >= CHEAT_DAYS) {
607 year = CHEAT_YEARS;
608 m -= CHEAT_DAYS;
609 }
610
611 if (m >= 0) {
3a879e9 Michael G. Schwern r60993@windhund: schwern | 2008-09-11 01:35:12 -0700
authored
612 /* Gregorian cycles, this is huge optimization for distant times */
d7c5113 Michael G. Schwern Quiet a type conversion warning.
authored
613 cycles = (int)(m / (Time64_T) days_in_gregorian_cycle);
d95058a Michael G. Schwern r67119@windhund: schwern | 2008-09-30 01:22:47 -0400
authored
614 if( cycles ) {
615 m -= (cycles * (Time64_T) days_in_gregorian_cycle);
616 year += (cycles * years_in_gregorian_cycle);
3a879e9 Michael G. Schwern r60993@windhund: schwern | 2008-09-11 01:35:12 -0700
authored
617 }
618
619 /* Years */
45e46b2 Michael G. Schwern r60995@windhund: schwern | 2008-09-11 03:38:17 -0700
authored
620 leap = IS_LEAP (year);
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
621 while (m >= (Time64_T) length_of_year[leap]) {
622 m -= (Time64_T) length_of_year[leap];
45e46b2 Michael G. Schwern r60995@windhund: schwern | 2008-09-11 03:38:17 -0700
authored
623 year++;
624 leap = IS_LEAP (year);
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
625 }
3a879e9 Michael G. Schwern r60993@windhund: schwern | 2008-09-11 01:35:12 -0700
authored
626
627 /* Months */
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
628 v_tm_mon = 0;
629 while (m >= (Time64_T) days_in_month[leap][v_tm_mon]) {
630 m -= (Time64_T) days_in_month[leap][v_tm_mon];
631 v_tm_mon++;
632 }
633 } else {
7c5ceaa Michael G. Schwern r61016@windhund: schwern | 2008-09-11 17:03:58 -0700
authored
634 year--;
3a879e9 Michael G. Schwern r60993@windhund: schwern | 2008-09-11 01:35:12 -0700
authored
635
636 /* Gregorian cycles */
d7c5113 Michael G. Schwern Quiet a type conversion warning.
authored
637 cycles = (int)((m / (Time64_T) days_in_gregorian_cycle) + 1);
d95058a Michael G. Schwern r67119@windhund: schwern | 2008-09-30 01:22:47 -0400
authored
638 if( cycles ) {
639 m -= (cycles * (Time64_T) days_in_gregorian_cycle);
640 year += (cycles * years_in_gregorian_cycle);
3a879e9 Michael G. Schwern r60993@windhund: schwern | 2008-09-11 01:35:12 -0700
authored
641 }
642
643 /* Years */
45e46b2 Michael G. Schwern r60995@windhund: schwern | 2008-09-11 03:38:17 -0700
authored
644 leap = IS_LEAP (year);
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
645 while (m < (Time64_T) -length_of_year[leap]) {
646 m += (Time64_T) length_of_year[leap];
45e46b2 Michael G. Schwern r60995@windhund: schwern | 2008-09-11 03:38:17 -0700
authored
647 year--;
648 leap = IS_LEAP (year);
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
649 }
3a879e9 Michael G. Schwern r60993@windhund: schwern | 2008-09-11 01:35:12 -0700
authored
650
651 /* Months */
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
652 v_tm_mon = 11;
653 while (m < (Time64_T) -days_in_month[leap][v_tm_mon]) {
654 m += (Time64_T) days_in_month[leap][v_tm_mon];
655 v_tm_mon--;
656 }
657 m += (Time64_T) days_in_month[leap][v_tm_mon];
658 }
45e46b2 Michael G. Schwern r60995@windhund: schwern | 2008-09-11 03:38:17 -0700
authored
659
660 p->tm_year = year;
661 if( p->tm_year != year ) {
27654fb Michael G. Schwern r61018@windhund: schwern | 2008-09-13 02:58:57 -0700
authored
662 #ifdef EOVERFLOW
45e46b2 Michael G. Schwern r60995@windhund: schwern | 2008-09-11 03:38:17 -0700
authored
663 errno = EOVERFLOW;
27654fb Michael G. Schwern r61018@windhund: schwern | 2008-09-13 02:58:57 -0700
authored
664 #endif
45e46b2 Michael G. Schwern r60995@windhund: schwern | 2008-09-11 03:38:17 -0700
authored
665 return NULL;
666 }
667
4697651 Michael G. Schwern Quiet on last type warning (on Windows).
authored
668 /* At this point m is less than a year so casting to an int is safe */
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
669 p->tm_mday = (int) m + 1;
4697651 Michael G. Schwern Quiet on last type warning (on Windows).
authored
670 p->tm_yday = julian_days_by_month[leap][v_tm_mon] + (int)m;
671 p->tm_sec = v_tm_sec;
672 p->tm_min = v_tm_min;
673 p->tm_hour = v_tm_hour;
674 p->tm_mon = v_tm_mon;
675 p->tm_wday = v_tm_wday;
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
676
db44efb Michael G. Schwern r67110@windhund: schwern | 2008-09-29 17:25:49 -0400
authored
677 assert(check_tm(p));
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
678
679 return p;
680 }
681
682
14b7965 Michael G. Schwern r67102@windhund: schwern | 2008-09-29 13:42:05 -0400
authored
683 struct TM *localtime64_r (const Time64_T *time, struct TM *local_tm)
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
684 {
685 time_t safe_time;
14b7965 Michael G. Schwern r67102@windhund: schwern | 2008-09-29 13:42:05 -0400
authored
686 struct tm safe_date;
687 struct TM gm_tm;
a26825a Michael G. Schwern r66454@windhund: schwern | 2008-09-25 15:03:36 -0400
authored
688 Year orig_year;
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
689 int month_diff;
690
59f2c77 Michael G. Schwern r67096@windhund: schwern | 2008-09-29 10:28:04 -0400
authored
691 assert(local_tm != NULL);
692
e1e20af Michael G. Schwern r61024@windhund: schwern | 2008-09-13 04:17:41 -0700
authored
693 /* Use the system localtime() if time_t is small enough */
694 if( SHOULD_USE_SYSTEM_LOCALTIME(*time) ) {
d60e0f6 Silence Win32 compiler warnings.
Steve Hay authored
695 safe_time = (time_t)*time;
14b7965 Michael G. Schwern r67102@windhund: schwern | 2008-09-29 13:42:05 -0400
authored
696
1a0ba72 Craig A. Berry Give the TRACE macros specific names to avoid clashing with other librar...
craigberry authored
697 TIME64_TRACE1("Using system localtime for %lld\n", *time);
a6bdcd5 Michael G. Schwern Add some trace code to help with debugging.
authored
698
14b7965 Michael G. Schwern r67102@windhund: schwern | 2008-09-29 13:42:05 -0400
authored
699 LOCALTIME_R(&safe_time, &safe_date);
700
c1747bb Michael G. Schwern Apparently VMS's C compiler is case insensitive wrt function names. *he...
authored
701 copy_tm_to_TM64(&safe_date, local_tm);
db44efb Michael G. Schwern r67110@windhund: schwern | 2008-09-29 17:25:49 -0400
authored
702 assert(check_tm(local_tm));
14b7965 Michael G. Schwern r67102@windhund: schwern | 2008-09-29 13:42:05 -0400
authored
703
e1e20af Michael G. Schwern r61024@windhund: schwern | 2008-09-13 04:17:41 -0700
authored
704 return local_tm;
705 }
706
a6bdcd5 Michael G. Schwern Add some trace code to help with debugging.
authored
707 if( gmtime64_r(time, &gm_tm) == NULL ) {
1a0ba72 Craig A. Berry Give the TRACE macros specific names to avoid clashing with other librar...
craigberry authored
708 TIME64_TRACE1("gmtime64_r returned null for %lld\n", *time);
80c941e Michael G. Schwern r61035@windhund: schwern | 2008-09-14 15:25:33 -0700
authored
709 return NULL;
a6bdcd5 Michael G. Schwern Add some trace code to help with debugging.
authored
710 }
80c941e Michael G. Schwern r61035@windhund: schwern | 2008-09-14 15:25:33 -0700
authored
711
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
712 orig_year = gm_tm.tm_year;
713
5c64fde Michael G. Schwern r61038@windhund: schwern | 2008-09-14 18:28:38 -0700
authored
714 if (gm_tm.tm_year > (2037 - 1900) ||
a6bdcd5 Michael G. Schwern Add some trace code to help with debugging.
authored
715 gm_tm.tm_year < (1970 - 1900)
5c64fde Michael G. Schwern r61038@windhund: schwern | 2008-09-14 18:28:38 -0700
authored
716 )
717 {
1a0ba72 Craig A. Berry Give the TRACE macros specific names to avoid clashing with other librar...
craigberry authored
718 TIME64_TRACE1("Mapping tm_year %lld to safe_year\n", (Year)gm_tm.tm_year);
e0d2108 Michael G. Schwern Fix some more type conversion warnings revealed by turning USE_TM64 off.
authored
719 gm_tm.tm_year = safe_year((Year)(gm_tm.tm_year + 1900)) - 1900;
5c64fde Michael G. Schwern r61038@windhund: schwern | 2008-09-14 18:28:38 -0700
authored
720 }
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
721
d60e0f6 Silence Win32 compiler warnings.
Steve Hay authored
722 safe_time = (time_t)timegm64(&gm_tm);
a6bdcd5 Michael G. Schwern Add some trace code to help with debugging.
authored
723 if( LOCALTIME_R(&safe_time, &safe_date) == NULL ) {
1a0ba72 Craig A. Berry Give the TRACE macros specific names to avoid clashing with other librar...
craigberry authored
724 TIME64_TRACE1("localtime_r(%d) returned NULL\n", (int)safe_time);
80c941e Michael G. Schwern r61035@windhund: schwern | 2008-09-14 15:25:33 -0700
authored
725 return NULL;
a6bdcd5 Michael G. Schwern Add some trace code to help with debugging.
authored
726 }
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
727
c1747bb Michael G. Schwern Apparently VMS's C compiler is case insensitive wrt function names. *he...
authored
728 copy_tm_to_TM64(&safe_date, local_tm);
14b7965 Michael G. Schwern r67102@windhund: schwern | 2008-09-29 13:42:05 -0400
authored
729
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
730 local_tm->tm_year = orig_year;
80c941e Michael G. Schwern r61035@windhund: schwern | 2008-09-14 15:25:33 -0700
authored
731 if( local_tm->tm_year != orig_year ) {
1a0ba72 Craig A. Berry Give the TRACE macros specific names to avoid clashing with other librar...
craigberry authored
732 TIME64_TRACE2("tm_year overflow: tm_year %lld, orig_year %lld\n",
a6bdcd5 Michael G. Schwern Add some trace code to help with debugging.
authored
733 (Year)local_tm->tm_year, (Year)orig_year);
734
80c941e Michael G. Schwern r61035@windhund: schwern | 2008-09-14 15:25:33 -0700
authored
735 #ifdef EOVERFLOW
736 errno = EOVERFLOW;
737 #endif
738 return NULL;
739 }
740
741
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
742 month_diff = local_tm->tm_mon - gm_tm.tm_mon;
743
744 /* When localtime is Dec 31st previous year and
745 gmtime is Jan 1st next year.
746 */
747 if( month_diff == 11 ) {
748 local_tm->tm_year--;
749 }
750
751 /* When localtime is Jan 1st, next year and
752 gmtime is Dec 31st, previous year.
753 */
754 if( month_diff == -11 ) {
755 local_tm->tm_year++;
756 }
757
758 /* GMT is Jan 1st, xx01 year, but localtime is still Dec 31st
759 in a non-leap xx00. There is one point in the cycle
760 we can't account for which the safe xx00 year is a leap
761 year. So we need to correct for Dec 31st comming out as
762 the 366th day of the year.
763 */
764 if( !IS_LEAP(local_tm->tm_year) && local_tm->tm_yday == 365 )
765 local_tm->tm_yday--;
766
db44efb Michael G. Schwern r67110@windhund: schwern | 2008-09-29 17:25:49 -0400
authored
767 assert(check_tm(local_tm));
634d1c1 Michael G. Schwern r60990@windhund: schwern | 2008-09-10 21:17:55 -0700
authored
768
769 return local_tm;
770 }
a71803a Michael G. Schwern Implement gmtime64() and localtime64(). Follow the requirement that
authored
771
772
7caec0a Michael G. Schwern Implement asctime64() and asctime64_r()
authored
773 int valid_tm_wday( const struct TM* date ) {
774 if( 0 <= date->tm_wday && date->tm_wday <= 6 )
775 return 1;
776 else
777 return 0;
778 }
779
780 int valid_tm_mon( const struct TM* date ) {
781 if( 0 <= date->tm_mon && date->tm_mon <= 11 )
782 return 1;
783 else
784 return 0;
785 }
786
787
788 char *asctime64_r( const struct TM* date, char *result ) {
789 /* I figure everything else can be displayed, even hour 25, but if
790 these are out of range we walk off the name arrays */
791 if( !valid_tm_wday(date) || !valid_tm_mon(date) )
792 return NULL;
793
f039d23 Michael G. Schwern Fix the asctime format to handle tm64's big year
authored
794 sprintf(result, TM64_ASCTIME_FORMAT,
7caec0a Michael G. Schwern Implement asctime64() and asctime64_r()
authored
795 wday_name[date->tm_wday],
796 mon_name[date->tm_mon],
797 date->tm_mday, date->tm_hour,
798 date->tm_min, date->tm_sec,
799 1900 + date->tm_year);
800
801 return result;
802 }
803
804
855f57d Michael G. Schwern Implement ctime64() and ctime64_r()
authored
805 char *ctime64_r( const Time64_T* time, char* result ) {
806 struct TM date;
807
808 localtime64_r( time, &date );
809 return asctime64_r( &date, result );
810 }
811
812
7caec0a Michael G. Schwern Implement asctime64() and asctime64_r()
authored
813 /* Non-thread safe versions of the above */
a71803a Michael G. Schwern Implement gmtime64() and localtime64(). Follow the requirement that
authored
814 struct TM *localtime64(const Time64_T *time) {
fbc7937 Michael G. Schwern Ensure localtime() honors the TZ environment variable.
authored
815 tzset();
9ef5a5f Michael G. Schwern Simplify the non-reentrant versions of gmtime and localtime.
authored
816 return localtime64_r(time, &Static_Return_Date);
a71803a Michael G. Schwern Implement gmtime64() and localtime64(). Follow the requirement that
authored
817 }
818
819 struct TM *gmtime64(const Time64_T *time) {
9ef5a5f Michael G. Schwern Simplify the non-reentrant versions of gmtime and localtime.
authored
820 return gmtime64_r(time, &Static_Return_Date);
a71803a Michael G. Schwern Implement gmtime64() and localtime64(). Follow the requirement that
authored
821 }
7caec0a Michael G. Schwern Implement asctime64() and asctime64_r()
authored
822
823 char *asctime64( const struct TM* date ) {
824 return asctime64_r( date, Static_Return_String );
825 }
855f57d Michael G. Schwern Implement ctime64() and ctime64_r()
authored
826
827 char *ctime64( const Time64_T* time ) {
fbc7937 Michael G. Schwern Ensure localtime() honors the TZ environment variable.
authored
828 tzset();
855f57d Michael G. Schwern Implement ctime64() and ctime64_r()
authored
829 return asctime64(localtime64(time));
830 }
Something went wrong with that request. Please try again.