| 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 |