Skip to content

Commit

Permalink
[dart:core] Update DartTime.parse to support arbitrary precision frac…
Browse files Browse the repository at this point in the history
…tional seconds.

Update DartTime.parse to support arbitrary precision fractional seconds. So it now conforms to ISO8901 and RFC3339 standards.

Closes #24205

Closes #39350
dart-lang/sdk#39350

GitOrigin-RevId: 66f15b6e646a65b7955c7b617647b8edfd680481
Change-Id: Ife2211e6cce5922b59cdde0d30ed3ef887cffcf9
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/124903
Reviewed-by: Lasse R.H. Nielsen <lrn@google.com>
Commit-Queue: Alexander Thomas <athom@google.com>
  • Loading branch information
slightfoot authored and commit-bot@chromium.org committed Nov 20, 2019
1 parent ae34d6e commit 867a6e0
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 25 deletions.
19 changes: 9 additions & 10 deletions sdk/lib/core/date_time.dart
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,8 @@ class DateTime implements Comparable<DateTime> {
* The time part is a two digit hour,
* then optionally a two digit minutes value,
* then optionally a two digit seconds value, and
* then optionally a '.' or ',' followed by a one-to-six digit second fraction.
* then optionally a '.' or ',' followed by at least a one digit
* second fraction.
* The minutes and seconds may be separated from the previous parts by a
* ':'.
* Examples: "12", "12:30:24.124", "12:30:24,124", "123010.50".
Expand All @@ -263,8 +264,8 @@ class DateTime implements Comparable<DateTime> {
* Examples of accepted strings:
*
* * `"2012-02-27 13:27:00"`
* * `"2012-02-27 13:27:00.123456z"`
* * `"2012-02-27 13:27:00,123456z"`
* * `"2012-02-27 13:27:00.123456789z"`
* * `"2012-02-27 13:27:00,123456789z"`
* * `"20120227 13:27:00"`
* * `"20120227T132700"`
* * `"20120227"`
Expand All @@ -285,14 +286,13 @@ class DateTime implements Comparable<DateTime> {
return int.parse(matched);
}

// Parses fractional second digits of '.(\d{1,6})' into the combined
// microseconds.
// Parses fractional second digits of '.(\d+)' into the combined
// microseconds. We only use the first 6 digits because of DateTime
// precision of 999 milliseconds and 999 microseconds.
int parseMilliAndMicroseconds(String matched) {
if (matched == null) return 0;
int length = matched.length;
assert(length >= 1);
assert(length <= 6);

int result = 0;
for (int i = 0; i < 6; i++) {
result *= 10;
Expand All @@ -309,7 +309,6 @@ class DateTime implements Comparable<DateTime> {
int hour = parseIntOrZero(match[4]);
int minute = parseIntOrZero(match[5]);
int second = parseIntOrZero(match[6]);
bool addOneMillisecond = false;
int milliAndMicroseconds = parseMilliAndMicroseconds(match[7]);
int millisecond =
milliAndMicroseconds ~/ Duration.microsecondsPerMillisecond;
Expand Down Expand Up @@ -862,14 +861,14 @@ class DateTime implements Comparable<DateTime> {
* time_opt ::= <empty> | (' ' | 'T') hour minutes_opt
* minutes_opt ::= <empty> | colon_opt digit{2} seconds_opt
* seconds_opt ::= <empty> | colon_opt digit{2} millis_opt
* micros_opt ::= <empty> | ('.' | ',') digit{1,6}
* micros_opt ::= <empty> | ('.' | ',') digit+
* timezone_opt ::= <empty> | space_opt timezone
* space_opt :: ' ' | <empty>
* timezone ::= 'z' | 'Z' | sign digit{2} timezonemins_opt
* timezonemins_opt ::= <empty> | colon_opt digit{2}
*/
static final RegExp _parseFormat = RegExp(
r'^([+-]?\d{4,6})-?(\d\d)-?(\d\d)' // Day part.
r'(?:[ T](\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d{1,6}))?)?)?' // Time part.
r'(?:[ T](\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d+))?)?)?' // Time part.
r'( ?[zZ]| ?([-+])(\d\d)(?::?(\d\d))?)?)?$'); // Timezone part.
}
18 changes: 9 additions & 9 deletions sdk_nnbd/lib/core/date_time.dart
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,8 @@ class DateTime implements Comparable<DateTime> {
* The time part is a two digit hour,
* then optionally a two digit minutes value,
* then optionally a two digit seconds value, and
* then optionally a '.' or ',' followed by a one-to-six digit second fraction.
* then optionally a '.' or ',' followed by at least a one digit
* second fraction.
* The minutes and seconds may be separated from the previous parts by a
* ':'.
* Examples: "12", "12:30:24.124", "12:30:24,124", "123010.50".
Expand All @@ -261,8 +262,8 @@ class DateTime implements Comparable<DateTime> {
* Examples of accepted strings:
*
* * `"2012-02-27 13:27:00"`
* * `"2012-02-27 13:27:00.123456z"`
* * `"2012-02-27 13:27:00,123456z"`
* * `"2012-02-27 13:27:00.123456789z"`
* * `"2012-02-27 13:27:00,123456789z"`
* * `"20120227 13:27:00"`
* * `"20120227T132700"`
* * `"20120227"`
Expand All @@ -283,14 +284,13 @@ class DateTime implements Comparable<DateTime> {
return int.parse(matched);
}

// Parses fractional second digits of '.(\d{1,6})' into the combined
// microseconds.
// Parses fractional second digits of '.(\d+)' into the combined
// microseconds. We only use the first 6 digits because of DateTime
// precision of 999 milliseconds and 999 microseconds.
int parseMilliAndMicroseconds(String? matched) {
if (matched == null) return 0;
int length = matched.length;
assert(length >= 1);
assert(length <= 6);

int result = 0;
for (int i = 0; i < 6; i++) {
result *= 10;
Expand Down Expand Up @@ -857,14 +857,14 @@ class DateTime implements Comparable<DateTime> {
* time_opt ::= <empty> | (' ' | 'T') hour minutes_opt
* minutes_opt ::= <empty> | colon_opt digit{2} seconds_opt
* seconds_opt ::= <empty> | colon_opt digit{2} millis_opt
* micros_opt ::= <empty> | ('.' | ',') digit{1,6}
* micros_opt ::= <empty> | ('.' | ',') digit+
* timezone_opt ::= <empty> | space_opt timezone
* space_opt :: ' ' | <empty>
* timezone ::= 'z' | 'Z' | sign digit{2} timezonemins_opt
* timezonemins_opt ::= <empty> | colon_opt digit{2}
*/
static final RegExp _parseFormat = RegExp(
r'^([+-]?\d{4,6})-?(\d\d)-?(\d\d)' // Day part.
r'(?:[ T](\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d{1,6}))?)?)?' // Time part.
r'(?:[ T](\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d+))?)?)?' // Time part.
r'( ?[zZ]| ?([-+])(\d\d)(?::?(\d\d))?)?)?$'); // Timezone part.
}
12 changes: 6 additions & 6 deletions tests/corelib_2/date_time_parse_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ main() {
check(new DateTime(2012, 02, 27, 13, 27), "2012-02-27 13:27:00");
if (supportsMicroseconds) {
check(new DateTime.utc(2012, 02, 27, 13, 27, 0, 123, 456),
"2012-02-27 13:27:00.123456z");
"2012-02-27 13:27:00.1234567891234z");
check(new DateTime.utc(2012, 02, 27, 13, 27, 0, 123, 456),
"2012-02-27 13:27:00,123456z");
"2012-02-27 13:27:00,1234567891234z");
} else {
check(new DateTime.utc(2012, 02, 27, 13, 27, 0, 123, 456),
"2012-02-27 13:27:00.123z");
check(new DateTime.utc(2012, 02, 27, 13, 27, 0, 123, 456),
"2012-02-27 13:27:00,123z");
check(new DateTime.utc(2012, 02, 27, 13, 27, 0, 123, 0),
"2012-02-27 13:27:00.1234567891234z");
check(new DateTime.utc(2012, 02, 27, 13, 27, 0, 123, 0),
"2012-02-27 13:27:00,1234567891234z");
}
check(new DateTime(2012, 02, 27, 13, 27), "20120227 13:27:00");
check(new DateTime(2012, 02, 27, 13, 27), "20120227T132700");
Expand Down

0 comments on commit 867a6e0

Please sign in to comment.