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

Side by Side Diff: runtime/lib/date.dart

Issue 10832166: Updated VM and JS versions of Date to allow underflow and overflow. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: clean up unnecessary hoop-jumping Created 8 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 DateImplementation. 6 // VM implementation of DateImplementation.
7 class DateImplementation implements Date { 7 class DateImplementation implements Date {
8 static final int _MAX_MILLISECONDS_SINCE_EPOCH = 8640000000000000; 8 static final int _MAX_MILLISECONDS_SINCE_EPOCH = 8640000000000000;
9 9
10 DateImplementation(int years, 10 DateImplementation(int year,
11 [int month = 1, 11 [int month = 1,
12 int day = 1, 12 int day = 1,
13 int hour = 0, 13 int hour = 0,
14 int minute = 0, 14 int minute = 0,
15 int second = 0, 15 int second = 0,
16 int millisecond = 0, 16 int millisecond = 0,
17 bool isUtc = false]) 17 bool isUtc = false])
18 : this.isUtc = isUtc, 18 : this.isUtc = isUtc,
19 this.millisecondsSinceEpoch = _brokenDownDateToMillisecondsSinceEpoch( 19 this.millisecondsSinceEpoch = _brokenDownDateToMillisecondsSinceEpoch(
20 years, month, day, hour, minute, second, millisecond, isUtc) { 20 year, month, day, hour, minute, second, millisecond, isUtc) {
21 if (millisecondsSinceEpoch === null) throw new IllegalArgumentException(); 21 if (millisecondsSinceEpoch === null) throw new IllegalArgumentException();
22 if (isUtc === null) throw new IllegalArgumentException(); 22 if (isUtc === null) throw new IllegalArgumentException();
23 } 23 }
24 24
25 DateImplementation.now() 25 DateImplementation.now()
26 : isUtc = false, 26 : isUtc = false,
27 millisecondsSinceEpoch = _getCurrentMs() { 27 millisecondsSinceEpoch = _getCurrentMs() {
28 } 28 }
29 29
30 factory DateImplementation.fromString(String formattedString) { 30 factory DateImplementation.fromString(String formattedString) {
(...skipping 16 matching lines...) Expand all
47 if (matched === null || matched == "") return 0; 47 if (matched === null || matched == "") return 0;
48 return Math.parseInt(matched); 48 return Math.parseInt(matched);
49 } 49 }
50 50
51 double parseDoubleOrZero(String matched) { 51 double parseDoubleOrZero(String matched) {
52 // TODO(floitsch): we should not need to test against the empty string. 52 // TODO(floitsch): we should not need to test against the empty string.
53 if (matched === null || matched == "") return 0.0; 53 if (matched === null || matched == "") return 0.0;
54 return Math.parseDouble(matched); 54 return Math.parseDouble(matched);
55 } 55 }
56 56
57 int years = Math.parseInt(match[1]); 57 int year = Math.parseInt(match[1]);
58 int month = Math.parseInt(match[2]); 58 int month = Math.parseInt(match[2]);
59 int day = Math.parseInt(match[3]); 59 int day = Math.parseInt(match[3]);
60 int hour = parseIntOrZero(match[4]); 60 int hour = parseIntOrZero(match[4]);
61 int minute = parseIntOrZero(match[5]); 61 int minute = parseIntOrZero(match[5]);
62 int second = parseIntOrZero(match[6]); 62 int second = parseIntOrZero(match[6]);
63 bool addOneMillisecond = false; 63 bool addOneMillisecond = false;
64 int millisecond = (parseDoubleOrZero(match[7]) * 1000).round().toInt(); 64 int millisecond = (parseDoubleOrZero(match[7]) * 1000).round().toInt();
65 if (millisecond == 1000) { 65 if (millisecond == 1000) {
66 addOneMillisecond = true; 66 addOneMillisecond = true;
67 millisecond = 999; 67 millisecond = 999;
68 } 68 }
69 // TODO(floitsch): we should not need to test against the empty string. 69 // TODO(floitsch): we should not need to test against the empty string.
70 bool isUtc = (match[8] !== null) && (match[8] != ""); 70 bool isUtc = (match[8] !== null) && (match[8] != "");
71 int millisecondsSinceEpoch = _brokenDownDateToMillisecondsSinceEpoch( 71 int millisecondsSinceEpoch = _brokenDownDateToMillisecondsSinceEpoch(
72 years, month, day, hour, minute, second, millisecond, isUtc); 72 year, month, day, hour, minute, second, millisecond, isUtc);
73 if (millisecondsSinceEpoch === null) { 73 if (millisecondsSinceEpoch === null) {
74 throw new IllegalArgumentException(formattedString); 74 throw new IllegalArgumentException(formattedString);
75 } 75 }
76 if (addOneMillisecond) millisecondsSinceEpoch++; 76 if (addOneMillisecond) millisecondsSinceEpoch++;
77 return new DateImplementation.fromMillisecondsSinceEpoch( 77 return new DateImplementation.fromMillisecondsSinceEpoch(
78 millisecondsSinceEpoch, isUtc); 78 millisecondsSinceEpoch, isUtc);
79 } else { 79 } else {
80 throw new IllegalArgumentException(formattedString); 80 throw new IllegalArgumentException(formattedString);
81 } 81 }
82 } 82 }
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 /** Returns a [Duration] with the difference of [this] and [other]. */ 239 /** Returns a [Duration] with the difference of [this] and [other]. */
240 Duration difference(Date other) { 240 Duration difference(Date other) {
241 int ms = millisecondsSinceEpoch; 241 int ms = millisecondsSinceEpoch;
242 int otherMs = other.millisecondsSinceEpoch; 242 int otherMs = other.millisecondsSinceEpoch;
243 return new DurationImplementation(milliseconds: ms - otherMs); 243 return new DurationImplementation(milliseconds: ms - otherMs);
244 } 244 }
245 245
246 /** The first list contains the days until each month in non-leap years. The 246 /** The first list contains the days until each month in non-leap years. The
247 * second list contains the days in leap years. */ 247 * second list contains the days in leap years. */
248 static final List<List<int>> _DAYS_UNTIL_MONTH = 248 static final List<List<int>> _DAYS_UNTIL_MONTH =
249 const [const [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334], 249 const [
250 const [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335]]; 250 const [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365],
floitsch 2012/08/15 08:44:26 No need for the additional days anymore.
dominich 2012/08/17 16:38:33 Done.
251 const [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366]];
251 252
252 // Returns the UTC year, month and day for the corresponding 253 // Returns the UTC year, month and day for the corresponding
253 // [millisecondsSinceEpoch]. 254 // [millisecondsSinceEpoch].
254 // Code is adapted from V8. 255 // Code is adapted from V8.
255 static List<int> _decomposeIntoYearMonthDay(int millisecondsSinceEpoch) { 256 static List<int> _decomposeIntoYearMonthDay(int millisecondsSinceEpoch) {
256 // TODO(floitsch): cache result. 257 // TODO(floitsch): cache result.
257 final int DAYS_IN_4_YEARS = 4 * 365 + 1; 258 final int DAYS_IN_4_YEARS = 4 * 365 + 1;
258 final int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1; 259 final int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1;
259 final int DAYS_IN_400_YEARS = 4 * DAYS_IN_100_YEARS + 1; 260 final int DAYS_IN_400_YEARS = 4 * DAYS_IN_100_YEARS + 1;
260 final int DAYS_1970_TO_2000 = 30 * 365 + 7; 261 final int DAYS_1970_TO_2000 = 30 * 365 + 7;
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 - _flooredDivision(year - 1901, 100) 334 - _flooredDivision(year - 1901, 100)
334 + _flooredDivision(year - 1601, 400); 335 + _flooredDivision(year - 1601, 400);
335 } 336 }
336 337
337 static bool _isLeapYear(y) { 338 static bool _isLeapYear(y) {
338 return (y.remainder(4) == 0) && 339 return (y.remainder(4) == 0) &&
339 ((y.remainder(100) != 0) || (y.remainder(400) == 0)); 340 ((y.remainder(100) != 0) || (y.remainder(400) == 0));
340 } 341 }
341 342
342 static _brokenDownDateToMillisecondsSinceEpoch( 343 static _brokenDownDateToMillisecondsSinceEpoch(
343 int years, int month, int day, 344 int year, int month, int day,
344 int hour, int minute, int second, int millisecond, 345 int hour, int minute, int second, int millisecond,
345 bool isUtc) { 346 bool isUtc) {
346 if ((month < 1) || (month > 12)) return null; 347 // JavaScript month is zero-based while Dart is one-based. This should
347 if ((day < 1) || (day > 31)) return null; 348 // simplify some calculations.
348 // Leap seconds can lead to hour == 24. 349 --month;
349 if ((hour < 0) || (hour > 24)) return null; 350 // Deal with under and overflow.
350 if ((hour == 24) && ((minute != 0) || (second != 0))) return null; 351 year += (month / 12).floor().toInt();
351 if ((minute < 0) || (minute > 59)) return null; 352 month = month % 12;
352 if ((second < 0) || (second > 59)) return null; 353 int clampedMonth = month.remainder(12);
353 if ((millisecond < 0) || (millisecond > 999)) return null; 354 if (clampedMonth < 0) {
355 --year;
356 clampedMonth += 12;
357 }
354 358
355 // First compute the seconds in UTC, independent of the [isUtc] flag. If 359 // First compute the seconds in UTC, independent of the [isUtc] flag. If
356 // necessary we will add the time-zone offset later on. 360 // necessary we will add the time-zone offset later on.
357 int days = day - 1; 361 int days = day - 1;
358 days += _DAYS_UNTIL_MONTH[_isLeapYear(years) ? 1 : 0][month - 1]; 362 days += _DAYS_UNTIL_MONTH[_isLeapYear(year) ? 1 : 0][clampedMonth];
359 days += _dayFromYear(years); 363 days += _dayFromYear(year);
360 int millisecondsSinceEpoch = days * Duration.MILLISECONDS_PER_DAY + 364 int millisecondsSinceEpoch = days * Duration.MILLISECONDS_PER_DAY +
361 hour * Duration.MILLISECONDS_PER_HOUR + 365 hour * Duration.MILLISECONDS_PER_HOUR +
362 minute * Duration.MILLISECONDS_PER_MINUTE+ 366 minute * Duration.MILLISECONDS_PER_MINUTE+
363 second * Duration.MILLISECONDS_PER_SECOND + 367 second * Duration.MILLISECONDS_PER_SECOND +
364 millisecond; 368 millisecond;
365 369
366 // Since [_timeZoneOffsetInSeconds] will crash if the input is far out of 370 // Since [_timeZoneOffsetInSeconds] will crash if the input is far out of
367 // the valid range we do a preliminary test that weeds out values that can 371 // the valid range we do a preliminary test that weeds out values that can
368 // not become valid even with timezone adjustments. 372 // not become valid even with timezone adjustments.
369 // The timezone adjustment is always less than a day, so adding a security 373 // The timezone adjustment is always less than a day, so adding a security
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 487
484 static String _timeZoneNameForClampedSeconds(int secondsSinceEpoch) 488 static String _timeZoneNameForClampedSeconds(int secondsSinceEpoch)
485 native "DateNatives_timeZoneName"; 489 native "DateNatives_timeZoneName";
486 490
487 static int _timeZoneOffsetInSecondsForClampedSeconds(int secondsSinceEpoch) 491 static int _timeZoneOffsetInSecondsForClampedSeconds(int secondsSinceEpoch)
488 native "DateNatives_timeZoneOffsetInSeconds"; 492 native "DateNatives_timeZoneOffsetInSeconds";
489 493
490 static int _localTimeZoneAdjustmentInSeconds() 494 static int _localTimeZoneAdjustmentInSeconds()
491 native "DateNatives_localTimeZoneAdjustmentInSeconds"; 495 native "DateNatives_localTimeZoneAdjustmentInSeconds";
492 } 496 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698