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

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

Issue 169493002: Add time-zone parsing to DateTime.parse. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | 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 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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 * 75 *
76 * DateTime today = new DateTime.now(); 76 * DateTime today = new DateTime.now();
77 * DateTime sixtyDaysFromNow = today.add(new Duration(days: 60)); 77 * DateTime sixtyDaysFromNow = today.add(new Duration(days: 60));
78 * 78 *
79 * To find out how much time is between two DateTime objects use 79 * To find out how much time is between two DateTime objects use
80 * [difference], which returns a [Duration] object: 80 * [difference], which returns a [Duration] object:
81 * 81 *
82 * Duration difference = berlinWallFell.difference(moonLanding) 82 * Duration difference = berlinWallFell.difference(moonLanding)
83 * assert(difference.inDays == 7416); 83 * assert(difference.inDays == 7416);
84 * 84 *
85 * The difference between two dates in different time zones
86 * is just the number of nanoseconds between the two points in time.
87 * It doesn't take calendar days into account.
88 * That means that the difference between two midnights in local time may be
89 * less than 24 hours times the number of days between them,
90 * if there is a daylight saving change in between.
91 * If the difference above is calculated using Australian local time, the
92 * difference is 7415 days and 23 hours, which is only 7415 whole days as
93 * reported by `inDays`.
94 *
85 * ## Other resources 95 * ## Other resources
86 * 96 *
87 * See [Duration] to represent a span of time. 97 * See [Duration] to represent a span of time.
88 * See [Stopwatch] to measure timespans. 98 * See [Stopwatch] to measure timespans.
89 * 99 *
90 * The DateTime class does not provide internationalization. 100 * The DateTime class does not provide internationalization.
91 * To internationalize your code, use 101 * To internationalize your code, use
92 * the [intl](http://pub.dartlang.org/packages/intl) package. 102 * the [intl](http://pub.dartlang.org/packages/intl) package.
93 * 103 *
94 */ 104 */
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 final bool isUtc; 151 final bool isUtc;
142 152
143 /** 153 /**
144 * Constructs a [DateTime] instance specified in the local time zone. 154 * Constructs a [DateTime] instance specified in the local time zone.
145 * 155 *
146 * For example, 156 * For example,
147 * to create a new DateTime object representing April 29, 2014, 6:04am: 157 * to create a new DateTime object representing April 29, 2014, 6:04am:
148 * 158 *
149 * DateTime annularEclipse = new DateTime(2014, DateTime.APRIL, 29, 6, 4); 159 * DateTime annularEclipse = new DateTime(2014, DateTime.APRIL, 29, 6, 4);
150 */ 160 */
151 // TODO(8042): This should be a redirecting constructor and not a factory. 161 DateTime(int year,
152 factory DateTime(int year,
153 [int month = 1, 162 [int month = 1,
154 int day = 1, 163 int day = 1,
155 int hour = 0, 164 int hour = 0,
156 int minute = 0, 165 int minute = 0,
157 int second = 0, 166 int second = 0,
158 int millisecond = 0]) { 167 int millisecond = 0])
159 return new DateTime._internal( 168 : this._internal(
Lasse Reichstein Nielsen 2014/02/17 11:24:10 Reverting this change since 8042 isn't fixed yet.
Lasse Reichstein Nielsen 2014/02/19 13:11:28 It's fixed now. Thank you Johnni.
160 year, month, day, hour, minute, second, millisecond, false); 169 year, month, day, hour, minute, second, millisecond, false);
161 }
162 170
163 /** 171 /**
164 * Constructs a [DateTime] instance specified in the UTC time zone. 172 * Constructs a [DateTime] instance specified in the UTC time zone.
165 * 173 *
166 * DateTime dDay = new DateTime.utc(1944, DateTime.JUNE, 6); 174 * DateTime dDay = new DateTime.utc(1944, DateTime.JUNE, 6);
167 */ 175 */
168 // TODO(8042): This should be a redirecting constructor and not a factory. 176 DateTime.utc(int year,
169 factory DateTime.utc(int year, 177 [int month = 1,
170 [int month = 1, 178 int day = 1,
171 int day = 1, 179 int hour = 0,
172 int hour = 0, 180 int minute = 0,
173 int minute = 0, 181 int second = 0,
174 int second = 0, 182 int millisecond = 0])
175 int millisecond = 0]) { 183 : this._internal(
176 return new DateTime._internal(
177 year, month, day, hour, minute, second, millisecond, true); 184 year, month, day, hour, minute, second, millisecond, true);
178 }
179 185
180 /** 186 /**
181 * Constructs a [DateTime] instance with current date and time in the 187 * Constructs a [DateTime] instance with current date and time in the
182 * local time zone. 188 * local time zone.
183 * 189 *
184 * DateTime thisInstant = new DateTime.now(); 190 * DateTime thisInstant = new DateTime.now();
185 * 191 *
186 */ 192 */
187 // TODO(8042): This should be a redirecting constructor and not a factory. 193 DateTime.now() : this._now();
188 factory DateTime.now() { return new DateTime._now(); }
189 194
190 /** 195 /**
191 * Constructs a new [DateTime] instance based on [formattedString]. 196 * Constructs a new [DateTime] instance based on [formattedString].
192 * 197 *
193 * Throws a [FormatException] if the input cannot be parsed. 198 * Throws a [FormatException] if the input cannot be parsed.
194 * 199 *
195 * The function parses a subset of ISO 8601. Examples of accepted strings: 200 * The function parses a subset of ISO 8601
201 * which includes the subset accepted by RFC 3339.
202 *
203 * The result is always in either local time or UTC.
204 * If a time zone offset other than UTC is specified,
205 * the time is converted to the equivalent UTC time.
206 *
207 * Examples of accepted strings:
196 * 208 *
197 * * `"2012-02-27 13:27:00"` 209 * * `"2012-02-27 13:27:00"`
198 * * `"2012-02-27 13:27:00.123456z"` 210 * * `"2012-02-27 13:27:00.123456z"`
199 * * `"20120227 13:27:00"` 211 * * `"20120227 13:27:00"`
200 * * `"20120227T132700"` 212 * * `"20120227T132700"`
201 * * `"20120227"` 213 * * `"20120227"`
202 * * `"+20120227"` 214 * * `"+20120227"`
203 * * `"2012-02-27T14Z"` 215 * * `"2012-02-27T14Z"`
204 * * `"2012-02-27T14+00:00"` 216 * * `"2012-02-27T14+00:00"`
205 * * `"-123450101 00:00:00 Z"`: in the year -12345. 217 * * `"-123450101 00:00:00 Z"`: in the year -12345.
218 * * `"2002-02-27T14:00:00-0500"`: Same as `"2002-02-27T19:00:00Z"`
206 */ 219 */
207 // TODO(floitsch): specify grammar. 220 // TODO(floitsch): specify grammar.
221 // TODO(lrn): restrict incorrect values like 2003-02-29T50:70:80.
208 static DateTime parse(String formattedString) { 222 static DateTime parse(String formattedString) {
209 /* 223 /*
210 * date ::= yeardate time_opt timezone_opt 224 * date ::= yeardate time_opt timezone_opt
211 * yeardate ::= year colon_opt month colon_opt day 225 * yeardate ::= year colon_opt month colon_opt day
212 * year ::= sign_opt digit{4,5} 226 * year ::= sign_opt digit{4,5}
213 * colon_opt :: <empty> | ':' 227 * colon_opt :: <empty> | ':'
214 * sign_opt ::= <empty> | '+' | '-' 228 * sign ::= '+' | '-'
229 * sign_opt ::= <empty> | sign
215 * month ::= digit{2} 230 * month ::= digit{2}
216 * day ::= digit{2} 231 * day ::= digit{2}
217 * time_opt ::= <empty> | (' ' | 'T') hour minutes_opt 232 * time_opt ::= <empty> | (' ' | 'T') hour minutes_opt
218 * minutes_opt ::= <empty> | ':' digit{2} seconds_opt 233 * minutes_opt ::= <empty> | ':' digit{2} seconds_opt
219 * seconds_opt ::= <empty> | ':' digit{2} millis_opt 234 * seconds_opt ::= <empty> | ':' digit{2} millis_opt
220 * millis_opt ::= <empty> | '.' digit{1,6} 235 * millis_opt ::= <empty> | '.' digit{1,6}
221 * timezone_opt ::= <empty> | space_opt timezone 236 * timezone_opt ::= <empty> | space_opt timezone
222 * space_opt :: ' ' | <empty> 237 * space_opt :: ' ' | <empty>
223 * timezone ::= 'z' | 'Z' | '+' '0' '0' timezonemins_opt 238 * timezone ::= 'z' | 'Z' | sign digit{2} timezonemins_opt
224 * timezonemins_opt ::= <empty> | colon_opt '0' '0' 239 * timezonemins_opt ::= <empty> | colon_opt digit{2}
225 */ 240 */
226 final RegExp re = new RegExp( 241 final RegExp re = new RegExp(
227 r'^([+-]?\d?\d\d\d\d)-?(\d\d)-?(\d\d)' // The day part. 242 r'^([+-]?\d{4,5})-?(\d\d)-?(\d\d)' // The day part.
228 r'(?:[ T](\d\d)(?::?(\d\d)(?::?(\d\d)(.\d{1,6})?)?)?' // The time part 243 r'(?:[ T](\d\d)(?::?(\d\d)(?::?(\d\d)(.\d{1,6})?)?)?' // The time part
229 r'( ?[zZ]| ?\+00(?::?00)?)?)?$'); // The timezone part 244 r'( ?[zZ]| ?([-+])(\d\d)(?::?(\d\d))?)?)?$'); // The timezone part
230 245
231 Match match = re.firstMatch(formattedString); 246 Match match = re.firstMatch(formattedString);
232 if (match != null) { 247 if (match != null) {
233 int parseIntOrZero(String matched) { 248 int parseIntOrZero(String matched) {
234 if (matched == null) return 0; 249 if (matched == null) return 0;
235 return int.parse(matched); 250 return int.parse(matched);
236 } 251 }
237 252
238 double parseDoubleOrZero(String matched) { 253 double parseDoubleOrZero(String matched) {
239 if (matched == null) return 0.0; 254 if (matched == null) return 0.0;
240 return double.parse(matched); 255 return double.parse(matched);
241 } 256 }
242 257
243 int years = int.parse(match[1]); 258 int years = int.parse(match[1]);
244 int month = int.parse(match[2]); 259 int month = int.parse(match[2]);
245 int day = int.parse(match[3]); 260 int day = int.parse(match[3]);
246 int hour = parseIntOrZero(match[4]); 261 int hour = parseIntOrZero(match[4]);
247 int minute = parseIntOrZero(match[5]); 262 int minute = parseIntOrZero(match[5]);
248 int second = parseIntOrZero(match[6]); 263 int second = parseIntOrZero(match[6]);
249 bool addOneMillisecond = false; 264 bool addOneMillisecond = false;
250 int millisecond = (parseDoubleOrZero(match[7]) * 1000).round(); 265 int millisecond = (parseDoubleOrZero(match[7]) * 1000).round();
251 if (millisecond == 1000) { 266 if (millisecond == 1000) {
252 addOneMillisecond = true; 267 addOneMillisecond = true;
253 millisecond = 999; 268 millisecond = 999;
254 } 269 }
255 bool isUtc = (match[8] != null); 270 bool isUtc = false;
271 if (match[8] != null) { // timezone part
272 isUtc = true;
273 if (match[9] != null) {
274 // timezone other than 'Z' and 'z'.
275 int sign = (match[9] == '-') ? -1 : 1;
276 int hourDifference = int.parse(match[10]);
277 int minuteDifference = parseIntOrZero(match[11]);
278 minuteDifference += 60 * hourDifference;
279 minute -= sign * minuteDifference;
280 }
281 }
256 int millisecondsSinceEpoch = _brokenDownDateToMillisecondsSinceEpoch( 282 int millisecondsSinceEpoch = _brokenDownDateToMillisecondsSinceEpoch(
257 years, month, day, hour, minute, second, millisecond, isUtc); 283 years, month, day, hour, minute, second, millisecond, isUtc);
258 if (millisecondsSinceEpoch == null) { 284 if (millisecondsSinceEpoch == null) {
259 throw new FormatException(formattedString); 285 throw new FormatException(formattedString);
260 } 286 }
261 if (addOneMillisecond) millisecondsSinceEpoch++; 287 if (addOneMillisecond) millisecondsSinceEpoch++;
262 return new DateTime.fromMillisecondsSinceEpoch(millisecondsSinceEpoch, 288 return new DateTime.fromMillisecondsSinceEpoch(millisecondsSinceEpoch,
263 isUtc: isUtc); 289 isUtc: isUtc);
264 } else { 290 } else {
265 throw new FormatException(formattedString); 291 throw new FormatException(formattedString);
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 /** 524 /**
499 * The abbreviated time zone name&mdash;for example, 525 * The abbreviated time zone name&mdash;for example,
500 * [:"CET":] or [:"CEST":]. 526 * [:"CET":] or [:"CEST":].
501 */ 527 */
502 external String get timeZoneName; 528 external String get timeZoneName;
503 529
504 /** 530 /**
505 * The time zone offset, which 531 * The time zone offset, which
506 * is the difference between local time and UTC. 532 * is the difference between local time and UTC.
507 * 533 *
508 * The offset is positive for time zones west of UTC. 534 * The offset is positive for time zones east of UTC.
floitsch 2014/02/17 10:37:38 oops.
509 * 535 *
510 * Note, that JavaScript, Python and C return the difference between UTC and 536 * Note, that JavaScript, Python and C return the difference between UTC and
511 * local time. Java, C# and Ruby return the difference between local time and 537 * local time. Java, C# and Ruby return the difference between local time and
512 * UTC. 538 * UTC.
513 */ 539 */
514 external Duration get timeZoneOffset; 540 external Duration get timeZoneOffset;
515 541
516 /** 542 /**
517 * The year. 543 * The year.
518 * 544 *
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
576 * In accordance with ISO 8601 602 * In accordance with ISO 8601
577 * a week starts with Monday, which has the value 1. 603 * a week starts with Monday, which has the value 1.
578 * 604 *
579 * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); 605 * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00");
580 * assert(moonLanding.weekday == 7); 606 * assert(moonLanding.weekday == 7);
581 * assert(moonLanding.weekday == DateTime.SUNDAY); 607 * assert(moonLanding.weekday == DateTime.SUNDAY);
582 * 608 *
583 */ 609 */
584 external int get weekday; 610 external int get weekday;
585 } 611 }
OLDNEW
« no previous file with comments | « no previous file | tests/corelib/date_time_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698