OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 // Dart core library. | 4 // Dart core library. |
5 | 5 |
6 // VM implementation of DateTime. | 6 // VM implementation of DateTime. |
7 patch class DateTime { | 7 patch class DateTime { |
8 // Natives. | 8 // Natives. |
9 // The natives have been moved up here to work around Issue 10401. | 9 // The natives have been moved up here to work around Issue 10401. |
10 static int _getCurrentMicros() native "DateTime_currentTimeMicros"; | 10 static int _getCurrentMicros() native "DateTime_currentTimeMicros"; |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 // the valid range we do a preliminary test that weeds out values that can | 277 // the valid range we do a preliminary test that weeds out values that can |
278 // not become valid even with timezone adjustments. | 278 // not become valid even with timezone adjustments. |
279 // The timezone adjustment is always less than a day, so adding a security | 279 // The timezone adjustment is always less than a day, so adding a security |
280 // margin of one day should be enough. | 280 // margin of one day should be enough. |
281 if (microsecondsSinceEpoch.abs() > | 281 if (microsecondsSinceEpoch.abs() > |
282 _MAX_MILLISECONDS_SINCE_EPOCH * 1000 + Duration.MICROSECONDS_PER_DAY) { | 282 _MAX_MILLISECONDS_SINCE_EPOCH * 1000 + Duration.MICROSECONDS_PER_DAY) { |
283 return null; | 283 return null; |
284 } | 284 } |
285 | 285 |
286 if (!isUtc) { | 286 if (!isUtc) { |
287 // Note that we need to remove the local timezone adjustement before | 287 // Note that we need to remove the local timezone adjustment before |
288 // asking for the correct zone offset. | 288 // asking for the correct zone offset. |
289 int adjustment = _localTimeZoneAdjustmentInSeconds() * | 289 int adjustment = _localTimeZoneAdjustmentInSeconds() * |
290 Duration.MICROSECONDS_PER_SECOND; | 290 Duration.MICROSECONDS_PER_SECOND; |
| 291 // The adjustment is independent of the actual date and of the daylight |
| 292 // saving time. It is positive east of the Prime Meridian and negative |
| 293 // west of it, e.g. -28800 sec for America/Los_Angeles timezone. |
291 | 294 |
292 int zoneOffset = | 295 int zoneOffset = |
293 _timeZoneOffsetInSeconds(microsecondsSinceEpoch - adjustment); | 296 _timeZoneOffsetInSeconds(microsecondsSinceEpoch - adjustment); |
| 297 // The zoneOffset depends on the actual date and reflects any daylight |
| 298 // saving time and/or historical deviation relative to UTC time. |
| 299 // It is positive east of the Prime Meridian and negative west of it, |
| 300 // e.g. -25200 sec for America/Los_Angeles timezone during DST. |
294 microsecondsSinceEpoch -= zoneOffset * Duration.MICROSECONDS_PER_SECOND; | 301 microsecondsSinceEpoch -= zoneOffset * Duration.MICROSECONDS_PER_SECOND; |
| 302 // The resulting microsecondsSinceEpoch value is therefore the calculated |
| 303 // UTC value decreased by a (positive if east of GMT) timezone adjustment |
| 304 // and decreased by typically one hour if DST is in effect. |
295 } | 305 } |
296 if (microsecondsSinceEpoch.abs() > | 306 if (microsecondsSinceEpoch.abs() > |
297 _MAX_MILLISECONDS_SINCE_EPOCH * Duration.MICROSECONDS_PER_MILLISECOND) { | 307 _MAX_MILLISECONDS_SINCE_EPOCH * Duration.MICROSECONDS_PER_MILLISECOND) { |
298 return null; | 308 return null; |
299 } | 309 } |
300 return microsecondsSinceEpoch; | 310 return microsecondsSinceEpoch; |
301 } | 311 } |
302 | 312 |
303 static int _weekDay(y) { | 313 static int _weekDay(y) { |
304 // 1/1/1970 was a Thursday. | 314 // 1/1/1970 was a Thursday. |
305 return (_dayFromYear(y) + 4) % 7; | 315 return (_dayFromYear(y) + 4) % 7; |
306 } | 316 } |
307 | 317 |
308 /** | 318 /** |
309 * Returns a year in the range 2008-2035 matching | 319 * Returns a year in the range 2008-2035 matching |
310 * * leap year, and | 320 * * leap year, and |
311 * * week day of first day. | 321 * * week day of first day. |
312 * | 322 * |
313 * Leap seconds are ignored. | 323 * Leap seconds are ignored. |
314 * Adapted from V8's date implementation. See ECMA 262 - 15.9.1.9. | 324 * Adapted from V8's date implementation. See ECMA 262 - 15.9.1.9. |
315 */ | 325 */ |
316 static int _equivalentYear(int year) { | 326 static int _equivalentYear(int year) { |
317 // Returns the week day (in range 0 - 6). | 327 // Returns year y so that _weekDay(y) == _weekDay(year). |
| 328 // _weekDay returns the week day (in range 0 - 6). |
318 // 1/1/1956 was a Sunday (i.e. weekday 0). 1956 was a leap-year. | 329 // 1/1/1956 was a Sunday (i.e. weekday 0). 1956 was a leap-year. |
319 // 1/1/1967 was a Sunday (i.e. weekday 0). | 330 // 1/1/1967 was a Sunday (i.e. weekday 0). |
320 // Without leap years a subsequent year has a week day + 1 (for example | 331 // Without leap years a subsequent year has a week day + 1 (for example |
321 // 1/1/1968 was a Monday). With leap-years it jumps over one week day | 332 // 1/1/1968 was a Monday). With leap-years it jumps over one week day |
322 // (e.g. 1/1/1957 was a Tuesday). | 333 // (e.g. 1/1/1957 was a Tuesday). |
323 // After 12 years the weekdays have advanced by 12 days + 3 leap days = | 334 // After 12 years the weekdays have advanced by 12 days + 3 leap days = |
324 // 15 days. 15 % 7 = 1. So after 12 years the week day has always | 335 // 15 days. 15 % 7 = 1. So after 12 years the week day has always |
325 // (now independently of leap-years) advanced by one. | 336 // (now independently of leap-years) advanced by one. |
326 // weekDay * 12 gives thus a year starting with the wanted weekDay. | 337 // weekDay * 12 gives thus a year starting with the wanted weekDay. |
327 int recentYear = (_isLeapYear(year) ? 1956 : 1967) + (_weekDay(year) * 12); | 338 int recentYear = (_isLeapYear(year) ? 1956 : 1967) + (_weekDay(year) * 12); |
(...skipping 17 matching lines...) Expand all Loading... |
345 int days = secondsSinceEpoch ~/ Duration.SECONDS_PER_DAY; | 356 int days = secondsSinceEpoch ~/ Duration.SECONDS_PER_DAY; |
346 if (days > 0 && days < DAYS_YEAR_2098) { | 357 if (days > 0 && days < DAYS_YEAR_2098) { |
347 // According to V8 this fast case works for dates from 1970 to 2099. | 358 // According to V8 this fast case works for dates from 1970 to 2099. |
348 return 1970 + (4 * days + 2) ~/ DAYS_IN_4_YEARS; | 359 return 1970 + (4 * days + 2) ~/ DAYS_IN_4_YEARS; |
349 } | 360 } |
350 int micros = secondsSinceEpoch * Duration.MICROSECONDS_PER_SECOND; | 361 int micros = secondsSinceEpoch * Duration.MICROSECONDS_PER_SECOND; |
351 return _computeUpperPart(micros)[_YEAR_INDEX]; | 362 return _computeUpperPart(micros)[_YEAR_INDEX]; |
352 } | 363 } |
353 | 364 |
354 /** | 365 /** |
355 * Returns a date in seconds that is equivalent to the current date. An | 366 * Returns a date in seconds that is equivalent to the given |
356 * equivalent date has the same fields (`month`, `day`, etc.) as the | 367 * date in microseconds [microsecondsSinceEpoch]. An equivalent |
357 * [this], but the `year` is in the range [1970..2037]. | 368 * date has the same fields (`month`, `day`, etc.) as the given |
| 369 * date, but the `year` is in the range [1901..2038]. |
358 * | 370 * |
359 * * The time since the beginning of the year is the same. | 371 * * The time since the beginning of the year is the same. |
360 * * If [this] is in a leap year then the returned seconds are in a leap | 372 * * If the given date is in a leap year then the returned |
361 * year, too. | 373 * seconds are in a leap year, too. |
362 * * The week day of [this] is the same as the one for the returned date. | 374 * * The week day of given date is the same as the one for the |
| 375 * returned date. |
363 */ | 376 */ |
364 static int _equivalentSeconds(int microsecondsSinceEpoch) { | 377 static int _equivalentSeconds(int microsecondsSinceEpoch) { |
365 const int CUT_OFF_SECONDS = 2100000000; | 378 const int CUT_OFF_SECONDS = 0x7FFFFFFF; |
366 | 379 |
367 int secondsSinceEpoch = _flooredDivision(microsecondsSinceEpoch, | 380 int secondsSinceEpoch = _flooredDivision(microsecondsSinceEpoch, |
368 Duration.MICROSECONDS_PER_SECOND); | 381 Duration.MICROSECONDS_PER_SECOND); |
369 | 382 |
370 if (secondsSinceEpoch < 0 || secondsSinceEpoch >= CUT_OFF_SECONDS) { | 383 if (secondsSinceEpoch.abs() > CUT_OFF_SECONDS) { |
371 int year = _yearsFromSecondsSinceEpoch(secondsSinceEpoch); | 384 int year = _yearsFromSecondsSinceEpoch(secondsSinceEpoch); |
372 int days = _dayFromYear(year); | 385 int days = _dayFromYear(year); |
373 int equivalentYear = _equivalentYear(year); | 386 int equivalentYear = _equivalentYear(year); |
374 int equivalentDays = _dayFromYear(equivalentYear); | 387 int equivalentDays = _dayFromYear(equivalentYear); |
375 int diffDays = equivalentDays - days; | 388 int diffDays = equivalentDays - days; |
376 secondsSinceEpoch += diffDays * Duration.SECONDS_PER_DAY; | 389 secondsSinceEpoch += diffDays * Duration.SECONDS_PER_DAY; |
377 } | 390 } |
378 return secondsSinceEpoch; | 391 return secondsSinceEpoch; |
379 } | 392 } |
380 | 393 |
381 static int _timeZoneOffsetInSeconds(int microsecondsSinceEpoch) { | 394 static int _timeZoneOffsetInSeconds(int microsecondsSinceEpoch) { |
382 int equivalentSeconds = _equivalentSeconds(microsecondsSinceEpoch); | 395 int equivalentSeconds = _equivalentSeconds(microsecondsSinceEpoch); |
383 return _timeZoneOffsetInSecondsForClampedSeconds(equivalentSeconds); | 396 return _timeZoneOffsetInSecondsForClampedSeconds(equivalentSeconds); |
384 } | 397 } |
385 | 398 |
386 static String _timeZoneName(int microsecondsSinceEpoch) { | 399 static String _timeZoneName(int microsecondsSinceEpoch) { |
387 int equivalentSeconds = _equivalentSeconds(microsecondsSinceEpoch); | 400 int equivalentSeconds = _equivalentSeconds(microsecondsSinceEpoch); |
388 return _timeZoneNameForClampedSeconds(equivalentSeconds); | 401 return _timeZoneNameForClampedSeconds(equivalentSeconds); |
389 } | 402 } |
390 } | 403 } |
OLD | NEW |