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 * |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 #endif | 96 #endif |
97 | 97 |
98 using namespace WTF; | 98 using namespace WTF; |
99 | 99 |
100 namespace WTF { | 100 namespace WTF { |
101 | 101 |
102 /* Constants */ | 102 /* Constants */ |
103 | 103 |
104 static const double hoursPerDay = 24.0; | 104 static const double hoursPerDay = 24.0; |
105 static const double secondsPerDay = 24.0 * 60.0 * 60.0; | 105 static const double secondsPerDay = 24.0 * 60.0 * 60.0; |
106 static const double secondsPerHour = 60.0 * 60.0; | |
107 | 106 |
108 static const double maxUnixTime = 2145859200.0; // 12/31/2037 | 107 static const double maxUnixTime = 2145859200.0; // 12/31/2037 |
109 | 108 |
110 // Day of year for the first day of each month, where index 0 is January, and da
y 0 is January 1. | 109 // Day of year for the first day of each month, where index 0 is January, and da
y 0 is January 1. |
111 // First for non-leap years, then for leap years. | 110 // First for non-leap years, then for leap years. |
112 static const int firstDayOfMonth[2][12] = { | 111 static const int firstDayOfMonth[2][12] = { |
113 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}, | 112 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}, |
114 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335} | 113 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335} |
115 }; | 114 }; |
116 | 115 |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 } | 187 } |
189 | 188 |
190 static inline double msToMilliseconds(double ms) | 189 static inline double msToMilliseconds(double ms) |
191 { | 190 { |
192 double result = fmod(ms, msPerDay); | 191 double result = fmod(ms, msPerDay); |
193 if (result < 0) | 192 if (result < 0) |
194 result += msPerDay; | 193 result += msPerDay; |
195 return result; | 194 return result; |
196 } | 195 } |
197 | 196 |
198 static int msToMinutes(double ms) | |
199 { | |
200 double result = fmod(floor(ms / msPerMinute), minutesPerHour); | |
201 if (result < 0) | |
202 result += minutesPerHour; | |
203 return static_cast<int>(result); | |
204 } | |
205 | |
206 static int msToHours(double ms) | |
207 { | |
208 double result = fmod(floor(ms/msPerHour), hoursPerDay); | |
209 if (result < 0) | |
210 result += hoursPerDay; | |
211 return static_cast<int>(result); | |
212 } | |
213 | |
214 int monthFromDayInYear(int dayInYear, bool leapYear) | 197 int monthFromDayInYear(int dayInYear, bool leapYear) |
215 { | 198 { |
216 const int d = dayInYear; | 199 const int d = dayInYear; |
217 int step; | 200 int step; |
218 | 201 |
219 if (d < (step = 31)) | 202 if (d < (step = 31)) |
220 return 0; | 203 return 0; |
221 step += (leapYear ? 29 : 28); | 204 step += (leapYear ? 29 : 28); |
222 if (d < step) | 205 if (d < step) |
223 return 1; | 206 return 1; |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 return year; | 334 return year; |
352 | 335 |
353 int quotient = difference / 28; | 336 int quotient = difference / 28; |
354 int product = (quotient) * 28; | 337 int product = (quotient) * 28; |
355 | 338 |
356 year += product; | 339 year += product; |
357 ASSERT((year >= minYear && year <= maxYear) || (product - year == static_cas
t<int>(std::numeric_limits<double>::quiet_NaN()))); | 340 ASSERT((year >= minYear && year <= maxYear) || (product - year == static_cas
t<int>(std::numeric_limits<double>::quiet_NaN()))); |
358 return year; | 341 return year; |
359 } | 342 } |
360 | 343 |
361 int32_t calculateUTCOffset() | 344 static double calculateUTCOffset() |
362 { | 345 { |
363 #if OS(WIN) | 346 #if OS(WIN) |
364 TIME_ZONE_INFORMATION timeZoneInformation; | 347 TIME_ZONE_INFORMATION timeZoneInformation; |
365 GetTimeZoneInformation(&timeZoneInformation); | 348 GetTimeZoneInformation(&timeZoneInformation); |
366 int32_t bias = timeZoneInformation.Bias + timeZoneInformation.StandardBias; | 349 int32_t bias = timeZoneInformation.Bias + timeZoneInformation.StandardBias; |
367 return -bias * 60 * 1000; | 350 return -bias * 60 * 1000; |
368 #else | 351 #else |
369 time_t localTime = time(0); | 352 time_t localTime = time(0); |
370 tm localt; | 353 tm localt; |
371 getLocalTime(&localTime, &localt); | 354 getLocalTime(&localTime, &localt); |
372 | 355 |
373 // Get the difference between this time zone and UTC on the 1st of January o
f this year. | 356 // tm_gmtoff includes any daylight savings offset, so subtract it. |
374 localt.tm_sec = 0; | 357 return static_cast<double>(localt.tm_gmtoff * msPerSecond - (localt.tm_isdst
> 0 ? msPerHour : 0)); |
375 localt.tm_min = 0; | |
376 localt.tm_hour = 0; | |
377 localt.tm_mday = 1; | |
378 localt.tm_mon = 0; | |
379 // Not setting localt.tm_year! | |
380 localt.tm_wday = 0; | |
381 localt.tm_yday = 0; | |
382 localt.tm_isdst = 0; | |
383 #if HAVE(TM_GMTOFF) | |
384 localt.tm_gmtoff = 0; | |
385 #endif | |
386 #if HAVE(TM_ZONE) | |
387 localt.tm_zone = 0; | |
388 #endif | |
389 | |
390 #if HAVE(TIMEGM) | |
391 time_t utcOffset = timegm(&localt) - mktime(&localt); | |
392 #else | |
393 // Using a canned date of 01/01/2009 on platforms with weaker date-handling
foo. | |
394 localt.tm_year = 109; | |
395 time_t utcOffset = 1230768000 - mktime(&localt); | |
396 #endif | |
397 | |
398 return static_cast<int32_t>(utcOffset * 1000); | |
399 #endif | 358 #endif |
400 } | 359 } |
401 | 360 |
402 /* | 361 /* |
403 * Get the DST offset for the time passed in. | 362 * Get the DST offset for the time passed in. |
404 */ | 363 */ |
405 static double calculateDSTOffsetSimple(double localTimeSeconds, double utcOffset
) | 364 static double calculateDSTOffsetSimple(double localTimeSeconds, double utcOffset
) |
406 { | 365 { |
407 if (localTimeSeconds > maxUnixTime) | 366 if (localTimeSeconds > maxUnixTime) |
408 localTimeSeconds = maxUnixTime; | 367 localTimeSeconds = maxUnixTime; |
409 else if (localTimeSeconds < 0) // Go ahead a day to make localtime work (doe
s not work with 0) | 368 else if (localTimeSeconds < 0) // Go ahead a day to make localtime work (doe
s not work with 0) |
410 localTimeSeconds += secondsPerDay; | 369 localTimeSeconds += secondsPerDay; |
411 | 370 |
412 //input is UTC so we have to shift back to local time to determine DST thus
the + getUTCOffset() | |
413 double offsetTime = (localTimeSeconds * msPerSecond) + utcOffset; | |
414 | |
415 // Offset from UTC but doesn't include DST obviously | |
416 int offsetHour = msToHours(offsetTime); | |
417 int offsetMinute = msToMinutes(offsetTime); | |
418 | |
419 // FIXME: time_t has a potential problem in 2038 | 371 // FIXME: time_t has a potential problem in 2038 |
420 time_t localTime = static_cast<time_t>(localTimeSeconds); | 372 time_t localTime = static_cast<time_t>(localTimeSeconds); |
421 | 373 |
422 tm localTM; | 374 tm localTM; |
423 getLocalTime(&localTime, &localTM); | 375 getLocalTime(&localTime, &localTM); |
424 | 376 |
425 double diff = ((localTM.tm_hour - offsetHour) * secondsPerHour) + ((localTM.
tm_min - offsetMinute) * 60); | 377 return localTM.tm_isdst > 0 ? msPerHour : 0; |
426 | |
427 if (diff < 0) | |
428 diff += secondsPerDay; | |
429 | |
430 return (diff * msPerSecond); | |
431 } | 378 } |
432 | 379 |
433 // Get the DST offset, given a time in UTC | 380 // Get the DST offset, given a time in UTC |
434 double calculateDSTOffset(double ms, double utcOffset) | 381 static double calculateDSTOffset(double ms, double utcOffset) |
435 { | 382 { |
436 // On Mac OS X, the call to localtime (see calculateDSTOffsetSimple) will re
turn historically accurate | 383 // On Mac OS X, the call to localtime (see calculateDSTOffsetSimple) will re
turn historically accurate |
437 // DST information (e.g. New Zealand did not have DST from 1946 to 1974) how
ever the JavaScript | 384 // DST information (e.g. New Zealand did not have DST from 1946 to 1974) how
ever the JavaScript |
438 // standard explicitly dictates that historical information should not be co
nsidered when | 385 // standard explicitly dictates that historical information should not be co
nsidered when |
439 // determining DST. For this reason we shift away from years that localtime
can handle but would | 386 // determining DST. For this reason we shift away from years that localtime
can handle but would |
440 // return historically accurate information. | 387 // return historically accurate information. |
441 int year = msToYear(ms); | 388 int year = msToYear(ms); |
442 int equivalentYear = equivalentYearForDST(year); | 389 int equivalentYear = equivalentYearForDST(year); |
443 if (year != equivalentYear) { | 390 if (year != equivalentYear) { |
444 bool leapYear = isLeapYear(year); | 391 bool leapYear = isLeapYear(year); |
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
874 stringBuilder.append(' '); | 821 stringBuilder.append(' '); |
875 | 822 |
876 stringBuilder.append(utcOffset > 0 ? '+' : '-'); | 823 stringBuilder.append(utcOffset > 0 ? '+' : '-'); |
877 int absoluteUTCOffset = abs(utcOffset); | 824 int absoluteUTCOffset = abs(utcOffset); |
878 stringBuilder.append(twoDigitStringFromNumber(absoluteUTCOffset / 60)); | 825 stringBuilder.append(twoDigitStringFromNumber(absoluteUTCOffset / 60)); |
879 stringBuilder.append(twoDigitStringFromNumber(absoluteUTCOffset % 60)); | 826 stringBuilder.append(twoDigitStringFromNumber(absoluteUTCOffset % 60)); |
880 | 827 |
881 return stringBuilder.toString(); | 828 return stringBuilder.toString(); |
882 } | 829 } |
883 | 830 |
| 831 double convertToLocalTime(double ms) |
| 832 { |
| 833 double utcOffset = calculateUTCOffset(); |
| 834 double dstOffset = calculateDSTOffset(ms, utcOffset); |
| 835 return (ms + utcOffset + dstOffset); |
| 836 } |
| 837 |
884 } // namespace WTF | 838 } // namespace WTF |
OLD | NEW |