aboutsummaryrefslogtreecommitdiffstats
path: root/lib/time_rz.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/time_rz.c')
-rw-r--r--lib/time_rz.c51
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. */
55static timezone_t const local_tz = (timezone_t) 1; 55static 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. */
61static bool
62isdst_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. */
68static int
69equal_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 }