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

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: 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 [const [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365],
250 const [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335]]; 250 const [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366]] ;
floitsch 2012/08/06 21:00:58 80chars.
dominich 2012/08/06 21:20:58 Done.
251 251
252 // Returns the UTC year, month and day for the corresponding 252 // Returns the UTC year, month and day for the corresponding
253 // [millisecondsSinceEpoch]. 253 // [millisecondsSinceEpoch].
254 // Code is adapted from V8. 254 // Code is adapted from V8.
255 static List<int> _decomposeIntoYearMonthDay(int millisecondsSinceEpoch) { 255 static List<int> _decomposeIntoYearMonthDay(int millisecondsSinceEpoch) {
256 // TODO(floitsch): cache result. 256 // TODO(floitsch): cache result.
257 final int DAYS_IN_4_YEARS = 4 * 365 + 1; 257 final int DAYS_IN_4_YEARS = 4 * 365 + 1;
258 final int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1; 258 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; 259 final int DAYS_IN_400_YEARS = 4 * DAYS_IN_100_YEARS + 1;
260 final int DAYS_1970_TO_2000 = 30 * 365 + 7; 260 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) 333 - _flooredDivision(year - 1901, 100)
334 + _flooredDivision(year - 1601, 400); 334 + _flooredDivision(year - 1601, 400);
335 } 335 }
336 336
337 static bool _isLeapYear(y) { 337 static bool _isLeapYear(y) {
338 return (y.remainder(4) == 0) && 338 return (y.remainder(4) == 0) &&
339 ((y.remainder(100) != 0) || (y.remainder(400) == 0)); 339 ((y.remainder(100) != 0) || (y.remainder(400) == 0));
340 } 340 }
341 341
342 static _brokenDownDateToMillisecondsSinceEpoch( 342 static _brokenDownDateToMillisecondsSinceEpoch(
343 int years, int month, int day, 343 int year, int month, int day,
344 int hour, int minute, int second, int millisecond, 344 int hour, int minute, int second, int millisecond,
345 bool isUtc) { 345 bool isUtc) {
346 if ((month < 1) || (month > 12)) return null; 346 // Deal with under and overflow.
347 if ((day < 1) || (day > 31)) return null; 347 second += (millisecond / 1000).floor().toInt();
348 // Leap seconds can lead to hour == 24. 348 millisecond = millisecond % 1000;
349 if ((hour < 0) || (hour > 24)) return null; 349 minute += (second / 60).floor().toInt();
350 if ((hour == 24) && ((minute != 0) || (second != 0))) return null; 350 second = second % 60;
351 if ((minute < 0) || (minute > 59)) return null; 351 hour += (minute / 60).floor().toInt();
352 if ((second < 0) || (second > 59)) return null; 352 minute = minute % 60;
353 if ((millisecond < 0) || (millisecond > 999)) return null; 353 day += (hour / 24).floor().toInt();
354 hour = hour % 24;
355 year += ((month - 1) / 12).floor().toInt();
356 month = (month - 1) % 12 + 1;
357
358 // Start with the current month and add _DAYS_UNTIL_MONTH until day > 1
359 // (and <= numDaysInMonth).
360 while (day < 1) {
361 int numDaysInMonth = _DAYS_UNTIL_MONTH[_isLeapYear(year) ? 1 : 0][month] -
362 _DAYS_UNTIL_MONTH[_isLeapYear(year) ? 1 : 0][month - 1];
363 day += numDaysInMonth;
364 --month;
365 if (month < 1) {
366 --year;
367 month = 12;
368 }
369 }
370
371 // And in reverse.
372 int numDaysInMonth = _DAYS_UNTIL_MONTH[_isLeapYear(year) ? 1 : 0][month] -
373 _DAYS_UNTIL_MONTH[_isLeapYear(year) ? 1 : 0][month - 1];
374 while (day > numDaysInMonth) {
375 day -= numDaysInMonth;
376 ++month;
377 if (month > 12) {
378 ++year;
379 month = 1;
380 }
381 numDaysInMonth = _DAYS_UNTIL_MONTH[_isLeapYear(year) ? 1 : 0][month] -
382 _DAYS_UNTIL_MONTH[_isLeapYear(year) ? 1 : 0][month - 1];
383 }
354 384
355 // First compute the seconds in UTC, independent of the [isUtc] flag. If 385 // First compute the seconds in UTC, independent of the [isUtc] flag. If
356 // necessary we will add the time-zone offset later on. 386 // necessary we will add the time-zone offset later on.
357 int days = day - 1; 387 int days = day - 1;
358 days += _DAYS_UNTIL_MONTH[_isLeapYear(years) ? 1 : 0][month - 1]; 388 days += _DAYS_UNTIL_MONTH[_isLeapYear(year) ? 1 : 0][month - 1];
floitsch 2012/08/06 21:00:58 Isn't it enough to: years += (month - 1) ~/ 12; in
dominich 2012/08/06 21:20:58 No - clampedMonth could be -50 in which case years
floitsch 2012/08/07 09:10:07 I don't see how this could happen since it is .rem
dominich 2012/08/13 19:26:35 i've just realised - i'm not sure which bit of the
floitsch 2012/08/13 19:41:34 Unless I'm wrong you don't need to do any loops. T
359 days += _dayFromYear(years); 389 days += _dayFromYear(year);
360 int millisecondsSinceEpoch = days * Duration.MILLISECONDS_PER_DAY + 390 int millisecondsSinceEpoch = days * Duration.MILLISECONDS_PER_DAY +
361 hour * Duration.MILLISECONDS_PER_HOUR + 391 hour * Duration.MILLISECONDS_PER_HOUR +
362 minute * Duration.MILLISECONDS_PER_MINUTE+ 392 minute * Duration.MILLISECONDS_PER_MINUTE+
363 second * Duration.MILLISECONDS_PER_SECOND + 393 second * Duration.MILLISECONDS_PER_SECOND +
364 millisecond; 394 millisecond;
365 395
366 // Since [_timeZoneOffsetInSeconds] will crash if the input is far out of 396 // 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 397 // the valid range we do a preliminary test that weeds out values that can
368 // not become valid even with timezone adjustments. 398 // not become valid even with timezone adjustments.
369 // The timezone adjustment is always less than a day, so adding a security 399 // 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 513
484 static String _timeZoneNameForClampedSeconds(int secondsSinceEpoch) 514 static String _timeZoneNameForClampedSeconds(int secondsSinceEpoch)
485 native "DateNatives_timeZoneName"; 515 native "DateNatives_timeZoneName";
486 516
487 static int _timeZoneOffsetInSecondsForClampedSeconds(int secondsSinceEpoch) 517 static int _timeZoneOffsetInSecondsForClampedSeconds(int secondsSinceEpoch)
488 native "DateNatives_timeZoneOffsetInSeconds"; 518 native "DateNatives_timeZoneOffsetInSeconds";
489 519
490 static int _localTimeZoneAdjustmentInSeconds() 520 static int _localTimeZoneAdjustmentInSeconds()
491 native "DateNatives_localTimeZoneAdjustmentInSeconds"; 521 native "DateNatives_localTimeZoneAdjustmentInSeconds";
492 } 522 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698