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