OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) | 2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) |
3 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. | 3 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. |
4 * Copyright (C) 2009 Google Inc. All rights reserved. | 4 * Copyright (C) 2009 Google Inc. All rights reserved. |
5 * Copyright (C) 2007-2009 Torch Mobile, Inc. | 5 * Copyright (C) 2007-2009 Torch Mobile, Inc. |
6 * Copyright (C) 2010 &yet, LLC. (nate@andyet.net) | 6 * Copyright (C) 2010 &yet, LLC. (nate@andyet.net) |
7 * | 7 * |
8 * The Original Code is Mozilla Communicator client code, released | 8 * The Original Code is Mozilla Communicator client code, released |
9 * March 31, 1998. | 9 * March 31, 1998. |
10 * | 10 * |
11 * The Initial Developer of the Original Code is | 11 * The Initial Developer of the Original Code is |
12 * Netscape Communications Corporation. | 12 * Netscape Communications Corporation. |
13 * Portions created by the Initial Developer are Copyright (C) 1998 | 13 * Portions created by the Initial Developer are Copyright (C) 1998 |
14 * the Initial Developer. All Rights Reserved. | 14 * the Initial Developer. All Rights Reserved. |
15 * | 15 * |
16 * This library is free software; you can redistribute it and/or | 16 * This library is free software; you can redistribute it and/or |
17 * modify it under the terms of the GNU Lesser General Public | 17 * modify it under the terms of the GNU Lesser General Public |
18 * License as published by the Free Software Foundation; either | 18 * License as published by the Free Software Foundation; either |
19 * version 2.1 of the License, or (at your option) any later version. | 19 * version 2.1 of the License, or (at your option) any later version. |
20 * | 20 * |
21 * This library is distributed in the hope that it will be useful, | 21 * This library is distributed in the hope that it will be useful, |
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
24 * Lesser General Public License for more details. | 24 * Lesser General Public License for more details. |
25 * | 25 * |
26 * You should have received a copy of the GNU Lesser General Public | 26 * You should have received a copy of the GNU Lesser General Public |
27 * License along with this library; if not, write to the Free Software | 27 * License along with this library; if not, write to the Free Software |
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 US
A | 28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
29 * | 29 * |
30 * Alternatively, the contents of this file may be used under the terms | 30 * Alternatively, the contents of this file may be used under the terms |
31 * of either the Mozilla Public License Version 1.1, found at | 31 * of either the Mozilla Public License Version 1.1, found at |
32 * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public | 32 * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public |
33 * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html | 33 * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html |
34 * (the "GPL"), in which case the provisions of the MPL or the GPL are | 34 * (the "GPL"), in which case the provisions of the MPL or the GPL are |
35 * applicable instead of those above. If you wish to allow use of your | 35 * applicable instead of those above. If you wish to allow use of your |
36 * version of this file only under the terms of one of those two | 36 * version of this file only under the terms of one of those two |
37 * licenses (the MPL or the GPL) and not to allow others to use your | 37 * licenses (the MPL or the GPL) and not to allow others to use your |
38 * version of this file under the LGPL, indicate your decision by | 38 * version of this file under the LGPL, indicate your decision by |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 | 95 |
96 /* Constants */ | 96 /* Constants */ |
97 | 97 |
98 static const double hoursPerDay = 24.0; | 98 static const double hoursPerDay = 24.0; |
99 static const double secondsPerDay = 24.0 * 60.0 * 60.0; | 99 static const double secondsPerDay = 24.0 * 60.0 * 60.0; |
100 | 100 |
101 static const double maxUnixTime = 2145859200.0; // 12/31/2037 | 101 static const double maxUnixTime = 2145859200.0; // 12/31/2037 |
102 static const double kMinimumECMADateInMs = -8640000000000000.0; | 102 static const double kMinimumECMADateInMs = -8640000000000000.0; |
103 static const double kMaximumECMADateInMs = 8640000000000000.0; | 103 static const double kMaximumECMADateInMs = 8640000000000000.0; |
104 | 104 |
105 // Day of year for the first day of each month, where index 0 is January, and da
y 0 is January 1. | 105 // Day of year for the first day of each month, where index 0 is January, and |
106 // First for non-leap years, then for leap years. | 106 // day 0 is January 1. First for non-leap years, then for leap years. |
107 static const int firstDayOfMonth[2][12] = { | 107 static const int firstDayOfMonth[2][12] = { |
108 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}, | 108 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}, |
109 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}}; | 109 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}}; |
110 | 110 |
111 static inline void getLocalTime(const time_t* localTime, struct tm* localTM) { | 111 static inline void getLocalTime(const time_t* localTime, struct tm* localTM) { |
112 #if COMPILER(MSVC) | 112 #if COMPILER(MSVC) |
113 localtime_s(localTM, localTime); | 113 localtime_s(localTM, localTime); |
114 #else | 114 #else |
115 localtime_r(localTime, localTM); | 115 localtime_r(localTime, localTM); |
116 #endif | 116 #endif |
117 } | 117 } |
118 | 118 |
119 bool isLeapYear(int year) { | 119 bool isLeapYear(int year) { |
120 if (year % 4 != 0) | 120 if (year % 4 != 0) |
121 return false; | 121 return false; |
122 if (year % 400 == 0) | 122 if (year % 400 == 0) |
123 return true; | 123 return true; |
124 if (year % 100 == 0) | 124 if (year % 100 == 0) |
125 return false; | 125 return false; |
126 return true; | 126 return true; |
127 } | 127 } |
128 | 128 |
129 static inline int daysInYear(int year) { | 129 static inline int daysInYear(int year) { |
130 return 365 + isLeapYear(year); | 130 return 365 + isLeapYear(year); |
131 } | 131 } |
132 | 132 |
133 static inline double daysFrom1970ToYear(int year) { | 133 static inline double daysFrom1970ToYear(int year) { |
134 // The Gregorian Calendar rules for leap years: | 134 // The Gregorian Calendar rules for leap years: |
135 // Every fourth year is a leap year. 2004, 2008, and 2012 are leap years. | 135 // Every fourth year is a leap year. 2004, 2008, and 2012 are leap years. |
136 // However, every hundredth year is not a leap year. 1900 and 2100 are not le
ap years. | 136 // However, every hundredth year is not a leap year. 1900 and 2100 are not |
137 // Every four hundred years, there's a leap year after all. 2000 and 2400 are
leap years. | 137 // leap years. |
| 138 // Every four hundred years, there's a leap year after all. 2000 and 2400 are |
| 139 // leap years. |
138 | 140 |
139 static const int leapDaysBefore1971By4Rule = 1970 / 4; | 141 static const int leapDaysBefore1971By4Rule = 1970 / 4; |
140 static const int excludedLeapDaysBefore1971By100Rule = 1970 / 100; | 142 static const int excludedLeapDaysBefore1971By100Rule = 1970 / 100; |
141 static const int leapDaysBefore1971By400Rule = 1970 / 400; | 143 static const int leapDaysBefore1971By400Rule = 1970 / 400; |
142 | 144 |
143 const double yearMinusOne = year - 1; | 145 const double yearMinusOne = year - 1; |
144 const double yearsToAddBy4Rule = | 146 const double yearsToAddBy4Rule = |
145 floor(yearMinusOne / 4.0) - leapDaysBefore1971By4Rule; | 147 floor(yearMinusOne / 4.0) - leapDaysBefore1971By4Rule; |
146 const double yearsToExcludeBy100Rule = | 148 const double yearsToExcludeBy100Rule = |
147 floor(yearMinusOne / 100.0) - excludedLeapDaysBefore1971By100Rule; | 149 floor(yearMinusOne / 100.0) - excludedLeapDaysBefore1971By100Rule; |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 } | 290 } |
289 | 291 |
290 static inline int minimumYearForDST() { | 292 static inline int minimumYearForDST() { |
291 // Because of the 2038 issue (see maximumYearForDST) if the current year is | 293 // Because of the 2038 issue (see maximumYearForDST) if the current year is |
292 // greater than the max year minus 27 (2010), we want to use the max year | 294 // greater than the max year minus 27 (2010), we want to use the max year |
293 // minus 27 instead, to ensure there is a range of 28 years that all years | 295 // minus 27 instead, to ensure there is a range of 28 years that all years |
294 // can map to. | 296 // can map to. |
295 return std::min(msToYear(jsCurrentTime()), maximumYearForDST() - 27); | 297 return std::min(msToYear(jsCurrentTime()), maximumYearForDST() - 27); |
296 } | 298 } |
297 | 299 |
298 /* | 300 // Find an equivalent year for the one given, where equivalence is deterined by |
299 * Find an equivalent year for the one given, where equivalence is deterined by | 301 // the two years having the same leapness and the first day of the year, falling |
300 * the two years having the same leapness and the first day of the year, falling | 302 // on the same day of the week. |
301 * on the same day of the week. | 303 // |
302 * | 304 // This function returns a year between this current year and 2037, however this |
303 * This function returns a year between this current year and 2037, however this | 305 // function will potentially return incorrect results if the current year is |
304 * function will potentially return incorrect results if the current year is aft
er | 306 // after 2010, (rdar://problem/5052975), if the year passed in is before 1900 |
305 * 2010, (rdar://problem/5052975), if the year passed in is before 1900 or after | 307 // or after 2100, (rdar://problem/5055038). |
306 * 2100, (rdar://problem/5055038). | |
307 */ | |
308 static int equivalentYearForDST(int year) { | 308 static int equivalentYearForDST(int year) { |
309 // It is ok if the cached year is not the current year as long as the rules | 309 // It is ok if the cached year is not the current year as long as the rules |
310 // for DST did not change between the two years; if they did the app would nee
d | 310 // for DST did not change between the two years; if they did the app would |
311 // to be restarted. | 311 // need to be restarted. |
312 static int minYear = minimumYearForDST(); | 312 static int minYear = minimumYearForDST(); |
313 int maxYear = maximumYearForDST(); | 313 int maxYear = maximumYearForDST(); |
314 | 314 |
315 int difference; | 315 int difference; |
316 if (year > maxYear) | 316 if (year > maxYear) |
317 difference = minYear - year; | 317 difference = minYear - year; |
318 else if (year < minYear) | 318 else if (year < minYear) |
319 difference = maxYear - year; | 319 difference = maxYear - year; |
320 else | 320 else |
321 return year; | 321 return year; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 time_t localTime = static_cast<time_t>(localTimeSeconds); | 362 time_t localTime = static_cast<time_t>(localTimeSeconds); |
363 | 363 |
364 tm localTM; | 364 tm localTM; |
365 getLocalTime(&localTime, &localTM); | 365 getLocalTime(&localTime, &localTM); |
366 | 366 |
367 return localTM.tm_isdst > 0 ? msPerHour : 0; | 367 return localTM.tm_isdst > 0 ? msPerHour : 0; |
368 } | 368 } |
369 | 369 |
370 // Get the DST offset, given a time in UTC | 370 // Get the DST offset, given a time in UTC |
371 static double calculateDSTOffset(double ms, double utcOffset) { | 371 static double calculateDSTOffset(double ms, double utcOffset) { |
372 // On Mac OS X, the call to localtime (see calculateDSTOffsetSimple) will retu
rn historically accurate | 372 // On macOS, the call to localtime (see calculateDSTOffsetSimple) will return |
373 // DST information (e.g. New Zealand did not have DST from 1946 to 1974) howev
er the JavaScript | 373 // historically accurate DST information (e.g. New Zealand did not have DST |
374 // standard explicitly dictates that historical information should not be cons
idered when | 374 // from 1946 to 1974) however the JavaScript standard explicitly dictates |
375 // determining DST. For this reason we shift away from years that localtime ca
n handle but would | 375 // that historical information should not be considered when determining DST. |
376 // return historically accurate information. | 376 // For this reason we shift away from years that localtime can handle but |
| 377 // would return historically accurate information. |
377 int year = msToYear(ms); | 378 int year = msToYear(ms); |
378 int equivalentYear = equivalentYearForDST(year); | 379 int equivalentYear = equivalentYearForDST(year); |
379 if (year != equivalentYear) { | 380 if (year != equivalentYear) { |
380 bool leapYear = isLeapYear(year); | 381 bool leapYear = isLeapYear(year); |
381 int dayInYearLocal = dayInYear(ms, year); | 382 int dayInYearLocal = dayInYear(ms, year); |
382 int dayInMonth = dayInMonthFromDayInYear(dayInYearLocal, leapYear); | 383 int dayInMonth = dayInMonthFromDayInYear(dayInYearLocal, leapYear); |
383 int month = monthFromDayInYear(dayInYearLocal, leapYear); | 384 int month = monthFromDayInYear(dayInYearLocal, leapYear); |
384 double day = dateToDaysFrom1970(equivalentYear, month, dayInMonth); | 385 double day = dateToDaysFrom1970(equivalentYear, month, dayInMonth); |
385 ms = (day * msPerDay) + msToMilliseconds(ms); | 386 ms = (day * msPerDay) + msToMilliseconds(ms); |
386 } | 387 } |
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
831 return stringBuilder.toString(); | 832 return stringBuilder.toString(); |
832 } | 833 } |
833 | 834 |
834 double convertToLocalTime(double ms) { | 835 double convertToLocalTime(double ms) { |
835 double utcOffset = calculateUTCOffset(); | 836 double utcOffset = calculateUTCOffset(); |
836 double dstOffset = calculateDSTOffset(ms, utcOffset); | 837 double dstOffset = calculateDSTOffset(ms, utcOffset); |
837 return (ms + utcOffset + dstOffset); | 838 return (ms + utcOffset + dstOffset); |
838 } | 839 } |
839 | 840 |
840 } // namespace WTF | 841 } // namespace WTF |
OLD | NEW |