Skip to content

Commit 104a967

Browse files
authored
Fix localtime() and gmtime() with 64bit time_t (#17471)
See: #17393
1 parent 73c1d12 commit 104a967

File tree

3 files changed

+46
-2
lines changed

3 files changed

+46
-2
lines changed

src/library.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -510,9 +510,10 @@ mergeInto(LibraryManager.library, {
510510
return (date.getTime() / 1000)|0;
511511
},
512512

513+
_gmtime_js__deps: ['$readI53FromI64'],
513514
_gmtime_js__sig: 'ipp',
514515
_gmtime_js: function(time, tmPtr) {
515-
var date = new Date({{{ makeGetValue('time', 0, 'i32') }}}*1000);
516+
var date = new Date({{{ makeGetValue('time', 0, 'i53') }}}*1000);
516517
{{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_sec, 'date.getUTCSeconds()', 'i32') }}};
517518
{{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_min, 'date.getUTCMinutes()', 'i32') }}};
518519
{{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_hour, 'date.getUTCHours()', 'i32') }}};
@@ -544,9 +545,10 @@ mergeInto(LibraryManager.library, {
544545
return (date.getTime() / 1000)|0;
545546
},
546547

548+
_localtime_js__deps: ['$readI53FromI64'],
547549
_localtime_js__sig: 'ipp',
548550
_localtime_js: function(time, tmPtr) {
549-
var date = new Date({{{ makeGetValue('time', 0, 'i32') }}}*1000);
551+
var date = new Date({{{ makeGetValue('time', 0, 'i53') }}}*1000);
550552
{{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_sec, 'date.getSeconds()', 'i32') }}};
551553
{{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_min, 'date.getMinutes()', 'i32') }}};
552554
{{{ makeSetValue('tmPtr', C_STRUCTS.tm.tm_hour, 'date.getHours()', 'i32') }}};

tests/core/test_time.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,30 @@
1010
#include <assert.h>
1111
#include <math.h>
1212

13+
void
14+
check_gmtime_localtime(time_t time)
15+
{
16+
char gmbuf[32], locbuf[32];
17+
const char fmt[] = "%Y-%m-%d %H:%M:%S";
18+
struct tm *gm;
19+
struct tm *loc;
20+
21+
gm = gmtime(&time);
22+
assert(gm);
23+
assert(strftime(gmbuf, sizeof(gmbuf) - 1, fmt, gm) > 0);
24+
loc = localtime(&time);
25+
assert(loc);
26+
assert(strftime(locbuf, sizeof(locbuf) - 1, fmt, loc) > 0);
27+
28+
// gmtime and localtime are only equal when timezone is UTC
29+
if ((timezone == 0) && (strcmp(gmbuf, locbuf) != 0)) {
30+
printf("time: %lld, gmtime: %s != localtime: %s\n", time, gmbuf, locbuf);
31+
puts("failed");
32+
} else {
33+
printf("time: %lld, gmtime: %s\n", time, gmbuf);
34+
}
35+
}
36+
1337
int main() {
1438
time_t xmas2002 = 1040786563ll;
1539
time_t summer2002 = 1025528525ll;
@@ -216,5 +240,15 @@ int main() {
216240
clock_gettime(CLOCK_REALTIME, &ts_clock_gettime);
217241
printf("timespec_get test 6: %d\n", abs(ts_timespec_get.tv_sec - ts_clock_gettime.tv_sec) <= 2);
218242

243+
// verify gmtime() and localtime()
244+
check_gmtime_localtime(0);
245+
check_gmtime_localtime(2147483647); // int8_t max, Y2K38
246+
check_gmtime_localtime(2147483648);
247+
check_gmtime_localtime(-2147483648); // int8_t min
248+
check_gmtime_localtime(-2147483649);
249+
check_gmtime_localtime(253402300799); // end of year 9999
250+
check_gmtime_localtime(-62135596800); // beginning of year 1
251+
252+
puts("success");
219253
return 0;
220254
}

tests/core/test_time.out

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,11 @@ timespec_get test 3: 1
5151
timespec_get test 4: 1
5252
timespec_get test 5: 1
5353
timespec_get test 6: 1
54+
time: 0, gmtime: 1970-01-01 00:00:00
55+
time: 2147483647, gmtime: 2038-01-19 03:14:07
56+
time: 2147483648, gmtime: 2038-01-19 03:14:08
57+
time: -2147483648, gmtime: 1901-12-13 20:45:52
58+
time: -2147483649, gmtime: 1901-12-13 20:45:51
59+
time: 253402300799, gmtime: 9999-12-31 23:59:59
60+
time: -62135596800, gmtime: 1-01-01 00:00:00
61+
success

0 commit comments

Comments
 (0)