OLD | NEW |
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 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 static const int JUNE = 6; | 122 static const int JUNE = 6; |
123 static const int JULY = 7; | 123 static const int JULY = 7; |
124 static const int AUGUST = 8; | 124 static const int AUGUST = 8; |
125 static const int SEPTEMBER = 9; | 125 static const int SEPTEMBER = 9; |
126 static const int OCTOBER = 10; | 126 static const int OCTOBER = 10; |
127 static const int NOVEMBER = 11; | 127 static const int NOVEMBER = 11; |
128 static const int DECEMBER = 12; | 128 static const int DECEMBER = 12; |
129 static const int MONTHS_PER_YEAR = 12; | 129 static const int MONTHS_PER_YEAR = 12; |
130 | 130 |
131 /** | 131 /** |
132 * The number of milliseconds since | 132 * The value of this DateTime. |
133 * the "Unix epoch" 1970-01-01T00:00:00Z (UTC). | |
134 * | 133 * |
135 * This value is independent of the time zone. | 134 * The content of this field is implementation dependent. On JavaScript it is |
136 * | 135 * equal to [millisecondsSinceEpoch]. On the VM it is equal to |
137 * This value is at most | 136 * [microsecondsSinceEpoch]. |
138 * 8,640,000,000,000,000ms (100,000,000 days) from the Unix epoch. | |
139 * In other words: [:millisecondsSinceEpoch.abs() <= 8640000000000000:]. | |
140 * | |
141 */ | 137 */ |
142 final int millisecondsSinceEpoch; | 138 final int _value; |
143 | 139 |
144 /** | 140 /** |
145 * True if this [DateTime] is set to UTC time. | 141 * True if this [DateTime] is set to UTC time. |
146 * | 142 * |
147 * DateTime dDay = new DateTime.utc(1944, 6, 6); | 143 * DateTime dDay = new DateTime.utc(1944, 6, 6); |
148 * assert(dDay.isUtc); | 144 * assert(dDay.isUtc); |
149 * | 145 * |
150 */ | 146 */ |
151 final bool isUtc; | 147 final bool isUtc; |
152 | 148 |
153 /** | 149 /** |
154 * Constructs a [DateTime] instance specified in the local time zone. | 150 * Constructs a [DateTime] instance specified in the local time zone. |
155 * | 151 * |
156 * For example, | 152 * For example, |
157 * to create a new DateTime object representing April 29, 2014, 6:04am: | 153 * to create a new DateTime object representing April 29, 2014, 6:04am: |
158 * | 154 * |
159 * DateTime annularEclipse = new DateTime(2014, DateTime.APRIL, 29, 6, 4); | 155 * DateTime annularEclipse = new DateTime(2014, DateTime.APRIL, 29, 6, 4); |
160 */ | 156 */ |
161 DateTime(int year, | 157 DateTime(int year, |
162 [int month = 1, | 158 [int month = 1, |
163 int day = 1, | 159 int day = 1, |
164 int hour = 0, | 160 int hour = 0, |
165 int minute = 0, | 161 int minute = 0, |
166 int second = 0, | 162 int second = 0, |
167 int millisecond = 0]) | 163 int millisecond = 0, |
| 164 int microsecond = 0]) |
168 : this._internal( | 165 : this._internal( |
169 year, month, day, hour, minute, second, millisecond, false); | 166 year, month, day, hour, minute, second, millisecond, microsecond, |
| 167 false); |
170 | 168 |
171 /** | 169 /** |
172 * Constructs a [DateTime] instance specified in the UTC time zone. | 170 * Constructs a [DateTime] instance specified in the UTC time zone. |
173 * | 171 * |
174 * DateTime dDay = new DateTime.utc(1944, DateTime.JUNE, 6); | 172 * DateTime dDay = new DateTime.utc(1944, DateTime.JUNE, 6); |
175 */ | 173 */ |
176 DateTime.utc(int year, | 174 DateTime.utc(int year, |
177 [int month = 1, | 175 [int month = 1, |
178 int day = 1, | 176 int day = 1, |
179 int hour = 0, | 177 int hour = 0, |
180 int minute = 0, | 178 int minute = 0, |
181 int second = 0, | 179 int second = 0, |
182 int millisecond = 0]) | 180 int millisecond = 0, |
| 181 int microsecond = 0]) |
183 : this._internal( | 182 : this._internal( |
184 year, month, day, hour, minute, second, millisecond, true); | 183 year, month, day, hour, minute, second, millisecond, microsecond, |
| 184 true); |
185 | 185 |
186 /** | 186 /** |
187 * Constructs a [DateTime] instance with current date and time in the | 187 * Constructs a [DateTime] instance with current date and time in the |
188 * local time zone. | 188 * local time zone. |
189 * | 189 * |
190 * DateTime thisInstant = new DateTime.now(); | 190 * DateTime thisInstant = new DateTime.now(); |
191 * | 191 * |
192 */ | 192 */ |
193 DateTime.now() : this._now(); | 193 DateTime.now() : this._now(); |
194 | 194 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 * yeardate ::= year colon_opt month colon_opt day | 249 * yeardate ::= year colon_opt month colon_opt day |
250 * year ::= sign_opt digit{4,6} | 250 * year ::= sign_opt digit{4,6} |
251 * colon_opt :: <empty> | ':' | 251 * colon_opt :: <empty> | ':' |
252 * sign ::= '+' | '-' | 252 * sign ::= '+' | '-' |
253 * sign_opt ::= <empty> | sign | 253 * sign_opt ::= <empty> | sign |
254 * month ::= digit{2} | 254 * month ::= digit{2} |
255 * day ::= digit{2} | 255 * day ::= digit{2} |
256 * time_opt ::= <empty> | (' ' | 'T') hour minutes_opt | 256 * time_opt ::= <empty> | (' ' | 'T') hour minutes_opt |
257 * minutes_opt ::= <empty> | colon_opt digit{2} seconds_opt | 257 * minutes_opt ::= <empty> | colon_opt digit{2} seconds_opt |
258 * seconds_opt ::= <empty> | colon_opt digit{2} millis_opt | 258 * seconds_opt ::= <empty> | colon_opt digit{2} millis_opt |
259 * millis_opt ::= <empty> | '.' digit{1,6} | 259 * micros_opt ::= <empty> | '.' digit{1,6} |
260 * timezone_opt ::= <empty> | space_opt timezone | 260 * timezone_opt ::= <empty> | space_opt timezone |
261 * space_opt :: ' ' | <empty> | 261 * space_opt :: ' ' | <empty> |
262 * timezone ::= 'z' | 'Z' | sign digit{2} timezonemins_opt | 262 * timezone ::= 'z' | 'Z' | sign digit{2} timezonemins_opt |
263 * timezonemins_opt ::= <empty> | colon_opt digit{2} | 263 * timezonemins_opt ::= <empty> | colon_opt digit{2} |
264 */ | 264 */ |
265 final RegExp re = new RegExp( | 265 final RegExp re = new RegExp( |
266 r'^([+-]?\d{4,6})-?(\d\d)-?(\d\d)' // Day part. | 266 r'^([+-]?\d{4,6})-?(\d\d)-?(\d\d)' // Day part. |
267 r'(?:[ T](\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d{1,6}))?)?)?' // Time part. | 267 r'(?:[ T](\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d{1,6}))?)?)?' // Time part. |
268 r'( ?[zZ]| ?([-+])(\d\d)(?::?(\d\d))?)?)?$'); // Timezone part. | 268 r'( ?[zZ]| ?([-+])(\d\d)(?::?(\d\d))?)?)?$'); // Timezone part. |
269 | 269 |
270 Match match = re.firstMatch(formattedString); | 270 Match match = re.firstMatch(formattedString); |
271 if (match != null) { | 271 if (match != null) { |
272 int parseIntOrZero(String matched) { | 272 int parseIntOrZero(String matched) { |
273 if (matched == null) return 0; | 273 if (matched == null) return 0; |
274 return int.parse(matched); | 274 return int.parse(matched); |
275 } | 275 } |
276 | 276 |
277 // Parses fractional second digits of '.(\d{1,6})' into milliseconds. | 277 // Parses fractional second digits of '.(\d{1,6})' into the combined |
278 // Uses first three digits (assumed to be zero if not there), and | 278 // microseconds. |
279 // rounds up if fourth digit is 5 or greater. | 279 int parseMilliAndMicroseconds(String matched) { |
280 // Should be equivalent to `(double.parse(".$matchd")*1000).round()`. | |
281 int parseMilliseconds(String matched) { | |
282 if (matched == null) return 0; | 280 if (matched == null) return 0; |
283 int length = matched.length; | 281 int length = matched.length; |
284 assert(length >= 1); | 282 assert(length >= 1); |
285 assert(length <= 6); | 283 assert(length <= 6); |
286 | 284 |
287 int result = (matched.codeUnitAt(0) ^ 0x30); | 285 int result = 0; |
288 if (length <= 3) { | 286 for (int i = 0; i < 6; i++) { |
289 int i = 1; | 287 result *= 10; |
290 while (i < length) { | 288 if (i < matched.length) { |
291 result *= 10; | |
292 result += matched.codeUnitAt(i) ^ 0x30; | 289 result += matched.codeUnitAt(i) ^ 0x30; |
293 i++; | |
294 } | 290 } |
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 } | 291 } |
307 return result; | 292 return result; |
308 } | 293 } |
309 | 294 |
310 int years = int.parse(match[1]); | 295 int years = int.parse(match[1]); |
311 int month = int.parse(match[2]); | 296 int month = int.parse(match[2]); |
312 int day = int.parse(match[3]); | 297 int day = int.parse(match[3]); |
313 int hour = parseIntOrZero(match[4]); | 298 int hour = parseIntOrZero(match[4]); |
314 int minute = parseIntOrZero(match[5]); | 299 int minute = parseIntOrZero(match[5]); |
315 int second = parseIntOrZero(match[6]); | 300 int second = parseIntOrZero(match[6]); |
316 bool addOneMillisecond = false; | 301 bool addOneMillisecond = false; |
317 int millisecond = parseMilliseconds(match[7]); | 302 int milliAndMicroseconds = parseMilliAndMicroseconds(match[7]); |
318 if (millisecond == 1000) { | 303 int millisecond = |
319 addOneMillisecond = true; | 304 milliAndMicroseconds ~/ Duration.MICROSECONDS_PER_MILLISECOND; |
320 millisecond = 999; | 305 int microsecond = |
321 } | 306 milliAndMicroseconds.remainder(Duration.MICROSECONDS_PER_MILLISECOND); |
322 bool isUtc = false; | 307 bool isUtc = false; |
323 if (match[8] != null) { // timezone part | 308 if (match[8] != null) { // timezone part |
324 isUtc = true; | 309 isUtc = true; |
325 if (match[9] != null) { | 310 if (match[9] != null) { |
326 // timezone other than 'Z' and 'z'. | 311 // timezone other than 'Z' and 'z'. |
327 int sign = (match[9] == '-') ? -1 : 1; | 312 int sign = (match[9] == '-') ? -1 : 1; |
328 int hourDifference = int.parse(match[10]); | 313 int hourDifference = int.parse(match[10]); |
329 int minuteDifference = parseIntOrZero(match[11]); | 314 int minuteDifference = parseIntOrZero(match[11]); |
330 minuteDifference += 60 * hourDifference; | 315 minuteDifference += 60 * hourDifference; |
331 minute -= sign * minuteDifference; | 316 minute -= sign * minuteDifference; |
332 } | 317 } |
333 } | 318 } |
334 int millisecondsSinceEpoch = _brokenDownDateToMillisecondsSinceEpoch( | 319 int value = _brokenDownDateToValue( |
335 years, month, day, hour, minute, second, millisecond, isUtc); | 320 years, month, day, hour, minute, second, millisecond, microsecond, |
336 if (millisecondsSinceEpoch == null) { | 321 isUtc); |
| 322 if (value == null) { |
337 throw new FormatException("Time out of range", formattedString); | 323 throw new FormatException("Time out of range", formattedString); |
338 } | 324 } |
339 if (addOneMillisecond) millisecondsSinceEpoch++; | 325 return new DateTime._withValue(value, isUtc: isUtc); |
340 return new DateTime.fromMillisecondsSinceEpoch(millisecondsSinceEpoch, | |
341 isUtc: isUtc); | |
342 } else { | 326 } else { |
343 throw new FormatException("Invalid date format", formattedString); | 327 throw new FormatException("Invalid date format", formattedString); |
344 } | 328 } |
345 } | 329 } |
346 | 330 |
347 static const int _MAX_MILLISECONDS_SINCE_EPOCH = 8640000000000000; | 331 static const int _MAX_MILLISECONDS_SINCE_EPOCH = 8640000000000000; |
348 | 332 |
349 /** | 333 /** |
350 * Constructs a new [DateTime] instance | 334 * Constructs a new [DateTime] instance |
351 * with the given [millisecondsSinceEpoch]. | 335 * with the given [millisecondsSinceEpoch]. |
352 * | 336 * |
353 * If [isUtc] is false then the date is in the local time zone. | 337 * If [isUtc] is false then the date is in the local time zone. |
354 * | 338 * |
355 * The constructed [DateTime] represents | 339 * The constructed [DateTime] represents |
356 * 1970-01-01T00:00:00Z + [millisecondsSinceEpoch] ms in the given | 340 * 1970-01-01T00:00:00Z + [millisecondsSinceEpoch] ms in the given |
357 * time zone (local or UTC). | 341 * time zone (local or UTC). |
358 */ | 342 */ |
359 DateTime.fromMillisecondsSinceEpoch(int millisecondsSinceEpoch, | 343 external DateTime.fromMillisecondsSinceEpoch(int millisecondsSinceEpoch, |
360 {bool isUtc: false}) | 344 {bool isUtc: false}); |
361 : this.millisecondsSinceEpoch = millisecondsSinceEpoch, | 345 |
362 this.isUtc = isUtc { | 346 /** |
363 if (millisecondsSinceEpoch.abs() > _MAX_MILLISECONDS_SINCE_EPOCH) { | 347 * Constructs a new [DateTime] instance |
| 348 * with the given [microsecondsSinceEpoch]. |
| 349 * |
| 350 * If [isUtc] is false then the date is in the local time zone. |
| 351 * |
| 352 * The constructed [DateTime] represents |
| 353 * 1970-01-01T00:00:00Z + [microsecondsSinceEpoch] us in the given |
| 354 * time zone (local or UTC). |
| 355 */ |
| 356 external DateTime.fromMicrosecondsSinceEpoch(int microsecondsSinceEpoch, |
| 357 {bool isUtc: false}); |
| 358 |
| 359 /** |
| 360 * Constructs a new [DateTime] instance with the given value. |
| 361 * |
| 362 * If [isUtc] is false then the date is in the local time zone. |
| 363 */ |
| 364 DateTime._withValue(this._value, {this.isUtc}) { |
| 365 if (millisecondsSinceEpoch.abs() > _MAX_MILLISECONDS_SINCE_EPOCH || |
| 366 (millisecondsSinceEpoch.abs() == _MAX_MILLISECONDS_SINCE_EPOCH && |
| 367 microsecond != 0)) { |
364 throw new ArgumentError(millisecondsSinceEpoch); | 368 throw new ArgumentError(millisecondsSinceEpoch); |
365 } | 369 } |
366 if (isUtc == null) throw new ArgumentError(isUtc); | 370 if (isUtc == null) throw new ArgumentError(isUtc); |
367 } | 371 } |
368 | 372 |
369 /** | 373 /** |
370 * Returns true if [other] is a [DateTime] at the same moment and in the | 374 * Returns true if [other] is a [DateTime] at the same moment and in the |
371 * same time zone (UTC or local). | 375 * same time zone (UTC or local). |
372 * | 376 * |
373 * DateTime dDayUtc = new DateTime.utc(1944, DateTime.JUNE, 6); | 377 * DateTime dDayUtc = new DateTime.utc(1944, DateTime.JUNE, 6); |
374 * DateTime dDayLocal = new DateTime(1944, DateTime.JUNE, 6); | 378 * DateTime dDayLocal = new DateTime(1944, DateTime.JUNE, 6); |
375 * | 379 * |
376 * assert(dDayUtc.isAtSameMomentAs(dDayLocal) == false); | 380 * assert(dDayUtc.isAtSameMomentAs(dDayLocal) == false); |
377 * | 381 * |
378 * See [isAtSameMomentAs] for a comparison that adjusts for time zone. | 382 * See [isAtSameMomentAs] for a comparison that adjusts for time zone. |
379 */ | 383 */ |
380 bool operator ==(other) { | 384 bool operator ==(other) { |
381 if (!(other is DateTime)) return false; | 385 if (!(other is DateTime)) return false; |
382 return (millisecondsSinceEpoch == other.millisecondsSinceEpoch && | 386 return (_value == other._value && isUtc == other.isUtc); |
383 isUtc == other.isUtc); | |
384 } | 387 } |
385 | 388 |
386 /** | 389 /** |
387 * Returns true if [this] occurs before [other]. | 390 * Returns true if [this] occurs before [other]. |
388 * | 391 * |
389 * The comparison is independent | 392 * The comparison is independent |
390 * of whether the time is in UTC or in the local time zone. | 393 * of whether the time is in UTC or in the local time zone. |
391 * | 394 * |
392 * DateTime berlinWallFell = new DateTime(1989, 11, 9); | 395 * DateTime berlinWallFell = new DateTime(1989, 11, 9); |
393 * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); | 396 * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); |
394 * | 397 * |
395 * assert(berlinWallFell.isBefore(moonLanding) == false); | 398 * assert(berlinWallFell.isBefore(moonLanding) == false); |
396 * | 399 * |
397 */ | 400 */ |
398 bool isBefore(DateTime other) { | 401 bool isBefore(DateTime other) { |
399 return millisecondsSinceEpoch < other.millisecondsSinceEpoch; | 402 return _value < other._value; |
400 } | 403 } |
401 | 404 |
402 /** | 405 /** |
403 * Returns true if [this] occurs after [other]. | 406 * Returns true if [this] occurs after [other]. |
404 * | 407 * |
405 * The comparison is independent | 408 * The comparison is independent |
406 * of whether the time is in UTC or in the local time zone. | 409 * of whether the time is in UTC or in the local time zone. |
407 * | 410 * |
408 * DateTime berlinWallFell = new DateTime(1989, 11, 9); | 411 * DateTime berlinWallFell = new DateTime(1989, 11, 9); |
409 * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); | 412 * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); |
410 * | 413 * |
411 * assert(berlinWallFell.isAfter(moonLanding) == true); | 414 * assert(berlinWallFell.isAfter(moonLanding) == true); |
412 * | 415 * |
413 */ | 416 */ |
414 bool isAfter(DateTime other) { | 417 bool isAfter(DateTime other) { |
415 return millisecondsSinceEpoch > other.millisecondsSinceEpoch; | 418 return _value > other._value; |
416 } | 419 } |
417 | 420 |
418 /** | 421 /** |
419 * Returns true if [this] occurs at the same moment as [other]. | 422 * Returns true if [this] occurs at the same moment as [other]. |
420 * | 423 * |
421 * The comparison is independent of whether the time is in UTC or in the local | 424 * The comparison is independent of whether the time is in UTC or in the local |
422 * time zone. | 425 * time zone. |
423 * | 426 * |
424 * DateTime berlinWallFell = new DateTime(1989, 11, 9); | 427 * DateTime berlinWallFell = new DateTime(1989, 11, 9); |
425 * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); | 428 * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); |
426 * | 429 * |
427 * assert(berlinWallFell.isAtSameMomentAs(moonLanding) == false); | 430 * assert(berlinWallFell.isAtSameMomentAs(moonLanding) == false); |
428 */ | 431 */ |
429 bool isAtSameMomentAs(DateTime other) { | 432 bool isAtSameMomentAs(DateTime other) { |
430 return millisecondsSinceEpoch == other.millisecondsSinceEpoch; | 433 return _value == other._value; |
431 } | 434 } |
432 | 435 |
433 /** | 436 /** |
434 * Compares this DateTime object to [other], | 437 * Compares this DateTime object to [other], |
435 * returning zero if the values are equal. | 438 * returning zero if the values are equal. |
436 * | 439 * |
437 * This function returns a negative integer | 440 * This function returns a negative integer |
438 * if this DateTime is smaller (earlier) than [other], | 441 * if this DateTime is smaller (earlier) than [other], |
439 * or a positive integer if it is greater (later). | 442 * or a positive integer if it is greater (later). |
440 */ | 443 */ |
441 int compareTo(DateTime other) | 444 int compareTo(DateTime other) => _value.compareTo(other._value); |
442 => millisecondsSinceEpoch.compareTo(other.millisecondsSinceEpoch); | |
443 | 445 |
444 int get hashCode => millisecondsSinceEpoch; | 446 int get hashCode => (_value ^ (_value >> 30)) & 0x3FFFFFFF; |
445 | 447 |
446 /** | 448 /** |
447 * Returns this DateTime value in the local time zone. | 449 * Returns this DateTime value in the local time zone. |
448 * | 450 * |
449 * Returns [this] if it is already in the local time zone. | 451 * Returns [this] if it is already in the local time zone. |
450 * Otherwise this method is equivalent to: | 452 * Otherwise this method is equivalent to: |
451 * | 453 * |
452 * new DateTime.fromMillisecondsSinceEpoch(millisecondsSinceEpoch, | 454 * new DateTime.fromMicrosecondsSinceEpoch(microsecondsSinceEpoch, |
453 * isUtc: false) | 455 * isUtc: false) |
454 */ | 456 */ |
455 DateTime toLocal() { | 457 DateTime toLocal() { |
456 if (isUtc) { | 458 if (isUtc) { |
457 return new DateTime.fromMillisecondsSinceEpoch(millisecondsSinceEpoch, | 459 return new DateTime._withValue(_value, isUtc: false); |
458 isUtc: false); | |
459 } | 460 } |
460 return this; | 461 return this; |
461 } | 462 } |
462 | 463 |
463 /** | 464 /** |
464 * Returns this DateTime value in the UTC time zone. | 465 * Returns this DateTime value in the UTC time zone. |
465 * | 466 * |
466 * Returns [this] if it is already in UTC. | 467 * Returns [this] if it is already in UTC. |
467 * Otherwise this method is equivalent to: | 468 * Otherwise this method is equivalent to: |
468 * | 469 * |
469 * new DateTime.fromMillisecondsSinceEpoch(millisecondsSinceEpoch, | 470 * new DateTime.fromMicrosecondsSinceEpoch(microsecondsSinceEpoch, |
470 * isUtc: true) | 471 * isUtc: true) |
471 */ | 472 */ |
472 DateTime toUtc() { | 473 DateTime toUtc() { |
473 if (isUtc) return this; | 474 if (isUtc) return this; |
474 return new DateTime.fromMillisecondsSinceEpoch(millisecondsSinceEpoch, | 475 return new DateTime._withValue(_value, isUtc: true); |
475 isUtc: true); | |
476 } | 476 } |
477 | 477 |
478 static String _fourDigits(int n) { | 478 static String _fourDigits(int n) { |
479 int absN = n.abs(); | 479 int absN = n.abs(); |
480 String sign = n < 0 ? "-" : ""; | 480 String sign = n < 0 ? "-" : ""; |
481 if (absN >= 1000) return "$n"; | 481 if (absN >= 1000) return "$n"; |
482 if (absN >= 100) return "${sign}0$absN"; | 482 if (absN >= 100) return "${sign}0$absN"; |
483 if (absN >= 10) return "${sign}00$absN"; | 483 if (absN >= 10) return "${sign}00$absN"; |
484 return "${sign}000$absN"; | 484 return "${sign}000$absN"; |
485 } | 485 } |
(...skipping 29 matching lines...) Expand all Loading... |
515 * The resulting string can be parsed back using [parse]. | 515 * The resulting string can be parsed back using [parse]. |
516 */ | 516 */ |
517 String toString() { | 517 String toString() { |
518 String y = _fourDigits(year); | 518 String y = _fourDigits(year); |
519 String m = _twoDigits(month); | 519 String m = _twoDigits(month); |
520 String d = _twoDigits(day); | 520 String d = _twoDigits(day); |
521 String h = _twoDigits(hour); | 521 String h = _twoDigits(hour); |
522 String min = _twoDigits(minute); | 522 String min = _twoDigits(minute); |
523 String sec = _twoDigits(second); | 523 String sec = _twoDigits(second); |
524 String ms = _threeDigits(millisecond); | 524 String ms = _threeDigits(millisecond); |
| 525 String us = microsecond == 0 ? "" : _threeDigits(microsecond); |
525 if (isUtc) { | 526 if (isUtc) { |
526 return "$y-$m-$d $h:$min:$sec.${ms}Z"; | 527 return "$y-$m-$d $h:$min:$sec.$ms${us}Z"; |
527 } else { | 528 } else { |
528 return "$y-$m-$d $h:$min:$sec.$ms"; | 529 return "$y-$m-$d $h:$min:$sec.$ms$us"; |
529 } | 530 } |
530 } | 531 } |
531 | 532 |
532 /** | 533 /** |
533 * Returns an ISO-8601 full-precision extended format representation. | 534 * Returns an ISO-8601 full-precision extended format representation. |
534 * | 535 * |
535 * The format is `yyyy-MM-ddTHH:mm:ss.sssZ` for UTC time, and | 536 * The format is `yyyy-MM-ddTHH:mm:ss.mmmuuuZ` for UTC time, and |
536 * `yyyy-MM-ddTHH:mm:ss.sss` (no trailing "Z") for local/non-UTC time, | 537 * `yyyy-MM-ddTHH:mm:ss.mmmuuu` (no trailing "Z") for local/non-UTC time, |
537 * where: | 538 * where: |
538 * | 539 * |
539 * * `yyyy` is a, possibly negative, four digit representation of the year, | 540 * * `yyyy` is a, possibly negative, four digit representation of the year, |
540 * if the year is in the range -9999 to 9999, | 541 * if the year is in the range -9999 to 9999, |
541 * otherwise it is a signed six digit representation of the year. | 542 * otherwise it is a signed six digit representation of the year. |
542 * * `MM` is the month in the range 01 to 12, | 543 * * `MM` is the month in the range 01 to 12, |
543 * * `dd` is the day of the month in the range 01 to 31, | 544 * * `dd` is the day of the month in the range 01 to 31, |
544 * * `HH` are hours in the range 00 to 23, | 545 * * `HH` are hours in the range 00 to 23, |
545 * * `mm` are minutes in the range 00 to 59, | 546 * * `mm` are minutes in the range 00 to 59, |
546 * * `ss` are seconds in the range 00 to 59 (no leap seconds), and | 547 * * `ss` are seconds in the range 00 to 59 (no leap seconds), |
547 * * `sss` are milliseconds in the range 000 to 999. | 548 * * `mmm` are microseconds in the range 000 to 999, and |
| 549 * * `uuu` are microseconds in the range 001 to 999. If [microsecond] equals |
| 550 * 0, then this part is omitted. |
548 * | 551 * |
549 * The resulting string can be parsed back using [parse]. | 552 * The resulting string can be parsed back using [parse]. |
550 */ | 553 */ |
551 String toIso8601String() { | 554 String toIso8601String() { |
552 String y = (year >= -9999 && year <= 9999) ? _fourDigits(year) | 555 String y = (year >= -9999 && year <= 9999) ? _fourDigits(year) |
553 : _sixDigits(year); | 556 : _sixDigits(year); |
554 String m = _twoDigits(month); | 557 String m = _twoDigits(month); |
555 String d = _twoDigits(day); | 558 String d = _twoDigits(day); |
556 String h = _twoDigits(hour); | 559 String h = _twoDigits(hour); |
557 String min = _twoDigits(minute); | 560 String min = _twoDigits(minute); |
558 String sec = _twoDigits(second); | 561 String sec = _twoDigits(second); |
559 String ms = _threeDigits(millisecond); | 562 String ms = _threeDigits(millisecond); |
| 563 String us = microsecond == 0 ? "" : _threeDigits(microsecond); |
560 if (isUtc) { | 564 if (isUtc) { |
561 return "$y-$m-${d}T$h:$min:$sec.${ms}Z"; | 565 return "$y-$m-${d}T$h:$min:$sec.$ms${us}Z"; |
562 } else { | 566 } else { |
563 return "$y-$m-${d}T$h:$min:$sec.$ms"; | 567 return "$y-$m-${d}T$h:$min:$sec.$ms$us"; |
564 } | 568 } |
565 } | 569 } |
566 | 570 |
567 /** | 571 /** |
568 * Returns a new [DateTime] instance with [duration] added to [this]. | 572 * Returns a new [DateTime] instance with [duration] added to [this]. |
569 * | 573 * |
570 * DateTime today = new DateTime.now(); | 574 * DateTime today = new DateTime.now(); |
571 * DateTime sixtyDaysFromNow = today.add(new Duration(days: 60)); | 575 * DateTime sixtyDaysFromNow = today.add(new Duration(days: 60)); |
572 */ | 576 */ |
573 DateTime add(Duration duration) { | 577 external DateTime add(Duration duration); |
574 int ms = millisecondsSinceEpoch; | |
575 return new DateTime.fromMillisecondsSinceEpoch( | |
576 ms + duration.inMilliseconds, isUtc: isUtc); | |
577 } | |
578 | 578 |
579 /** | 579 /** |
580 * Returns a new [DateTime] instance with [duration] subtracted from [this]. | 580 * Returns a new [DateTime] instance with [duration] subtracted from [this]. |
581 * | 581 * |
582 * DateTime today = new DateTime.now(); | 582 * DateTime today = new DateTime.now(); |
583 * DateTime sixtyDaysAgo = today.subtract(new Duration(days: 60)); | 583 * DateTime sixtyDaysAgo = today.subtract(new Duration(days: 60)); |
584 */ | 584 */ |
585 DateTime subtract(Duration duration) { | 585 external DateTime subtract(Duration duration); |
586 int ms = millisecondsSinceEpoch; | |
587 return new DateTime.fromMillisecondsSinceEpoch( | |
588 ms - duration.inMilliseconds, isUtc: isUtc); | |
589 } | |
590 | 586 |
591 /** | 587 /** |
592 * Returns a [Duration] with the difference between [this] and [other]. | 588 * Returns a [Duration] with the difference between [this] and [other]. |
593 * | 589 * |
594 * DateTime berlinWallFell = new DateTime(1989, DateTime.NOVEMBER, 9); | 590 * DateTime berlinWallFell = new DateTime(1989, DateTime.NOVEMBER, 9); |
595 * DateTime dDay = new DateTime(1944, DateTime.JUNE, 6); | 591 * DateTime dDay = new DateTime(1944, DateTime.JUNE, 6); |
596 * | 592 * |
597 * Duration difference = berlinWallFell.difference(dDay); | 593 * Duration difference = berlinWallFell.difference(dDay); |
598 * assert(difference.inDays == 16592); | 594 * assert(difference.inDays == 16592); |
599 */ | 595 */ |
600 | 596 external Duration difference(DateTime other); |
601 Duration difference(DateTime other) { | |
602 int ms = millisecondsSinceEpoch; | |
603 int otherMs = other.millisecondsSinceEpoch; | |
604 return new Duration(milliseconds: ms - otherMs); | |
605 } | |
606 | 597 |
607 external DateTime._internal(int year, | 598 external DateTime._internal(int year, |
608 int month, | 599 int month, |
609 int day, | 600 int day, |
610 int hour, | 601 int hour, |
611 int minute, | 602 int minute, |
612 int second, | 603 int second, |
613 int millisecond, | 604 int millisecond, |
| 605 int microsecond, |
614 bool isUtc); | 606 bool isUtc); |
| 607 |
615 external DateTime._now(); | 608 external DateTime._now(); |
616 /// Returns the time as milliseconds since epoch, or null if the | 609 |
617 /// values are out of range. | 610 /// Returns the time as value (millisecond or microsecond since epoch), or |
618 external static int _brokenDownDateToMillisecondsSinceEpoch( | 611 /// null if the values are out of range. |
| 612 external static int _brokenDownDateToValue( |
619 int year, int month, int day, int hour, int minute, int second, | 613 int year, int month, int day, int hour, int minute, int second, |
620 int millisecond, bool isUtc); | 614 int millisecond, int microsecond, bool isUtc); |
| 615 |
| 616 /** |
| 617 * The number of milliseconds since |
| 618 * the "Unix epoch" 1970-01-01T00:00:00Z (UTC). |
| 619 * |
| 620 * This value is independent of the time zone. |
| 621 * |
| 622 * This value is at most |
| 623 * 8,640,000,000,000,000ms (100,000,000 days) from the Unix epoch. |
| 624 * In other words: `millisecondsSinceEpoch.abs() <= 8640000000000000`. |
| 625 */ |
| 626 external int get millisecondsSinceEpoch; |
| 627 |
| 628 /** |
| 629 * The number of microseconds since |
| 630 * the "Unix epoch" 1970-01-01T00:00:00Z (UTC). |
| 631 * |
| 632 * This value is independent of the time zone. |
| 633 * |
| 634 * This value is at most |
| 635 * 8,640,000,000,000,000,000us (100,000,000 days) from the Unix epoch. |
| 636 * In other words: `microsecondsSinceEpoch.abs() <= 8640000000000000000`. |
| 637 * |
| 638 * Note that this value does not fit into 53 bits (the size of a IEEE double). |
| 639 * A JavaScript number is not able to hold this value. |
| 640 */ |
| 641 external int get microsecondsSinceEpoch; |
621 | 642 |
622 /** | 643 /** |
623 * The abbreviated time zone name—for example, | 644 * The abbreviated time zone name—for example, |
624 * [:"CET":] or [:"CEST":]. | 645 * [:"CET":] or [:"CEST":]. |
625 */ | 646 */ |
626 external String get timeZoneName; | 647 external String get timeZoneName; |
627 | 648 |
628 /** | 649 /** |
629 * The time zone offset, which | 650 * The time zone offset, which |
630 * is the difference between local time and UTC. | 651 * is the difference between local time and UTC. |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
688 | 709 |
689 /** | 710 /** |
690 * The millisecond [0...999]. | 711 * The millisecond [0...999]. |
691 * | 712 * |
692 * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); | 713 * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); |
693 * assert(moonLanding.millisecond == 0); | 714 * assert(moonLanding.millisecond == 0); |
694 */ | 715 */ |
695 external int get millisecond; | 716 external int get millisecond; |
696 | 717 |
697 /** | 718 /** |
| 719 * The microsecond [0...999]. |
| 720 * |
| 721 * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); |
| 722 * assert(moonLanding.microsecond == 0); |
| 723 */ |
| 724 external int get microsecond; |
| 725 |
| 726 /** |
698 * The day of the week [MONDAY]..[SUNDAY]. | 727 * The day of the week [MONDAY]..[SUNDAY]. |
699 * | 728 * |
700 * In accordance with ISO 8601 | 729 * In accordance with ISO 8601 |
701 * a week starts with Monday, which has the value 1. | 730 * a week starts with Monday, which has the value 1. |
702 * | 731 * |
703 * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); | 732 * DateTime moonLanding = DateTime.parse("1969-07-20 20:18:00"); |
704 * assert(moonLanding.weekday == 7); | 733 * assert(moonLanding.weekday == 7); |
705 * assert(moonLanding.weekday == DateTime.SUNDAY); | 734 * assert(moonLanding.weekday == DateTime.SUNDAY); |
706 * | 735 * |
707 */ | 736 */ |
708 external int get weekday; | 737 external int get weekday; |
709 } | 738 } |
OLD | NEW |