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+ static const LONGLONG UnixEpochOfDate_1601_01_02 = -11644387200000LL ; /* unit: ms */
39+ static const LONGLONG UnixEpochOfDate_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 *
3246 * https://support.microsoft.com/en-us/help/167296/how-to-convert-a-unix-time-t-to-a-win32-filetime-or-systemtime
3347 */
3448static void
35- unix_time_to_filetime (double t , LPFILETIME ft_p )
49+ unix_time_to_filetime (double t , LPFILETIME pft )
3650{
3751 LONGLONG ll = (LONGLONG ) t * TICKS_PER_MS + UNIX_EPOCH_IN_TICKS ;
38-
39- /* FILETIME values before the epoch are invalid. */
40- if (ll < 0 )
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 ) UnixEpochOfDate_1601_01_02 )
4160 {
42- ll = 0 ;
61+ t = ( double ) UnixEpochOfDate_1601_01_02 ;
4362 }
4463
45- ft_p -> dwLowDateTime = (DWORD ) ll ;
46- ft_p -> dwHighDateTime = (DWORD ) (ll >> 32 );
47- } /* unix_time_to_file_time */
64+ /* Like above, do not use the last supported day */
65+ if (t > (double ) UnixEpochOfDate_30827_12_29 )
66+ {
67+ t = (double ) UnixEpochOfDate_30827_12_29 ;
68+ }
69+ pft -> dwLowDateTime = (DWORD ) ll ;
70+ pft -> dwHighDateTime = (DWORD ) (ll >> 32 );
71+ } /* unix_time_to_filetime */
4872
4973/**
5074 * Convert a FILETIME to a unix time value.
@@ -58,7 +82,7 @@ filetime_to_unix_time (LPFILETIME ft_p)
5882 date .HighPart = ft_p -> dwHighDateTime ;
5983 date .LowPart = ft_p -> dwLowDateTime ;
6084 return (double ) (((LONGLONG ) date .QuadPart - UNIX_EPOCH_IN_TICKS ) / TICKS_PER_MS );
61- } /* FileTimeToUnixTimeMs */
85+ } /* filetime_to_unix_time */
6286
6387/**
6488 * Default implementation of jerry_port_local_tza.
0 commit comments