This source file includes following definitions.
- my_tzset
- shr
- leapyear
- isdst_differ
- ydhms_diff
- long_int_avg
- tm_diff
- convert_time
- ranged_convert
- __mktime_internal
- __mktime64
- libc_hidden_def
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 #ifndef _LIBC
34 # include <libc-config.h>
35 #endif
36
37
38
39
40 #ifndef LEAP_SECONDS_POSSIBLE
41 # define LEAP_SECONDS_POSSIBLE 1
42 #endif
43
44 #include <time.h>
45
46 #include <errno.h>
47 #include <limits.h>
48 #include <stdbool.h>
49 #include <stdlib.h>
50 #include <string.h>
51
52 #include <intprops.h>
53 #include <verify.h>
54
55 #ifndef NEED_MKTIME_INTERNAL
56 # define NEED_MKTIME_INTERNAL 0
57 #endif
58 #ifndef NEED_MKTIME_WINDOWS
59 # define NEED_MKTIME_WINDOWS 0
60 #endif
61 #ifndef NEED_MKTIME_WORKING
62 # define NEED_MKTIME_WORKING 0
63 #endif
64
65 #include "mktime-internal.h"
66
67 #if !defined _LIBC && (NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS)
68 static void
69 my_tzset (void)
70 {
71 # if NEED_MKTIME_WINDOWS
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94 const char *tz = getenv ("TZ");
95 if (tz != NULL && strchr (tz, '/') != NULL)
96 _putenv ("TZ=");
97 # else
98 tzset ();
99 # endif
100 }
101 # undef __tzset
102 # define __tzset() my_tzset ()
103 #endif
104
105 #if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_INTERNAL
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121 #if INT_MAX <= LONG_MAX / 4 / 366 / 24 / 60 / 60
122 typedef long int long_int;
123 #else
124 typedef long long int long_int;
125 #endif
126 verify (INT_MAX <= TYPE_MAXIMUM (long_int) / 4 / 366 / 24 / 60 / 60);
127
128
129
130
131
132
133
134
135
136
137
138 static long_int
139 shr (long_int a, int b)
140 {
141 long_int one = 1;
142 return (-one >> 1 == -1
143 ? a >> b
144 : (a + (a < 0)) / (one << b) - (a < 0));
145 }
146
147
148
149 static long_int const mktime_min
150 = ((TYPE_SIGNED (__time64_t)
151 && TYPE_MINIMUM (__time64_t) < TYPE_MINIMUM (long_int))
152 ? TYPE_MINIMUM (long_int) : TYPE_MINIMUM (__time64_t));
153 static long_int const mktime_max
154 = (TYPE_MAXIMUM (long_int) < TYPE_MAXIMUM (__time64_t)
155 ? TYPE_MAXIMUM (long_int) : TYPE_MAXIMUM (__time64_t));
156
157 #define EPOCH_YEAR 1970
158 #define TM_YEAR_BASE 1900
159 verify (TM_YEAR_BASE % 100 == 0);
160
161
162 static bool
163 leapyear (long_int year)
164 {
165
166
167 return
168 ((year & 3) == 0
169 && (year % 100 != 0
170 || ((year / 100) & 3) == (- (TM_YEAR_BASE / 100) & 3)));
171 }
172
173
174 #ifndef _LIBC
175 static
176 #endif
177 const unsigned short int __mon_yday[2][13] =
178 {
179
180 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
181
182 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
183 };
184
185
186
187
188 static bool
189 isdst_differ (int a, int b)
190 {
191 return (!a != !b) && (0 <= a) && (0 <= b);
192 }
193
194
195
196
197
198
199
200
201
202
203
204 static long_int
205 ydhms_diff (long_int year1, long_int yday1, int hour1, int min1, int sec1,
206 int year0, int yday0, int hour0, int min0, int sec0)
207 {
208 verify (-1 / 2 == 0);
209
210
211
212 int a4 = shr (year1, 2) + shr (TM_YEAR_BASE, 2) - ! (year1 & 3);
213 int b4 = shr (year0, 2) + shr (TM_YEAR_BASE, 2) - ! (year0 & 3);
214 int a100 = (a4 + (a4 < 0)) / 25 - (a4 < 0);
215 int b100 = (b4 + (b4 < 0)) / 25 - (b4 < 0);
216 int a400 = shr (a100, 2);
217 int b400 = shr (b100, 2);
218 int intervening_leap_days = (a4 - b4) - (a100 - b100) + (a400 - b400);
219
220
221 long_int years = year1 - year0;
222 long_int days = 365 * years + yday1 - yday0 + intervening_leap_days;
223 long_int hours = 24 * days + hour1 - hour0;
224 long_int minutes = 60 * hours + min1 - min0;
225 long_int seconds = 60 * minutes + sec1 - sec0;
226 return seconds;
227 }
228
229
230
231 static long_int
232 long_int_avg (long_int a, long_int b)
233 {
234 return shr (a, 1) + shr (b, 1) + ((a | b) & 1);
235 }
236
237
238
239
240
241
242
243
244 static long_int
245 tm_diff (long_int year, long_int yday, int hour, int min, int sec,
246 struct tm const *tp)
247 {
248 return ydhms_diff (year, yday, hour, min, sec,
249 tp->tm_year, tp->tm_yday,
250 tp->tm_hour, tp->tm_min, tp->tm_sec);
251 }
252
253
254
255
256 static struct tm *
257 convert_time (struct tm *(*convert) (const __time64_t *, struct tm *),
258 long_int t, struct tm *tm)
259 {
260 __time64_t x = t;
261 return convert (&x, tm);
262 }
263
264
265
266
267
268
269 static struct tm *
270 ranged_convert (struct tm *(*convert) (const __time64_t *, struct tm *),
271 long_int *t, struct tm *tp)
272 {
273 long_int t1 = (*t < mktime_min ? mktime_min
274 : *t <= mktime_max ? *t : mktime_max);
275 struct tm *r = convert_time (convert, t1, tp);
276 if (r)
277 {
278 *t = t1;
279 return r;
280 }
281 if (errno != EOVERFLOW)
282 return NULL;
283
284 long_int bad = t1;
285 long_int ok = 0;
286 struct tm oktm; oktm.tm_sec = -1;
287
288
289
290
291 while (true)
292 {
293 long_int mid = long_int_avg (ok, bad);
294 if (mid == ok || mid == bad)
295 break;
296 if (convert_time (convert, mid, tp))
297 ok = mid, oktm = *tp;
298 else if (errno != EOVERFLOW)
299 return NULL;
300 else
301 bad = mid;
302 }
303
304 if (oktm.tm_sec < 0)
305 return NULL;
306 *t = ok;
307 *tp = oktm;
308 return tp;
309 }
310
311
312
313
314
315
316
317
318
319
320 __time64_t
321 __mktime_internal (struct tm *tp,
322 struct tm *(*convert) (const __time64_t *, struct tm *),
323 mktime_offset_t *offset)
324 {
325 struct tm tm;
326
327
328
329
330
331 int remaining_probes = 6;
332
333
334
335 int sec = tp->tm_sec;
336 int min = tp->tm_min;
337 int hour = tp->tm_hour;
338 int mday = tp->tm_mday;
339 int mon = tp->tm_mon;
340 int year_requested = tp->tm_year;
341 int isdst = tp->tm_isdst;
342
343
344 int dst2 = 0;
345
346
347 int mon_remainder = mon % 12;
348 int negative_mon_remainder = mon_remainder < 0;
349 int mon_years = mon / 12 - negative_mon_remainder;
350 long_int lyear_requested = year_requested;
351 long_int year = lyear_requested + mon_years;
352
353
354
355
356
357
358 int mon_yday = ((__mon_yday[leapyear (year)]
359 [mon_remainder + 12 * negative_mon_remainder])
360 - 1);
361 long_int lmday = mday;
362 long_int yday = mon_yday + lmday;
363
364 mktime_offset_t off = *offset;
365 int negative_offset_guess;
366
367 int sec_requested = sec;
368
369 if (LEAP_SECONDS_POSSIBLE)
370 {
371
372
373 if (sec < 0)
374 sec = 0;
375 if (59 < sec)
376 sec = 59;
377 }
378
379
380
381
382 INT_SUBTRACT_WRAPV (0, off, &negative_offset_guess);
383 long_int t0 = ydhms_diff (year, yday, hour, min, sec,
384 EPOCH_YEAR - TM_YEAR_BASE, 0, 0, 0,
385 negative_offset_guess);
386 long_int t = t0, t1 = t0, t2 = t0;
387
388
389
390 while (true)
391 {
392 if (! ranged_convert (convert, &t, &tm))
393 return -1;
394 long_int dt = tm_diff (year, yday, hour, min, sec, &tm);
395 if (dt == 0)
396 break;
397
398 if (t == t1 && t != t2
399 && (tm.tm_isdst < 0
400 || (isdst < 0
401 ? dst2 <= (tm.tm_isdst != 0)
402 : (isdst != 0) != (tm.tm_isdst != 0))))
403
404
405
406
407
408
409
410
411
412 goto offset_found;
413
414 remaining_probes--;
415 if (remaining_probes == 0)
416 {
417 __set_errno (EOVERFLOW);
418 return -1;
419 }
420
421 t1 = t2, t2 = t, t += dt, dst2 = tm.tm_isdst != 0;
422 }
423
424
425
426 if (isdst_differ (isdst, tm.tm_isdst))
427 {
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442 int stride = 601200;
443
444
445
446
447
448
449 int duration_max = 536454000;
450
451
452
453 int delta_bound = duration_max / 2 + stride;
454
455 int delta, direction;
456
457 for (delta = stride; delta < delta_bound; delta += stride)
458 for (direction = -1; direction <= 1; direction += 2)
459 {
460 long_int ot;
461 if (! INT_ADD_WRAPV (t, delta * direction, &ot))
462 {
463 struct tm otm;
464 if (! ranged_convert (convert, &ot, &otm))
465 return -1;
466 if (! isdst_differ (isdst, otm.tm_isdst))
467 {
468
469
470 long_int gt = ot + tm_diff (year, yday, hour, min, sec,
471 &otm);
472 if (mktime_min <= gt && gt <= mktime_max)
473 {
474 if (convert_time (convert, gt, &tm))
475 {
476 t = gt;
477 goto offset_found;
478 }
479 if (errno != EOVERFLOW)
480 return -1;
481 }
482 }
483 }
484 }
485
486 __set_errno (EOVERFLOW);
487 return -1;
488 }
489
490 offset_found:
491
492
493
494 INT_SUBTRACT_WRAPV (t, t0, offset);
495 INT_SUBTRACT_WRAPV (*offset, negative_offset_guess, offset);
496
497 if (LEAP_SECONDS_POSSIBLE && sec_requested != tm.tm_sec)
498 {
499
500
501 long_int sec_adjustment = sec == 0 && tm.tm_sec == 60;
502 sec_adjustment -= sec;
503 sec_adjustment += sec_requested;
504 if (INT_ADD_WRAPV (t, sec_adjustment, &t)
505 || ! (mktime_min <= t && t <= mktime_max))
506 {
507 __set_errno (EOVERFLOW);
508 return -1;
509 }
510 if (! convert_time (convert, t, &tm))
511 return -1;
512 }
513
514 *tp = tm;
515 return t;
516 }
517
518 #endif
519
520 #if defined _LIBC || NEED_MKTIME_WORKING || NEED_MKTIME_WINDOWS
521
522
523 __time64_t
524 __mktime64 (struct tm *tp)
525 {
526
527
528
529 __tzset ();
530
531 # if defined _LIBC || NEED_MKTIME_WORKING
532 static mktime_offset_t localtime_offset;
533 return __mktime_internal (tp, __localtime64_r, &localtime_offset);
534 # else
535 # undef mktime
536 return mktime (tp);
537 # endif
538 }
539 #endif
540
541 #if defined _LIBC && __TIMESIZE != 64
542
543 libc_hidden_def (__mktime64)
544
545 time_t
546 mktime (struct tm *tp)
547 {
548 struct tm tm = *tp;
549 __time64_t t = __mktime64 (&tm);
550 if (in_time_t_range (t))
551 {
552 *tp = tm;
553 return t;
554 }
555 else
556 {
557 __set_errno (EOVERFLOW);
558 return -1;
559 }
560 }
561
562 #endif
563
564 weak_alias (mktime, timelocal)
565 libc_hidden_def (mktime)
566 libc_hidden_weak (timelocal)