#endif
{ 2007, 11, 7, 1, 7, 20 },
{ 1970, 1, 1, 0, 0, 0 },
- { 2038, 1, 19, 3, 14, 7 }
+ { 2038, 1, 19, 3, 14, 7 },
+ { INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX, INT_MAX },
+ { 2038, 1, 19, 3, 14, 8 },
+ { 2106, 2, 7, 6, 28, 15 },
+ { 2106, 2, 7, 6, 28, 16 },
+ /* June leap second */
+ { 2015, 6, 30, 23, 59, 59 },
+ { 2015, 6, 30, 23, 59, 60 },
+ { 2015, 7, 1, 0, 0, 0 },
+ /* Invalid leap second */
+ { 2017, 1, 24, 16, 40, 60 },
+ /* Dec leap second */
+ { 2016, 12, 31, 23, 59, 59 },
+ { 2016, 12, 31, 23, 59, 60 },
+ { 2017, 1, 1, 0, 0, 0 },
};
static time_t output[] = {
#ifdef TIME_T_SIGNED
#endif
1194397640,
0,
- 2147483647
+ 2147483647,
+ -1,
+ 2147483648,
+ 4294967295,
+ 4294967296,
+ /* June leap second */
+ 1435708799,
+ 1435708799,
+ 1435708800,
+ /* Invalid leap second - utc_mktime() doesn't mind */
+ 1485276059,
+ /* Dec leap second */
+ 1483228799,
+ 1483228799,
+ 1483228800,
};
+ i_assert(N_ELEMENTS(input) == N_ELEMENTS(output));
struct tm tm;
unsigned int i;
time_t t;
return tm1->tm_sec - tm2->tm_sec;
}
+static inline void adjust_leap_second(struct tm *tm)
+{
+ if (tm->tm_sec == 60)
+ tm->tm_sec = 59;
+}
+
#ifdef HAVE_TIMEGM
+/* Normalization done by timegm is considered a failure here, since it means
+ * the timestamp is not valid as-is. Leap second 60 is adjusted to 59 before
+ * this though. */
time_t utc_mktime(const struct tm *tm)
{
- struct tm mod_tm = *tm;
+ struct tm leap_adj_tm = *tm;
+ adjust_leap_second(&leap_adj_tm);
+ struct tm tmp = leap_adj_tm;
time_t t;
- t = timegm(&mod_tm);
- if (tm_cmp(tm, &mod_tm) != 0)
+ t = timegm(&tmp);
+ if (tm_cmp(&leap_adj_tm, &tmp) != 0)
return (time_t)-1;
return t;
}
#else
time_t utc_mktime(const struct tm *tm)
{
+ struct tm leap_adj_tm = *tm;
+ adjust_leap_second(&leap_adj_tm);
const struct tm *try_tm;
time_t t;
int bits, dir;
#endif
for (bits = TIME_T_MAX_BITS - 2;; bits--) {
try_tm = gmtime(&t);
- dir = tm_cmp(tm, try_tm);
+ dir = tm_cmp(&leap_adj_tm, try_tm);
if (dir == 0)
return t;
if (bits < 0)