Skip to content

Commit b629b5b

Browse files
committed
Revise implementation of jerry_port_get_local_time_zone_adjustment on Win32
Handle the limitation of Win32 date API properly. JerryScript-DCO-1.0-Signed-off-by: Yonggang Luo [email protected]
1 parent 43f5026 commit b629b5b

File tree

2 files changed

+31
-5
lines changed

2 files changed

+31
-5
lines changed

jerry-port/win/jerry-port-win-date.c

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,20 @@
2626
#define UNIX_EPOCH_IN_TICKS 116444736000000000ull /* difference between 1970 and 1601 */
2727
#define TICKS_PER_MS 10000ull /* 1 tick is 100 nanoseconds */
2828

29+
/*
30+
* If you take the limit of SYSTEMTIME (last millisecond in 30827) then you end up with
31+
* a FILETIME of 0x7fff35f4f06c58f0 by using SystemTimeToFileTime(). However, if you put
32+
* 0x7fffffffffffffff into FileTimeToSystemTime() then you will end up in the year 30828,
33+
* although this date is invalid for SYSTEMTIME. Any larger value (0x8000000000000000 and above)
34+
* causes FileTimeToSystemTime() to fail.
35+
* https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-systemtime
36+
* https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime
37+
*/
38+
#define UNIX_EPOCH_DATE_1601_01_02 -11644387200000LL /* unit: ms */
39+
#define UNIX_EPOCH_DATE_30827_12_29 9106702560000000LL /* unit: ms */
40+
41+
/* https://support.microsoft.com/en-us/help/167296/how-to-convert-a-unix-time-t-to-a-win32-filetime-or-systemtime */
42+
2943
/**
3044
* Convert unix time to a FILETIME value.
3145
*
@@ -35,16 +49,27 @@ static void
3549
unix_time_to_filetime (double t, LPFILETIME ft_p)
3650
{
3751
LONGLONG ll = (LONGLONG) t * TICKS_PER_MS + UNIX_EPOCH_IN_TICKS;
52+
/*
53+
* If the time is earlier than the date 1601-01-02, then always using date 1601-01-02 to
54+
* query time zone adjustment. This date (1601-01-02) will make sure both UTC and local
55+
* time succeed with Win32 API. The date 1601-01-01 may lead to a win32 api failure, as
56+
* after converting between local time and utc time, the time may be earlier than 1601-01-01
57+
* in UTC time, that exceeds the FILETIME representation range.
58+
*/
59+
if (t < (double) UNIX_EPOCH_DATE_1601_01_02)
60+
{
61+
t = (double) UNIX_EPOCH_DATE_1601_01_02;
62+
}
3863

39-
/* FILETIME values before the epoch are invalid. */
40-
if (ll < 0)
64+
/* Like above, do not use the last supported day */
65+
if (t > (double) UNIX_EPOCH_DATE_30827_12_29)
4166
{
42-
ll = 0;
67+
t = (double) UNIX_EPOCH_DATE_30827_12_29;
4368
}
4469

4570
ft_p->dwLowDateTime = (DWORD) ll;
4671
ft_p->dwHighDateTime = (DWORD) (ll >> 32);
47-
} /* unix_time_to_file_time */
72+
} /* unix_time_to_filetime */
4873

4974
/**
5075
* Convert a FILETIME to a unix time value.
@@ -58,7 +83,7 @@ filetime_to_unix_time (LPFILETIME ft_p)
5883
date.HighPart = ft_p->dwHighDateTime;
5984
date.LowPart = ft_p->dwLowDateTime;
6085
return (double) (((LONGLONG) date.QuadPart - UNIX_EPOCH_IN_TICKS) / TICKS_PER_MS);
61-
} /* FileTimeToUnixTimeMs */
86+
} /* filetime_to_unix_time */
6287

6388
/**
6489
* Default implementation of jerry_port_local_tza.

tests/jerry/date-getters.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ assert (isNaN (d.getTimezoneOffset()));
9797
/* 5. test case */
9898
assert (new Date(2013, -1).getMonth() === 11);
9999
assert (new Date(-2, -2).getFullYear() === -3);
100+
assert (new Date(30888, 2).getFullYear() === 30888);
100101
assert (new Date(-1, -1).getFullYear() === -2);
101102
assert (new Date(-1, -1, -1).getMonth() === 10);
102103
assert (new Date(-1, -1, -1, -1).getDate() === 28);

0 commit comments

Comments
 (0)