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

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: remove loops 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
« no previous file with comments | « lib/compiler/implementation/lib/js_helper.dart ('k') | tests/corelib/date_time_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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],
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 // Deal with under and overflow.
347 if ((day < 1) || (day > 31)) return null; 348 second += (millisecond / 1000).floor().toInt();
floitsch 2012/08/14 08:31:38 You shouldn't need to look at the hours, minutes,
dominich 2012/08/14 16:49:20 Of course - good point :)
348 // Leap seconds can lead to hour == 24. 349 millisecond = millisecond % 1000;
349 if ((hour < 0) || (hour > 24)) return null; 350 minute += (second / 60).floor().toInt();
350 if ((hour == 24) && ((minute != 0) || (second != 0))) return null; 351 second = second % 60;
351 if ((minute < 0) || (minute > 59)) return null; 352 hour += (minute / 60).floor().toInt();
352 if ((second < 0) || (second > 59)) return null; 353 minute = minute % 60;
353 if ((millisecond < 0) || (millisecond > 999)) return null; 354 day += (hour / 24).floor().toInt();
355 hour = hour % 24;
356 year += ((month - 1) / 12).floor().toInt();
357 month = (month - 1) % 12 + 1;
floitsch 2012/08/14 08:31:38 Instead of dealing with +/- 1 all over the place d
dominich 2012/08/14 16:49:20 Done.
358 int clampedMonth = (month - 1).remainder(12) + 1;
359 if (clampedMonth < 1) {
360 --year;
361 clampedMonth += 12;
362 }
354 363
355 // First compute the seconds in UTC, independent of the [isUtc] flag. If 364 // First compute the seconds in UTC, independent of the [isUtc] flag. If
356 // necessary we will add the time-zone offset later on. 365 // necessary we will add the time-zone offset later on.
357 int days = day - 1; 366 int days = day - 1;
358 days += _DAYS_UNTIL_MONTH[_isLeapYear(years) ? 1 : 0][month - 1]; 367 days += _DAYS_UNTIL_MONTH[_isLeapYear(year) ? 1 : 0][clampedMonth - 1];
359 days += _dayFromYear(years); 368 days += _dayFromYear(year);
360 int millisecondsSinceEpoch = days * Duration.MILLISECONDS_PER_DAY + 369 int millisecondsSinceEpoch = days * Duration.MILLISECONDS_PER_DAY +
361 hour * Duration.MILLISECONDS_PER_HOUR + 370 hour * Duration.MILLISECONDS_PER_HOUR +
362 minute * Duration.MILLISECONDS_PER_MINUTE+ 371 minute * Duration.MILLISECONDS_PER_MINUTE+
363 second * Duration.MILLISECONDS_PER_SECOND + 372 second * Duration.MILLISECONDS_PER_SECOND +
364 millisecond; 373 millisecond;
365 374
366 // Since [_timeZoneOffsetInSeconds] will crash if the input is far out of 375 // 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 376 // the valid range we do a preliminary test that weeds out values that can
368 // not become valid even with timezone adjustments. 377 // not become valid even with timezone adjustments.
369 // The timezone adjustment is always less than a day, so adding a security 378 // 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 492
484 static String _timeZoneNameForClampedSeconds(int secondsSinceEpoch) 493 static String _timeZoneNameForClampedSeconds(int secondsSinceEpoch)
485 native "DateNatives_timeZoneName"; 494 native "DateNatives_timeZoneName";
486 495
487 static int _timeZoneOffsetInSecondsForClampedSeconds(int secondsSinceEpoch) 496 static int _timeZoneOffsetInSecondsForClampedSeconds(int secondsSinceEpoch)
488 native "DateNatives_timeZoneOffsetInSeconds"; 497 native "DateNatives_timeZoneOffsetInSeconds";
489 498
490 static int _localTimeZoneAdjustmentInSeconds() 499 static int _localTimeZoneAdjustmentInSeconds()
491 native "DateNatives_localTimeZoneAdjustmentInSeconds"; 500 native "DateNatives_localTimeZoneAdjustmentInSeconds";
492 } 501 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/lib/js_helper.dart ('k') | tests/corelib/date_time_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698