From 104a9676a95d8fab94740d542bf481ce6d222399 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Tue, 19 Jul 2022 18:19:30 +0200 Subject: [PATCH] Fix localtime() and gmtime() with 64bit time_t (#17471) See: #17393 --- src/library.js | 6 ++++-- tests/core/test_time.cpp | 34 ++++++++++++++++++++++++++++++++++ tests/core/test_time.out | 8 ++++++++ 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/library.js b/src/library.js index 1b71d25430b17..2ebdd0cd8f11e 100644 --- a/src/library.js +++ b/src/library.js @@ -510,9 +510,10 @@ mergeInto(LibraryManager.library, { return (date.getTime() / 1000)|0; }, + _gmtime_js__deps: ['$readI53FromI64'], _gmtime_js__sig: 'ipp', _gmtime_js: function(time, tmPtr) { - var date = new Date({{{ makeGetValue('time', 0, 'i32') }}}*1000); + var date = new Date({{{ makeGetValue('time', 0, 'i53') }}}*1000); {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_sec, 'date.getUTCSeconds()', 'i32') }}}; {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_min, 'date.getUTCMinutes()', 'i32') }}}; {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_hour, 'date.getUTCHours()', 'i32') }}}; @@ -544,9 +545,10 @@ mergeInto(LibraryManager.library, { return (date.getTime() / 1000)|0; }, + _localtime_js__deps: ['$readI53FromI64'], _localtime_js__sig: 'ipp', _localtime_js: function(time, tmPtr) { - var date = new Date({{{ makeGetValue('time', 0, 'i32') }}}*1000); + var date = new Date({{{ makeGetValue('time', 0, 'i53') }}}*1000); {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_sec, 'date.getSeconds()', 'i32') }}}; {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_min, 'date.getMinutes()', 'i32') }}}; {{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_hour, 'date.getHours()', 'i32') }}}; diff --git a/tests/core/test_time.cpp b/tests/core/test_time.cpp index 0c05d92f0034e..59a60e66b968b 100644 --- a/tests/core/test_time.cpp +++ b/tests/core/test_time.cpp @@ -10,6 +10,30 @@ #include #include +void +check_gmtime_localtime(time_t time) +{ + char gmbuf[32], locbuf[32]; + const char fmt[] = "%Y-%m-%d %H:%M:%S"; + struct tm *gm; + struct tm *loc; + + gm = gmtime(&time); + assert(gm); + assert(strftime(gmbuf, sizeof(gmbuf) - 1, fmt, gm) > 0); + loc = localtime(&time); + assert(loc); + assert(strftime(locbuf, sizeof(locbuf) - 1, fmt, loc) > 0); + + // gmtime and localtime are only equal when timezone is UTC + if ((timezone == 0) && (strcmp(gmbuf, locbuf) != 0)) { + printf("time: %lld, gmtime: %s != localtime: %s\n", time, gmbuf, locbuf); + puts("failed"); + } else { + printf("time: %lld, gmtime: %s\n", time, gmbuf); + } +} + int main() { time_t xmas2002 = 1040786563ll; time_t summer2002 = 1025528525ll; @@ -216,5 +240,15 @@ int main() { clock_gettime(CLOCK_REALTIME, &ts_clock_gettime); printf("timespec_get test 6: %d\n", abs(ts_timespec_get.tv_sec - ts_clock_gettime.tv_sec) <= 2); + // verify gmtime() and localtime() + check_gmtime_localtime(0); + check_gmtime_localtime(2147483647); // int8_t max, Y2K38 + check_gmtime_localtime(2147483648); + check_gmtime_localtime(-2147483648); // int8_t min + check_gmtime_localtime(-2147483649); + check_gmtime_localtime(253402300799); // end of year 9999 + check_gmtime_localtime(-62135596800); // beginning of year 1 + + puts("success"); return 0; } diff --git a/tests/core/test_time.out b/tests/core/test_time.out index d8ae1716f77eb..daa6bd254b370 100644 --- a/tests/core/test_time.out +++ b/tests/core/test_time.out @@ -51,3 +51,11 @@ timespec_get test 3: 1 timespec_get test 4: 1 timespec_get test 5: 1 timespec_get test 6: 1 +time: 0, gmtime: 1970-01-01 00:00:00 +time: 2147483647, gmtime: 2038-01-19 03:14:07 +time: 2147483648, gmtime: 2038-01-19 03:14:08 +time: -2147483648, gmtime: 1901-12-13 20:45:52 +time: -2147483649, gmtime: 1901-12-13 20:45:51 +time: 253402300799, gmtime: 9999-12-31 23:59:59 +time: -62135596800, gmtime: 1-01-01 00:00:00 +success