Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1540)

Unified Diff: runtime/lib/date_patch.dart

Issue 3006853002: Use more of the std libraries to do date manipulations. (Closed)
Patch Set: Remove "clamped" part. Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/lib/date_patch.dart
diff --git a/runtime/lib/date_patch.dart b/runtime/lib/date_patch.dart
index 6a09226ae620c2fa6fa86c9898e8a4eb8ae72241..48722e10f64af8c8d3f18f11b43c9b54c5ab3161 100644
--- a/runtime/lib/date_patch.dart
+++ b/runtime/lib/date_patch.dart
@@ -10,15 +10,21 @@ class DateTime {
// The natives have been moved up here to work around Issue 10401.
static int _getCurrentMicros() native "DateTime_currentTimeMicros";
- static String _timeZoneNameForClampedSeconds(int secondsSinceEpoch)
+ static String _timeZoneNameForSeconds(int secondsSinceEpoch)
native "DateTime_timeZoneName";
- static int _timeZoneOffsetInSecondsForClampedSeconds(int secondsSinceEpoch)
+ static int _timeZoneOffsetInSecondsForSeconds(int secondsSinceEpoch)
native "DateTime_timeZoneOffsetInSeconds";
static int _localTimeZoneAdjustmentInSeconds()
native "DateTime_localTimeZoneAdjustmentInSeconds";
+ // Returns `null` if an error occurred.
+ static int
+ _brokenDownToSeconds(int year, int month, int day, int hour, int minute,
+ int second, bool isUtc)
+ native "DateTime_brokenDownToSeconds"; // Would use mktime or _mkgmtime/timegm
+
static const _MICROSECOND_INDEX = 0;
static const _MILLISECOND_INDEX = 1;
static const _SECOND_INDEX = 2;
@@ -261,155 +267,23 @@ class DateTime {
@patch
static int _brokenDownDateToValue(int year, int month, int day, int hour,
int minute, int second, int millisecond, int microsecond, bool isUtc) {
- // Simplify calculations by working with zero-based month.
- --month;
- // Deal with under and overflow.
- if (month >= 12) {
- year += month ~/ 12;
- month = month % 12;
- } else if (month < 0) {
- int realMonth = month % 12;
- year += (month - realMonth) ~/ 12;
- month = realMonth;
- }
-
- // First compute the seconds in UTC, independent of the [isUtc] flag. If
- // necessary we will add the time-zone offset later on.
- int days = day - 1;
- days += _DAYS_UNTIL_MONTH[_isLeapYear(year) ? 1 : 0][month];
- days += _dayFromYear(year);
- int microsecondsSinceEpoch = days * Duration.MICROSECONDS_PER_DAY +
- hour * Duration.MICROSECONDS_PER_HOUR +
- minute * Duration.MICROSECONDS_PER_MINUTE +
- second * Duration.MICROSECONDS_PER_SECOND +
- millisecond * Duration.MICROSECONDS_PER_MILLISECOND +
- microsecond;
-
- // Since [_timeZoneOffsetInSeconds] will crash if the input is far out of
- // the valid range we do a preliminary test that weeds out values that can
- // not become valid even with timezone adjustments.
- // The timezone adjustment is always less than a day, so adding a security
- // margin of one day should be enough.
- if (microsecondsSinceEpoch.abs() >
- _MAX_MILLISECONDS_SINCE_EPOCH * 1000 + Duration.MICROSECONDS_PER_DAY) {
- return null;
- }
-
- if (!isUtc) {
- // Note that we need to remove the local timezone adjustment before
- // asking for the correct zone offset.
- int adjustment = _localTimeZoneAdjustmentInSeconds() *
- Duration.MICROSECONDS_PER_SECOND;
- // The adjustment is independent of the actual date and of the daylight
- // saving time. It is positive east of the Prime Meridian and negative
- // west of it, e.g. -28800 sec for America/Los_Angeles timezone.
-
- int zoneOffset =
- _timeZoneOffsetInSeconds(microsecondsSinceEpoch - adjustment);
- // The zoneOffset depends on the actual date and reflects any daylight
- // saving time and/or historical deviation relative to UTC time.
- // It is positive east of the Prime Meridian and negative west of it,
- // e.g. -25200 sec for America/Los_Angeles timezone during DST.
- microsecondsSinceEpoch -= zoneOffset * Duration.MICROSECONDS_PER_SECOND;
- // The resulting microsecondsSinceEpoch value is therefore the calculated
- // UTC value decreased by a (positive if east of GMT) timezone adjustment
- // and decreased by typically one hour if DST is in effect.
- }
- if (microsecondsSinceEpoch.abs() >
- _MAX_MILLISECONDS_SINCE_EPOCH * Duration.MICROSECONDS_PER_MILLISECOND) {
- return null;
- }
- return microsecondsSinceEpoch;
- }
-
- static int _weekDay(y) {
- // 1/1/1970 was a Thursday.
- return (_dayFromYear(y) + 4) % 7;
- }
-
- /**
- * Returns a year in the range 2008-2035 matching
- * * leap year, and
- * * week day of first day.
- *
- * Leap seconds are ignored.
- * Adapted from V8's date implementation. See ECMA 262 - 15.9.1.9.
- */
- static int _equivalentYear(int year) {
- // Returns year y so that _weekDay(y) == _weekDay(year).
- // _weekDay returns the week day (in range 0 - 6).
- // 1/1/1956 was a Sunday (i.e. weekday 0). 1956 was a leap-year.
- // 1/1/1967 was a Sunday (i.e. weekday 0).
- // Without leap years a subsequent year has a week day + 1 (for example
- // 1/1/1968 was a Monday). With leap-years it jumps over one week day
- // (e.g. 1/1/1957 was a Tuesday).
- // After 12 years the weekdays have advanced by 12 days + 3 leap days =
- // 15 days. 15 % 7 = 1. So after 12 years the week day has always
- // (now independently of leap-years) advanced by one.
- // weekDay * 12 gives thus a year starting with the wanted weekDay.
- int recentYear = (_isLeapYear(year) ? 1956 : 1967) + (_weekDay(year) * 12);
- // Close to the year 2008 the calendar cycles every 4 * 7 years (4 for the
- // leap years, 7 for the weekdays).
- // Find the year in the range 2008..2037 that is equivalent mod 28.
- return 2008 + (recentYear - 2008) % 28;
- }
-
- /**
- * Returns the UTC year for the corresponding [secondsSinceEpoch].
- * It is relatively fast for values in the range 0 to year 2098.
- *
- * Code is adapted from V8.
- */
- static int _yearsFromSecondsSinceEpoch(int secondsSinceEpoch) {
- const int DAYS_IN_4_YEARS = 4 * 365 + 1;
- const int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1;
- const int DAYS_YEAR_2098 = DAYS_IN_100_YEARS + 6 * DAYS_IN_4_YEARS;
-
- int days = secondsSinceEpoch ~/ Duration.SECONDS_PER_DAY;
- if (days > 0 && days < DAYS_YEAR_2098) {
- // According to V8 this fast case works for dates from 1970 to 2099.
- return 1970 + (4 * days + 2) ~/ DAYS_IN_4_YEARS;
- }
- int micros = secondsSinceEpoch * Duration.MICROSECONDS_PER_SECOND;
- return _computeUpperPart(micros)[_YEAR_INDEX];
- }
-
- /**
- * Returns a date in seconds that is equivalent to the given
- * date in microseconds [microsecondsSinceEpoch]. An equivalent
- * date has the same fields (`month`, `day`, etc.) as the given
- * date, but the `year` is in the range [1901..2038].
- *
- * * The time since the beginning of the year is the same.
- * * If the given date is in a leap year then the returned
- * seconds are in a leap year, too.
- * * The week day of given date is the same as the one for the
- * returned date.
- */
- static int _equivalentSeconds(int microsecondsSinceEpoch) {
- const int CUT_OFF_SECONDS = 0x7FFFFFFF;
-
- int secondsSinceEpoch = _flooredDivision(
- microsecondsSinceEpoch, Duration.MICROSECONDS_PER_SECOND);
-
- if (secondsSinceEpoch.abs() > CUT_OFF_SECONDS) {
- int year = _yearsFromSecondsSinceEpoch(secondsSinceEpoch);
- int days = _dayFromYear(year);
- int equivalentYear = _equivalentYear(year);
- int equivalentDays = _dayFromYear(equivalentYear);
- int diffDays = equivalentDays - days;
- secondsSinceEpoch += diffDays * Duration.SECONDS_PER_DAY;
- }
- return secondsSinceEpoch;
+ var seconds =
+ _brokenDownToSeconds(year, month - 1, day, hour, minute, second, isUtc);
+ if (seconds == null) return null;
+ return seconds * Duration.MICROSECONDS_PER_SECOND +
+ milliseconds * Duration.MICROSECONDS_PER_MILLISECONDS +
+ microseconds;
}
static int _timeZoneOffsetInSeconds(int microsecondsSinceEpoch) {
- int equivalentSeconds = _equivalentSeconds(microsecondsSinceEpoch);
- return _timeZoneOffsetInSecondsForClampedSeconds(equivalentSeconds);
+ int seconds = _flooredDivision(
+ microsecondsSinceEpoch, Duration.MICROSECONDS_PER_SECOND);
+ return _timeZoneOffsetInSecondsForSeconds(seconds);
}
static String _timeZoneName(int microsecondsSinceEpoch) {
- int equivalentSeconds = _equivalentSeconds(microsecondsSinceEpoch);
- return _timeZoneNameForClampedSeconds(equivalentSeconds);
+ int seconds = _flooredDivision(
+ microsecondsSinceEpoch, Duration.MICROSECONDS_PER_SECOND);
+ return _timeZoneNameForSeconds(seconds);
}
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698