Skip to content

Commit

Permalink
Improvements for issues #2
Browse files Browse the repository at this point in the history
- units now accurately reflect the tm_isdst return value
- partial fix to library so correct tm_isdst is returned on non-switchover days
- tm_isdst will continue to be wrong on dst switchover days until issue #1 is fixed
  • Loading branch information
mnp committed Jan 30, 2015
1 parent f5279ba commit 9a9a148
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 19 deletions.
11 changes: 11 additions & 0 deletions fast-mktime.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,16 @@ time_t mktime(struct tm *tm)
{
/* cached - just add h,m,s from request to midnight */
result = time_cache + hmsarg;

/* Obscure, but documented, return value: only this value in arg struct.
*
* BUG: dst switchover was computed by mktime_real() for time 00:00:00
* of arg day. So this return value WILL be wrong for switchover days
* after the switchover occurs. There is no clean way to detect this
* situation in stock glibc. This bug will be reflected in unit test
* until fixed. See also github issues #1 and #2.
*/
tm->tm_isdst = cache.tm_isdst;
}
else
{
Expand All @@ -54,6 +64,7 @@ time_t mktime(struct tm *tm)
cache.tm_mon = tm->tm_mon;
cache.tm_year = tm->tm_year;
time_cache = mktime_real(&cache);
tm->tm_isdst = cache.tm_isdst;

result = (-1 == time_cache) ? -1 : time_cache + hmsarg;
}
Expand Down
42 changes: 23 additions & 19 deletions unittest.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
#include <string.h>
#include <assert.h>

void ok(int sec, int min, int hour, int day, int month, int year,
time_t expect, const char *title)
void ok(int sec, int min, int hour, int day, int month, int year, int isdst,
time_t expect_time, int expect_isdst, const char *title)
{
struct tm s;
s.tm_sec = sec;
Expand All @@ -20,15 +20,19 @@ void ok(int sec, int min, int hour, int day, int month, int year,
s.tm_mday = day;
s.tm_mon = month;
s.tm_year = year;
s.tm_isdst = -1;
s.tm_isdst = isdst;

time_t result = mktime(&s);

printf(" %s: got %10lu expected %10lu (isdst %d) -- %s\n",
(result == expect ? "okay" : "fail"),
printf(" %s: got t=%-10lu expected t=%-10lu -- %s\n",
(result == expect_time ? "okay" : "FAIL"),
(unsigned long)result,
(unsigned long)expect,
(unsigned long)expect_time,
title);
printf(" %s: got dst=%-8d expected dst=%-8d -- %s\n",
(s.tm_isdst == expect_isdst ? "okay" : "FAIL"),
s.tm_isdst,
expect_isdst,
title);
}

Expand All @@ -39,14 +43,14 @@ int main()
tzset();

// basic function checks for UTC
// s m h D M Y expect title
ok(39, 19, 20, 28, 5, 113, 1372450779, "sometime Fri Jun 28 20:19:39 2013 UTC");
ok(40, 20, 21, 28, 5, 113, 1372454440, "same day Fri Jun 28 21:20:40 2013 UTC");
ok(59, 59, 23, 29, 5, 113, 1372550399, "end of day Sat Jun 29 23:59:59 2013 UTC");
ok(0, 0, 0, 30, 5, 113, 1372550400, "next day Sun Jun 30 00:00:00 2013 UTC");
ok(40, 20, 21, 29, 5, 113, 1372540840, "next day Sat Jun 29 21:20:40 2013 UTC");
ok(0, 0, 0, 1, 0, 70, 0, "min epoch Thu Jan 1 00:00:00 1970 UTC");
ok(59, 59, 18, 31, 11, 137, 2145898799, "max epoch Thu Dec 31 18:59:59 2037 UTC");
// s m h D M Y dst expect title
ok(39, 19, 20, 28, 5, 113, -1, 1372450779, 0, "sometime Fri Jun 28 20:19:39 2013 UTC");
ok(40, 20, 21, 28, 5, 113, -1, 1372454440, 0, "same day Fri Jun 28 21:20:40 2013 UTC");
ok(59, 59, 23, 29, 5, 113, -1, 1372550399, 0, "end of day Sat Jun 29 23:59:59 2013 UTC");
ok(0, 0, 0, 30, 5, 113, -1, 1372550400, 0, "next day Sun Jun 30 00:00:00 2013 UTC");
ok(40, 20, 21, 29, 5, 113, -1, 1372540840, 0, "next day Sat Jun 29 21:20:40 2013 UTC");
ok(0, 0, 0, 1, 0, 70, -1, 0, 0, "min epoch Thu Jan 1 00:00:00 1970 UTC");
ok(59, 59, 18, 31, 11, 137, -1, 2145898799, 0, "max epoch Thu Dec 31 18:59:59 2037 UTC");

// force EDT/EST
putenv((char *)"TZ=US/Eastern");
Expand All @@ -58,11 +62,11 @@ int main()
// US/Eastern Sun Mar 11 07:00:00 2012 UT = Sun Mar 11 03:00:00 2012 EDT isdst=1 gmtoff=-14400
// US/Eastern Sun Nov 4 05:59:59 2012 UT = Sun Nov 4 01:59:59 2012 EDT isdst=1 gmtoff=-14400
// US/Eastern Sun Nov 4 06:00:00 2012 UT = Sun Nov 4 01:00:00 2012 EST isdst=0 gmtoff=-18000
// s m h D M Y expect title
ok(59, 59, 01, 11, 02, 112, 1331449199, "March 2012 dst before");
ok(00, 00, 03, 11, 02, 112, 1331449200, "March 2012 dst after");
ok(59, 59, 01, 04, 10, 112, 1352008799, "Nov 2012 dst before");
ok(00, 00, 01, 04, 10, 112, 1352005200, "Nov 2012 dst after");
// s m h D M Y dst expect title
ok(59, 59, 01, 11, 02, 112, -1, 1331449199, 0, "March 2012 dst before");
ok(00, 00, 03, 11, 02, 112, -1, 1331449200, 1, "March 2012 dst after");
ok(59, 59, 01, 04, 10, 112, -1, 1352008799, 1, "Nov 2012 dst before");
ok(00, 00, 01, 04, 10, 112, -1, 1352005200, 1, "Nov 2012 dst after");

return 0;
}

0 comments on commit 9a9a148

Please sign in to comment.