| 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 |