OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_DATE_H_ | 5 #ifndef V8_DATE_H_ |
6 #define V8_DATE_H_ | 6 #define V8_DATE_H_ |
7 | 7 |
8 #include "src/allocation.h" | 8 #include "src/allocation.h" |
9 #include "src/base/platform/platform.h" | 9 #include "src/base/platform/platform.h" |
10 #include "src/globals.h" | 10 #include "src/globals.h" |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 } | 97 } |
98 | 98 |
99 // ECMA 262 - 15.9.5.26 | 99 // ECMA 262 - 15.9.5.26 |
100 int TimezoneOffset(int64_t time_ms) { | 100 int TimezoneOffset(int64_t time_ms) { |
101 int64_t local_ms = ToLocal(time_ms); | 101 int64_t local_ms = ToLocal(time_ms); |
102 return static_cast<int>((time_ms - local_ms) / kMsPerMin); | 102 return static_cast<int>((time_ms - local_ms) / kMsPerMin); |
103 } | 103 } |
104 | 104 |
105 // ECMA 262 - 15.9.1.9 | 105 // ECMA 262 - 15.9.1.9 |
106 // LocalTime(t) = t + LocalTZA + DaylightSavingTA(t) | 106 // LocalTime(t) = t + LocalTZA + DaylightSavingTA(t) |
107 // ECMA 262 assumes that DaylightSavingTA is computed using UTC time, | |
108 // but we fetch DST from OS using local time, therefore we need: | |
109 // LocalTime(t) = t + LocalTZA + DaylightSavingTA(t + LocalTZA). | |
110 int64_t ToLocal(int64_t time_ms) { | 107 int64_t ToLocal(int64_t time_ms) { |
111 time_ms += LocalOffsetInMs(); | 108 return time_ms + LocalOffsetInMs() + DaylightSavingsOffsetInMs(time_ms); |
112 return time_ms + DaylightSavingsOffsetInMs(time_ms); | |
113 } | 109 } |
114 | 110 |
115 // ECMA 262 - 15.9.1.9 | 111 // ECMA 262 - 15.9.1.9 |
116 // UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA) | 112 // UTC(t) = t - LocalTZA - DaylightSavingTA(t - LocalTZA) |
117 // ECMA 262 assumes that DaylightSavingTA is computed using UTC time, | |
118 // but we fetch DST from OS using local time, therefore we need: | |
119 // UTC(t) = t - LocalTZA - DaylightSavingTA(t). | |
120 int64_t ToUTC(int64_t time_ms) { | 113 int64_t ToUTC(int64_t time_ms) { |
121 return time_ms - LocalOffsetInMs() - DaylightSavingsOffsetInMs(time_ms); | 114 // We need to compute UTC time that corresponds to the given local time. |
| 115 // Literally following spec here leads to incorrect time computation at |
| 116 // the points were we transition to and from DST. |
| 117 // |
| 118 // The following shows that using DST for (t - LocalTZA - hour) produces |
| 119 // correct conversion. |
| 120 // |
| 121 // Consider transition to DST at local time L1. |
| 122 // Let L0 = L1 - hour, L2 = L1 + hour, |
| 123 // U1 = UTC time that corresponds to L1, |
| 124 // U0 = U1 - hour. |
| 125 // Transitioning to DST moves local clock one hour forward L1 => L2, so |
| 126 // U0 = UTC time that corresponds to L0 = L0 - LocalTZA, |
| 127 // U1 = UTC time that corresponds to L1 = L1 - LocalTZA, |
| 128 // U1 = UTC time that corresponds to L2 = L2 - LocalTZA - hour. |
| 129 // Note that DST(U0 - hour) = 0, DST(U0) = 0, DST(U1) = 1. |
| 130 // U0 = L0 - LocalTZA - DST(L0 - LocalTZA - hour), |
| 131 // U1 = L1 - LocalTZA - DST(L1 - LocalTZA - hour), |
| 132 // U1 = L2 - LocalTZA - DST(L2 - LocalTZA - hour). |
| 133 // |
| 134 // Consider transition from DST at local time L1. |
| 135 // Let L0 = L1 - hour, |
| 136 // U1 = UTC time that corresponds to L1, |
| 137 // U0 = U1 - hour, U2 = U1 + hour. |
| 138 // Transitioning from DST moves local clock one hour back L1 => L0, so |
| 139 // U0 = UTC time that corresponds to L0 (before transition) |
| 140 // = L0 - LocalTZA - hour. |
| 141 // U1 = UTC time that corresponds to L0 (after transition) |
| 142 // = L0 - LocalTZA = L1 - LocalTZA - hour |
| 143 // U2 = UTC time that corresponds to L1 = L1 - LocalTZA. |
| 144 // Note that DST(U0) = 1, DST(U1) = 0, DST(U2) = 0. |
| 145 // U0 = L0 - LocalTZA - DST(L0 - LocalTZA - hour) = L0 - LocalTZA - DST(U0). |
| 146 // U2 = L1 - LocalTZA - DST(L1 - LocalTZA - hour) = L1 - LocalTZA - DST(U1). |
| 147 // It is impossible to get U1 from local time. |
| 148 |
| 149 const int kMsPerHour = 3600 * 1000; |
| 150 time_ms -= LocalOffsetInMs(); |
| 151 return time_ms - DaylightSavingsOffsetInMs(time_ms - kMsPerHour); |
122 } | 152 } |
123 | 153 |
124 | 154 |
125 // Computes a time equivalent to the given time according | 155 // Computes a time equivalent to the given time according |
126 // to ECMA 262 - 15.9.1.9. | 156 // to ECMA 262 - 15.9.1.9. |
127 // The issue here is that some library calls don't work right for dates | 157 // The issue here is that some library calls don't work right for dates |
128 // that cannot be represented using a non-negative signed 32 bit integer | 158 // that cannot be represented using a non-negative signed 32 bit integer |
129 // (measured in whole seconds based on the 1970 epoch). | 159 // (measured in whole seconds based on the 1970 epoch). |
130 // We solve this by mapping the time to a year with same leap-year-ness | 160 // We solve this by mapping the time to a year with same leap-year-ness |
131 // and same starting day for the year. The ECMAscript specification says | 161 // and same starting day for the year. The ECMAscript specification says |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 int ymd_year_; | 272 int ymd_year_; |
243 int ymd_month_; | 273 int ymd_month_; |
244 int ymd_day_; | 274 int ymd_day_; |
245 | 275 |
246 base::TimezoneCache* tz_cache_; | 276 base::TimezoneCache* tz_cache_; |
247 }; | 277 }; |
248 | 278 |
249 } } // namespace v8::internal | 279 } } // namespace v8::internal |
250 | 280 |
251 #endif | 281 #endif |
OLD | NEW |