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

Unified Diff: dart/frog/leg/lib/mockimpl.dart

Issue 9424027: Implement Date. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years, 10 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
Index: dart/frog/leg/lib/mockimpl.dart
diff --git a/dart/frog/leg/lib/mockimpl.dart b/dart/frog/leg/lib/mockimpl.dart
index fe65b9bda9798ceaec7e80905aaaba75aa31d38e..a08d426735793550c01624878f0524455bd1acd2 100644
--- a/dart/frog/leg/lib/mockimpl.dart
+++ b/dart/frog/leg/lib/mockimpl.dart
@@ -81,6 +81,9 @@ class TimeZoneImplementation implements TimeZone {
}
class DateImplementation implements Date {
+ final int value;
+ final TimeZoneImplementation timeZone;
+
factory DateImplementation(int years,
int month,
int day,
@@ -102,152 +105,63 @@ class DateImplementation implements Date {
int seconds,
int milliseconds,
TimeZoneImplementation timeZone)
- : timeZone = timeZone,
- value = brokenDownDateToMillisecondsSinceEpoch_(
- years, month, day, hours, minutes, seconds, milliseconds,
- timeZone.isUtc);
+ : this.timeZone = checkNull(timeZone),
+ value = Primitives.valueFromDecomposedDate(years, month, day,
+ hours, minutes, seconds,
+ milliseconds,
+ timeZone.isUtc) {
+ _asJs();
+ }
DateImplementation.now()
- : timeZone = new TimeZone.local(),
- value = Primitives.getCurrentMs();
-
- factory DateImplementation.fromString(String formattedString) {
- int substringToNumber(String str, int from, int to) {
- int result = 0;
- for (int i = from; i < to; i++) {
- result = result * 10 + str.charCodeAt(i) - "0".charCodeAt(0);
- }
- return result;
- }
+ : timeZone = new TimeZone.local(),
+ value = Primitives.dateNow() {
+ _asJs();
+ }
- // TODO(floitsch): improve DateImplementation parsing.
- // Parse ISO 8601: "2011-05-14 00:37:18.231Z".
- int yearMonthSeparator = formattedString.indexOf("-", 0);
- if (yearMonthSeparator < 0) throw "UNIMPLEMENTED";
- int monthDaySeparator =
- formattedString.indexOf("-", yearMonthSeparator + 1);
- if (monthDaySeparator < 0) throw "UNIMPLEMENTED";
- int dateTimeSeparator = formattedString.indexOf(" ", monthDaySeparator + 1);
- if (dateTimeSeparator < 0) throw "UNIMPLEMENTED";
- int hoursMinutesSeparator =
- formattedString.indexOf(":", dateTimeSeparator + 1);
- if (hoursMinutesSeparator < 0) throw "UNIMPLEMENTED";
- int minutesSecondsSeparator =
- formattedString.indexOf(":", hoursMinutesSeparator + 1);
- if (minutesSecondsSeparator < 0) throw "UNIMPLEMENTED";
- int secondsMillisecondsSeparator =
- formattedString.indexOf(".", minutesSecondsSeparator + 1);
- bool isUtc = formattedString.endsWith("Z");
- int end = formattedString.length - (isUtc ? 1 : 0);
- if (secondsMillisecondsSeparator < 0) secondsMillisecondsSeparator = end;
-
- int year = substringToNumber(formattedString, 0, yearMonthSeparator);
- int month = substringToNumber(formattedString,
- yearMonthSeparator + 1,
- monthDaySeparator);
- int day = substringToNumber(formattedString,
- monthDaySeparator + 1,
- dateTimeSeparator);
- int hours = substringToNumber(formattedString,
- dateTimeSeparator + 1,
- hoursMinutesSeparator);
- int minutes = substringToNumber(formattedString,
- hoursMinutesSeparator + 1,
- minutesSecondsSeparator);
- int seconds = substringToNumber(formattedString,
- minutesSecondsSeparator + 1,
- secondsMillisecondsSeparator);
- int milliseconds = substringToNumber(formattedString,
- secondsMillisecondsSeparator + 1,
- end);
- TimeZone timeZone = (isUtc ? const TimeZone.utc() : new TimeZone.local());
- return new DateImplementation.withTimeZone(
- year, month, day, hours, minutes, seconds, milliseconds, timeZone);
+ DateImplementation.fromString(String formattedString)
+ : timeZone = new TimeZone.local(),
+ value = Primitives.valueFromDateString(formattedString) {
+ _asJs();
}
- const DateImplementation.fromEpoch(int this.value,
- TimeZone this.timeZone);
+ const DateImplementation.fromEpoch(this.value, this.timeZone);
- bool operator ==(Object other) {
+ bool operator ==(other) {
if (!(other is DateImplementation)) return false;
- return value == other.value && timeZone == other.timeZone;
+ return (value == other.value) && (timeZone == other.timeZone);
}
int compareTo(Date other) {
+ checkNull(other);
return value.compareTo(other.value);
}
Date changeTimeZone(TimeZone targetTimeZone) {
- if (targetTimeZone === null) {
+ if (targetTimeZone == null) {
targetTimeZone = new TimeZoneImplementation.local();
}
return new Date.fromEpoch(value, targetTimeZone);
}
- int get year() {
- int secondsSinceEpoch = secondsSinceEpoch_;
- // According to V8 some library calls have troubles with negative values.
- // Therefore clamp to 0 - year 2035 (which is less than the size of 32bit).
- if (secondsSinceEpoch >= 0 && secondsSinceEpoch < SECONDS_YEAR_2035_) {
- return Primitives.getYear(secondsSinceEpoch, timeZone.isUtc);
- }
-
- // Approximate the result. We don't take timeZone into account.
- int approximateYear = yearsFromSecondsSinceEpoch_(secondsSinceEpoch);
- int equivalentYear = equivalentYear_(approximateYear);
- int y = Primitives.getYear(equivalentSeconds_(secondsSinceEpoch_),
- timeZone.isUtc);
- return approximateYear + (y - equivalentYear);
- }
-
- int get month() => Primitives.getMonth(equivalentSeconds_(secondsSinceEpoch_),
- timeZone.isUtc);
+ int get year() => Primitives.getYear(this);
- int get day() => Primitives.getDay(equivalentSeconds_(secondsSinceEpoch_),
- timeZone.isUtc);
+ int get month() => Primitives.getMonth(this);
- int get hours() => Primitives.getHours(equivalentSeconds_(secondsSinceEpoch_),
- timeZone.isUtc);
+ int get day() => Primitives.getDay(this);
- int get minutes() =>
- Primitives.getMinutes(equivalentSeconds_(secondsSinceEpoch_),
- timeZone.isUtc);
+ int get hours() => Primitives.getHours(this);
- int get seconds() =>
- Primitives.getSeconds(equivalentSeconds_(secondsSinceEpoch_),
- timeZone.isUtc);
+ int get minutes() => Primitives.getMinutes(this);
- int get milliseconds() {
- return value % Duration.MILLISECONDS_PER_SECOND;
- }
+ int get seconds() => Primitives.getSeconds(this);
- int get secondsSinceEpoch_() {
- // Always round down.
- if (value < 0) {
- return (value + 1) ~/ Duration.MILLISECONDS_PER_SECOND - 1;
- } else {
- return value ~/ Duration.MILLISECONDS_PER_SECOND;
- }
- }
+ int get milliseconds() => Primitives.getMilliseconds(this);
int get weekday() {
- final Date unixTimeStart =
- new Date.withTimeZone(1970, 1, 1, 0, 0, 0, 0, timeZone);
- int msSince1970 = this.difference(unixTimeStart).inMilliseconds;
- // Adjust the milliseconds to avoid problems with summer-time.
- if (hours < 2) {
- msSince1970 += 2 * Duration.MILLISECONDS_PER_HOUR;
- }
- // Compute the floor of msSince1970 / Duration.MS_PER_DAY.
- int daysSince1970;
- if (msSince1970 >= 0) {
- daysSince1970 = msSince1970 ~/ Duration.MILLISECONDS_PER_DAY;
- } else {
- daysSince1970 = (msSince1970 - Duration.MILLISECONDS_PER_DAY + 1) ~/
- Duration.MILLISECONDS_PER_DAY;
- }
- // 1970-1-1 was a Thursday.
- return ((daysSince1970 + Date.THU) % Date.DAYS_IN_WEEK);
+ // Adjust by one because JS weeks start on Sunday.
ngeoffray 2012/02/21 12:08:07 I'd prefer moving this adjustment in Primitives. A
+ var day = Primitives.getWeekday(this);
+ return (day + 6) % 7;
}
bool isLocalTime() {
@@ -259,16 +173,6 @@ class DateImplementation implements Date {
}
String toString() {
- String threeDigits(int n) {
- if (n >= 100) return "${n}";
- if (n > 10) return "0${n}";
- return "00${n}";
- }
- String twoDigits(int n) {
- if (n >= 10) return "${n}";
- return "0${n}";
- }
-
String m = twoDigits(month);
String d = twoDigits(day);
String h = twoDigits(hours);
@@ -284,181 +188,95 @@ class DateImplementation implements Date {
// Adds the [duration] to this Date instance.
Date add(Duration duration) {
+ checkNull(duration);
return new DateImplementation.fromEpoch(value + duration.inMilliseconds,
timeZone);
}
// Subtracts the [duration] from this Date instance.
Date subtract(Duration duration) {
+ checkNull(duration);
return new DateImplementation.fromEpoch(value - duration.inMilliseconds,
timeZone);
}
// Returns a [Duration] with the difference of [this] and [other].
Duration difference(Date other) {
- return new DurationImplementation(milliseconds: value - other.value);
+ checkNull(other);
+ return new Duration(milliseconds: value - other.value);
}
- final int value;
- final TimeZoneImplementation timeZone;
+ // Lazily keep a JS Date stored in the dart object.
+ var _asJs() => Primitives.lazyAsJsDate(this);
+}
- static final int SECONDS_YEAR_2035_ = 2051222400;
-
- // 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) {
- final int DAYS_IN_4_YEARS = 4 * 365 + 1;
- final int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1;
- final int DAYS_IN_400_YEARS = 4 * DAYS_IN_100_YEARS + 1;
- final int DAYS_1970_TO_2000 = 30 * 365 + 7;
- final int DAYS_OFFSET = 1000 * DAYS_IN_400_YEARS + 5 * DAYS_IN_400_YEARS -
- DAYS_1970_TO_2000;
- final int YEARS_OFFSET = 400000;
- final 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;
- } else {
- days += DAYS_OFFSET;
- int result = 400 * (days ~/ DAYS_IN_400_YEARS) - YEARS_OFFSET;
- days = days.remainder(DAYS_IN_400_YEARS);
- days--;
- int yd1 = days ~/ DAYS_IN_100_YEARS;
- days = days.remainder(DAYS_IN_100_YEARS);
- result += 100 * yd1;
- days++;
- int yd2 = days ~/ DAYS_IN_4_YEARS;
- days = days.remainder(DAYS_IN_4_YEARS);
- result += 4 * yd2;
- days--;
- int yd3 = days ~/ 365;
- days = days.remainder(365);
- result += yd3;
- return result;
+class ListFactory<E> implements List<E> {
+ factory List([int length]) => Primitives.newList(length);
+ factory List.from(Iterable<E> other) {
+ List<E> result = new List<E>();
+ Iterator<E> iterator = other.iterator();
+ while (iterator.hasNext()) {
+ result.add(iterator.next());
}
+ return result;
}
+}
- // Given [secondsSinceEpoch] returns seconds such that they are at the same
- // time in an equivalent year (see [equivalentYear_]).
- // Leap seconds are ignored.
- static int equivalentSeconds_(int secondsSinceEpoch) {
- if (secondsSinceEpoch >= 0 && secondsSinceEpoch < SECONDS_YEAR_2035_) {
- return secondsSinceEpoch;
- }
- int year = yearsFromSecondsSinceEpoch_(secondsSinceEpoch);
- int days = dayFromYear_(year);
- int equivalentYear = equivalentYear_(year);
- int equivalentDays = dayFromYear_(equivalentYear);
- int diffDays = equivalentDays - days;
- return secondsSinceEpoch + diffDays * Duration.SECONDS_PER_DAY;
+class DurationImplementation implements Duration {
+ final int inMilliseconds;
+
+ const DurationImplementation([int days = 0,
+ int hours = 0,
+ int minutes = 0,
+ int seconds = 0,
+ int milliseconds = 0])
+ : inMilliseconds = days * Duration.MILLISECONDS_PER_DAY +
+ hours * Duration.MILLISECONDS_PER_HOUR +
+ minutes * Duration.MILLISECONDS_PER_MINUTE +
+ seconds * Duration.MILLISECONDS_PER_SECOND +
+ milliseconds;
+
+ int get inDays() {
+ return inMilliseconds ~/ Duration.MILLISECONDS_PER_DAY;
}
- // Returns the days since 1970 for the start of the given [year].
- // [year] may be before epoch.
- static int dayFromYear_(int year) {
- int flooredDivision(int a, int b) {
- return (a - (a < 0 ? b - 1 : 0)) ~/ b;
- }
+ int get inHours() {
+ return inMilliseconds ~/ Duration.MILLISECONDS_PER_HOUR;
+ }
- return 365 * (year - 1970)
- + flooredDivision(year - 1969, 4)
- - flooredDivision(year - 1901, 100)
- + flooredDivision(year - 1601, 400);
+ int get inMinutes() {
+ return inMilliseconds ~/ Duration.MILLISECONDS_PER_MINUTE;
}
- // 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 equivalentYear_(int year) {
- // Returns 1 if in leap year. 0 otherwise.
- bool inLeapYear(year) {
- return (year.remainder(4) == 0) &&
- ((year.remainder(100) != 0) || (year.remainder(400) == 0));
- }
+ int get inSeconds() {
+ return inMilliseconds ~/ Duration.MILLISECONDS_PER_SECOND;
+ }
- // Returns the week day (in range 0 - 6).
- int weekDay(year) {
- // 1/1/1970 was a Thursday.
- return (dayFromYear_(year) + 4) % 7;
- }
- // 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 = (inLeapYear(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;
+ bool operator ==(other) {
+ if (other is !Duration) return false;
+ return inMilliseconds == other.inMilliseconds;
}
- static brokenDownDateToMillisecondsSinceEpoch_(
- int years, int month, int day,
- int hours, int minutes, int seconds, int milliseconds,
- bool isUtc) {
- if ((month < 1) || (month > 12)) {
- throw new IllegalArgumentException();
- }
- if ((day < 1) || (day > 31)) {
- throw new IllegalArgumentException();
- }
- // Leap seconds can lead to hours == 24.
- if ((hours < 0) || (hours > 24)) {
- throw new IllegalArgumentException();
- }
- if ((hours == 24) && ((minutes != 0) || (seconds != 0))) {
- throw new IllegalArgumentException();
- }
- if ((minutes < 0) || (minutes > 59)) {
- throw new IllegalArgumentException();
- }
- if ((seconds < 0) || (seconds > 59)) {
- throw new IllegalArgumentException();
- }
- if ((milliseconds < 0) || (milliseconds > 999)) {
- throw new IllegalArgumentException();
- }
- int equivalentYear;
- int offsetInSeconds;
- // According to V8 some library calls have troubles with negative values.
- // Therefore clamp to 1970 - year 2035 (which is less than the size of
- // 32bit).
- // We exclude the year 1970 when the time is not UTC, since the epoch
- // value could then be negative.
- if (years < (isUtc ? 1970 : 1971) || years > 2035) {
- equivalentYear = equivalentYear_(years);
- int offsetInDays = (dayFromYear_(years) - dayFromYear_(equivalentYear));
- // Leap seconds are ignored.
- offsetInSeconds = offsetInDays * Duration.SECONDS_PER_DAY;
- } else {
- equivalentYear = years;
- offsetInSeconds = 0;
- }
- int secondsSinceEpoch = Primitives.brokenDownDateToSecondsSinceEpoch(
- equivalentYear, month, day, hours, minutes, seconds, isUtc);
- int adjustedSeconds = secondsSinceEpoch + offsetInSeconds;
- return adjustedSeconds * Duration.MILLISECONDS_PER_SECOND + milliseconds;
+ int hashCode() {
+ return inMilliseconds.hashCode();
}
-}
-class ListFactory<E> implements List<E> {
- factory List([int length]) => Primitives.newList(length);
- factory List.from(Iterable<E> other) {
- List<E> result = new List<E>();
- Iterator<E> iterator = other.iterator();
- while (iterator.hasNext()) {
- result.add(iterator.next());
+ int compareTo(Duration other) {
+ return inMilliseconds.compareTo(other.inMilliseconds);
+ }
+
+ String toString() {
+ if (inMilliseconds < 0) {
+ Duration duration =
+ new DurationImplementation(milliseconds: -inMilliseconds);
+ return "-${duration}";
}
- return result;
+ String twoDigitMinutes =
+ twoDigits(inMinutes.remainder(Duration.MINUTES_PER_HOUR));
+ String twoDigitSeconds =
+ twoDigits(inSeconds.remainder(Duration.SECONDS_PER_MINUTE));
+ String threeDigitMs =
+ threeDigits(inMilliseconds.remainder(Duration.MILLISECONDS_PER_SECOND));
+ return "${inHours}:${twoDigitMinutes}:${twoDigitSeconds}.${threeDigitMs}";
}
}

Powered by Google App Engine
This is Rietveld 408576698