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

Side by Side Diff: sdk/lib/core/date_time.dart

Issue 1091553005: Fix bug in DateTime.parse. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Shorter line Created 5 years, 8 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 | « no previous file | tests/corelib/date_time_parse_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 4
5 part of dart.core; 5 part of dart.core;
6 6
7 /** 7 /**
8 * An instant in time, such as July 20, 1969, 8:18pm GMT. 8 * An instant in time, such as July 20, 1969, 8:18pm GMT.
9 * 9 *
10 * Create a DateTime object by using one of the constructors 10 * Create a DateTime object by using one of the constructors
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 * * An optional time part, separated from the date by either `T` or a space. 208 * * An optional time part, separated from the date by either `T` or a space.
209 * The time part is a two digit hour, 209 * The time part is a two digit hour,
210 * then optionally a two digit minutes value, 210 * then optionally a two digit minutes value,
211 * then optionally a two digit seconds value, and 211 * then optionally a two digit seconds value, and
212 * then optionally a '.' followed by a one-to-six digit second fraction. 212 * then optionally a '.' followed by a one-to-six digit second fraction.
213 * The minuts and seconds may be separated from the previous parts by a ':'. 213 * The minuts and seconds may be separated from the previous parts by a ':'.
214 * Examples: "12", "12:30:24.124", "123010.50". 214 * Examples: "12", "12:30:24.124", "123010.50".
215 * * An optional time-zone offset part, 215 * * An optional time-zone offset part,
216 * possibly separated from the previous by a space. 216 * possibly separated from the previous by a space.
217 * The time zone is either 'z' or 'Z', or it is a signed two digit hour 217 * The time zone is either 'z' or 'Z', or it is a signed two digit hour
218 * part and an optional two digit minute part. 218 * part and an optional two digit minute part. The sign must be either
219 * "+" or "-", and can not be omitted.
219 * The minutes may be separted from the hours by a ':'. 220 * The minutes may be separted from the hours by a ':'.
220 * Examples: "Z", "-10", "01:30", "1130". 221 * Examples: "Z", "-10", "01:30", "1130".
221 * 222 *
222 * This includes the output of both [toString] and [toIso8601String], which 223 * This includes the output of both [toString] and [toIso8601String], which
223 * will be parsed back into a `DateTime` object with the same time as the 224 * will be parsed back into a `DateTime` object with the same time as the
224 * original. 225 * original.
225 * 226 *
226 * The result is always in either local time or UTC. 227 * The result is always in either local time or UTC.
227 * If a time zone offset other than UTC is specified, 228 * If a time zone offset other than UTC is specified,
228 * the time is converted to the equivalent UTC time. 229 * the time is converted to the equivalent UTC time.
(...skipping 26 matching lines...) Expand all
255 * time_opt ::= <empty> | (' ' | 'T') hour minutes_opt 256 * time_opt ::= <empty> | (' ' | 'T') hour minutes_opt
256 * minutes_opt ::= <empty> | colon_opt digit{2} seconds_opt 257 * minutes_opt ::= <empty> | colon_opt digit{2} seconds_opt
257 * seconds_opt ::= <empty> | colon_opt digit{2} millis_opt 258 * seconds_opt ::= <empty> | colon_opt digit{2} millis_opt
258 * millis_opt ::= <empty> | '.' digit{1,6} 259 * millis_opt ::= <empty> | '.' digit{1,6}
259 * timezone_opt ::= <empty> | space_opt timezone 260 * timezone_opt ::= <empty> | space_opt timezone
260 * space_opt :: ' ' | <empty> 261 * space_opt :: ' ' | <empty>
261 * timezone ::= 'z' | 'Z' | sign digit{2} timezonemins_opt 262 * timezone ::= 'z' | 'Z' | sign digit{2} timezonemins_opt
262 * timezonemins_opt ::= <empty> | colon_opt digit{2} 263 * timezonemins_opt ::= <empty> | colon_opt digit{2}
263 */ 264 */
264 final RegExp re = new RegExp( 265 final RegExp re = new RegExp(
265 r'^([+-]?\d{4,6})-?(\d\d)-?(\d\d)' // The day part. 266 r'^([+-]?\d{4,6})-?(\d\d)-?(\d\d)' // Day part.
266 r'(?:[ T](\d\d)(?::?(\d\d)(?::?(\d\d)(.\d{1,6})?)?)?' // The time part 267 r'(?:[ T](\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d{1,6}))?)?)?' // Time part.
267 r'( ?[zZ]| ?([-+])(\d\d)(?::?(\d\d))?)?)?$'); // The timezone part 268 r'( ?[zZ]| ?([-+])(\d\d)(?::?(\d\d))?)?)?$'); // Timezone part.
268 269
269 Match match = re.firstMatch(formattedString); 270 Match match = re.firstMatch(formattedString);
270 if (match != null) { 271 if (match != null) {
271 int parseIntOrZero(String matched) { 272 int parseIntOrZero(String matched) {
272 if (matched == null) return 0; 273 if (matched == null) return 0;
273 return int.parse(matched); 274 return int.parse(matched);
274 } 275 }
275 276
276 double parseDoubleOrZero(String matched) { 277 // Parses fractional second digits of '.(\d{1,6})' into milliseconds.
277 if (matched == null) return 0.0; 278 // Uses first three digits (assumed to be zero if not there), and
278 return double.parse(matched); 279 // rounds up if fourth digit is 5 or greater.
280 // Should be equivalent to `(double.parse(".$matchd")*1000).round()`.
281 int parseMilliseconds(String matched) {
282 if (matched == null) return 0;
283 int length = matched.length;
284 assert(length >= 1);
285 assert(length <= 6);
286
287 int result = (matched.codeUnitAt(0) ^ 0x30);
288 if (length <= 3) {
289 int i = 1;
290 while (i < length) {
291 result *= 10;
292 result += matched.codeUnitAt(i) ^ 0x30;
293 i++;
294 }
295 while (i < 3) {
296 result *= 10;
297 i++;
298 }
299 return result;
300 }
301 // Parse the prefix from 0..3 without creating a new substring.
302 result = result * 10 + (matched.codeUnitAt(1) ^ 0x30);
303 result = result * 10 + (matched.codeUnitAt(2) ^ 0x30);
304 if (matched.codeUnitAt(3) >= 0x35) {
305 result += 1;
306 }
307 return result;
279 } 308 }
280 309
281 int years = int.parse(match[1]); 310 int years = int.parse(match[1]);
282 int month = int.parse(match[2]); 311 int month = int.parse(match[2]);
283 int day = int.parse(match[3]); 312 int day = int.parse(match[3]);
284 int hour = parseIntOrZero(match[4]); 313 int hour = parseIntOrZero(match[4]);
285 int minute = parseIntOrZero(match[5]); 314 int minute = parseIntOrZero(match[5]);
286 int second = parseIntOrZero(match[6]); 315 int second = parseIntOrZero(match[6]);
287 bool addOneMillisecond = false; 316 bool addOneMillisecond = false;
288 int millisecond = (parseDoubleOrZero(match[7]) * 1000).round(); 317 int millisecond = parseMilliseconds(match[7]);
289 if (millisecond == 1000) { 318 if (millisecond == 1000) {
290 addOneMillisecond = true; 319 addOneMillisecond = true;
291 millisecond = 999; 320 millisecond = 999;
292 } 321 }
293 bool isUtc = false; 322 bool isUtc = false;
294 if (match[8] != null) { // timezone part 323 if (match[8] != null) { // timezone part
295 isUtc = true; 324 isUtc = true;
296 if (match[9] != null) { 325 if (match[9] != null) {
297 // timezone other than 'Z' and 'z'. 326 // timezone other than 'Z' and 'z'.
298 int sign = (match[9] == '-') ? -1 : 1; 327 int sign = (match[9] == '-') ? -1 : 1;
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after
671 * In accordance with ISO 8601 700 * In accordance with ISO 8601
672 * a week starts with Monday, which has the value 1. 701 * a week starts with Monday, which has the value 1.
673 * 702 *
674 * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); 703 * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00");
675 * assert(moonLanding.weekday == 7); 704 * assert(moonLanding.weekday == 7);
676 * assert(moonLanding.weekday == DateTime.SUNDAY); 705 * assert(moonLanding.weekday == DateTime.SUNDAY);
677 * 706 *
678 */ 707 */
679 external int get weekday; 708 external int get weekday;
680 } 709 }
OLDNEW
« no previous file with comments | « no previous file | tests/corelib/date_time_parse_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698