diff options
Diffstat (limited to 'lib/time_rz.c')
| -rw-r--r-- | lib/time_rz.c | 51 |
1 files changed, 17 insertions, 34 deletions
diff --git a/lib/time_rz.c b/lib/time_rz.c index 5d85963c9ed..95438cf876e 100644 --- a/lib/time_rz.c +++ b/lib/time_rz.c | |||
| @@ -54,31 +54,6 @@ enum { ABBR_SIZE_MIN = DEFAULT_MXFAST - offsetof (struct tm_zone, abbrs) }; | |||
| 54 | matters; the pointer is never dereferenced. */ | 54 | matters; the pointer is never dereferenced. */ |
| 55 | static timezone_t const local_tz = (timezone_t) 1; | 55 | static timezone_t const local_tz = (timezone_t) 1; |
| 56 | 56 | ||
| 57 | #if HAVE_TM_ZONE || HAVE_TZNAME | ||
| 58 | |||
| 59 | /* Return true if the values A and B differ according to the rules for | ||
| 60 | tm_isdst: A and B differ if one is zero and the other positive. */ | ||
| 61 | static bool | ||
| 62 | isdst_differ (int a, int b) | ||
| 63 | { | ||
| 64 | return !a != !b && 0 <= a && 0 <= b; | ||
| 65 | } | ||
| 66 | |||
| 67 | /* Return true if A and B are equal. */ | ||
| 68 | static int | ||
| 69 | equal_tm (const struct tm *a, const struct tm *b) | ||
| 70 | { | ||
| 71 | return ! ((a->tm_sec ^ b->tm_sec) | ||
| 72 | | (a->tm_min ^ b->tm_min) | ||
| 73 | | (a->tm_hour ^ b->tm_hour) | ||
| 74 | | (a->tm_mday ^ b->tm_mday) | ||
| 75 | | (a->tm_mon ^ b->tm_mon) | ||
| 76 | | (a->tm_year ^ b->tm_year) | ||
| 77 | | isdst_differ (a->tm_isdst, b->tm_isdst)); | ||
| 78 | } | ||
| 79 | |||
| 80 | #endif | ||
| 81 | |||
| 82 | /* Copy to ABBRS the abbreviation at ABBR with size ABBR_SIZE (this | 57 | /* Copy to ABBRS the abbreviation at ABBR with size ABBR_SIZE (this |
| 83 | includes its trailing null byte). Append an extra null byte to | 58 | includes its trailing null byte). Append an extra null byte to |
| 84 | mark the end of ABBRS. */ | 59 | mark the end of ABBRS. */ |
| @@ -327,17 +302,25 @@ mktime_z (timezone_t tz, struct tm *tm) | |||
| 327 | timezone_t old_tz = set_tz (tz); | 302 | timezone_t old_tz = set_tz (tz); |
| 328 | if (old_tz) | 303 | if (old_tz) |
| 329 | { | 304 | { |
| 330 | time_t t = mktime (tm); | ||
| 331 | #if HAVE_TM_ZONE || HAVE_TZNAME | ||
| 332 | time_t badtime = -1; | ||
| 333 | struct tm tm_1; | 305 | struct tm tm_1; |
| 334 | if ((t != badtime | 306 | tm_1.tm_sec = tm->tm_sec; |
| 335 | || (localtime_r (&t, &tm_1) && equal_tm (tm, &tm_1))) | 307 | tm_1.tm_min = tm->tm_min; |
| 336 | && !save_abbr (tz, tm)) | 308 | tm_1.tm_hour = tm->tm_hour; |
| 337 | t = badtime; | 309 | tm_1.tm_mday = tm->tm_mday; |
| 310 | tm_1.tm_mon = tm->tm_mon; | ||
| 311 | tm_1.tm_year = tm->tm_year; | ||
| 312 | tm_1.tm_yday = -1; | ||
| 313 | tm_1.tm_isdst = tm->tm_isdst; | ||
| 314 | time_t t = mktime (&tm_1); | ||
| 315 | bool ok = 0 <= tm_1.tm_yday; | ||
| 316 | #if HAVE_TM_ZONE || HAVE_TZNAME | ||
| 317 | ok = ok && save_abbr (tz, &tm_1); | ||
| 338 | #endif | 318 | #endif |
| 339 | if (revert_tz (old_tz)) | 319 | if (revert_tz (old_tz) && ok) |
| 340 | return t; | 320 | { |
| 321 | *tm = tm_1; | ||
| 322 | return t; | ||
| 323 | } | ||
| 341 | } | 324 | } |
| 342 | return -1; | 325 | return -1; |
| 343 | } | 326 | } |