26
26
#define UNIX_EPOCH_IN_TICKS 116444736000000000ull /* difference between 1970 and 1601 */
27
27
#define TICKS_PER_MS 10000ull /* 1 tick is 100 nanoseconds */
28
28
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
+
29
41
/**
30
42
* Convert unix time to a FILETIME value.
31
43
*
@@ -44,7 +56,7 @@ unix_time_to_filetime (double t, LPFILETIME ft_p)
44
56
45
57
ft_p -> dwLowDateTime = (DWORD ) ll ;
46
58
ft_p -> dwHighDateTime = (DWORD ) (ll >> 32 );
47
- } /* unix_time_to_file_time */
59
+ } /* unix_time_to_filetime */
48
60
49
61
/**
50
62
* Convert a FILETIME to a unix time value.
@@ -58,7 +70,7 @@ filetime_to_unix_time (LPFILETIME ft_p)
58
70
date .HighPart = ft_p -> dwHighDateTime ;
59
71
date .LowPart = ft_p -> dwLowDateTime ;
60
72
return (double ) (((LONGLONG ) date .QuadPart - UNIX_EPOCH_IN_TICKS ) / TICKS_PER_MS );
61
- } /* FileTimeToUnixTimeMs */
73
+ } /* filetime_to_unix_time */
62
74
63
75
/**
64
76
* Default implementation of jerry_port_local_tza.
@@ -74,6 +86,23 @@ jerry_port_local_tza (double unix_ms)
74
86
SYSTEMTIME utc_sys ;
75
87
SYSTEMTIME local_sys ;
76
88
89
+ /*
90
+ * If the time is earlier than the date 1601-01-02, then always using date 1601-01-02 to
91
+ * query time zone adjustment. This date (1601-01-02) will make sure both UTC and local
92
+ * time succeed with Win32 API. The date 1601-01-01 may lead to a win32 api failure, as
93
+ * after converting between local time and utc time, the time may be earlier than 1601-01-01
94
+ * in UTC time, that exceeds the FILETIME representation range.
95
+ */
96
+ if (unix_ms < (double ) UNIX_EPOCH_DATE_1601_01_02 )
97
+ {
98
+ unix_ms = (double ) UNIX_EPOCH_DATE_1601_01_02 ;
99
+ }
100
+
101
+ /* Like above, do not use the last supported day */
102
+ if (unix_ms > (double ) UNIX_EPOCH_DATE_30827_12_29 )
103
+ {
104
+ unix_ms = (double ) UNIX_EPOCH_DATE_30827_12_29 ;
105
+ }
77
106
unix_time_to_filetime (unix_ms , & utc );
78
107
79
108
if (FileTimeToSystemTime (& utc , & utc_sys ) && SystemTimeToTzSpecificLocalTime (NULL , & utc_sys , & local_sys )
0 commit comments