diff options
Diffstat (limited to 'gl/mktime.c')
-rw-r--r-- | gl/mktime.c | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/gl/mktime.c b/gl/mktime.c index ae721c72..7dc9d67e 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 | } |