summaryrefslogtreecommitdiffstats
path: root/gl/mktime.c
diff options
context:
space:
mode:
Diffstat (limited to 'gl/mktime.c')
-rw-r--r--gl/mktime.c30
1 files changed, 21 insertions, 9 deletions
diff --git a/gl/mktime.c b/gl/mktime.c
index ae721c7..7dc9d67 100644
--- a/gl/mktime.c
+++ b/gl/mktime.c
@@ -1,5 +1,5 @@
1/* Convert a 'struct tm' to a time_t value. 1/* Convert a 'struct tm' to a time_t value.
2 Copyright (C) 1993-2021 Free Software Foundation, Inc. 2 Copyright (C) 1993-2022 Free Software Foundation, Inc.
3 This file is part of the GNU C Library. 3 This file is part of the GNU C Library.
4 Contributed by Paul Eggert <eggert@twinsun.com>. 4 Contributed by Paul Eggert <eggert@twinsun.com>.
5 5
@@ -429,8 +429,13 @@ __mktime_internal (struct tm *tp,
429 time with the right value, and use its UTC offset. 429 time with the right value, and use its UTC offset.
430 430
431 Heuristic: probe the adjacent timestamps in both directions, 431 Heuristic: probe the adjacent timestamps in both directions,
432 looking for the desired isdst. This should work for all real 432 looking for the desired isdst. If none is found within a
433 time zone histories in the tz database. */ 433 reasonable duration bound, assume a one-hour DST difference.
434 This should work for all real time zone histories in the tz
435 database. */
436
437 /* +1 if we wanted standard time but got DST, -1 if the reverse. */
438 int dst_difference = (isdst == 0) - (tm.tm_isdst == 0);
434 439
435 /* Distance between probes when looking for a DST boundary. In 440 /* Distance between probes when looking for a DST boundary. In
436 tzdata2003a, the shortest period of DST is 601200 seconds 441 tzdata2003a, the shortest period of DST is 601200 seconds
@@ -441,12 +446,14 @@ __mktime_internal (struct tm *tp,
441 periods when probing. */ 446 periods when probing. */
442 int stride = 601200; 447 int stride = 601200;
443 448
444 /* The longest period of DST in tzdata2003a is 536454000 seconds 449 /* In TZDB 2021e, the longest period of DST (or of non-DST), in
445 (e.g., America/Jujuy starting 1946-10-01 01:00). The longest 450 which the DST (or adjacent DST) difference is not one hour,
446 period of non-DST is much longer, but it makes no real sense 451 is 457243209 seconds: e.g., America/Cambridge_Bay with leap
447 to search for more than a year of non-DST, so use the DST 452 seconds, starting 1965-10-31 00:00 in a switch from
448 max. */ 453 double-daylight time (-05) to standard time (-07), and
449 int duration_max = 536454000; 454 continuing to 1980-04-27 02:00 in a switch from standard time
455 (-07) to daylight time (-06). */
456 int duration_max = 457243209;
450 457
451 /* Search in both directions, so the maximum distance is half 458 /* Search in both directions, so the maximum distance is half
452 the duration; add the stride to avoid off-by-1 problems. */ 459 the duration; add the stride to avoid off-by-1 problems. */
@@ -483,6 +490,11 @@ __mktime_internal (struct tm *tp,
483 } 490 }
484 } 491 }
485 492
493 /* No unusual DST offset was found nearby. Assume one-hour DST. */
494 t += 60 * 60 * dst_difference;
495 if (mktime_min <= t && t <= mktime_max && convert_time (convert, t, &tm))
496 goto offset_found;
497
486 __set_errno (EOVERFLOW); 498 __set_errno (EOVERFLOW);
487 return -1; 499 return -1;
488 } 500 }