| Index: sdk/lib/core/date_time.dart
|
| diff --git a/sdk/lib/core/date_time.dart b/sdk/lib/core/date_time.dart
|
| index 02f7cdae12a222c8f89e8b9a7e4f8ee70395b2d7..1e89080a5f688cb8219f982dbad99b719e5febd6 100644
|
| --- a/sdk/lib/core/date_time.dart
|
| +++ b/sdk/lib/core/date_time.dart
|
| @@ -215,7 +215,8 @@ class DateTime implements Comparable {
|
| * * An optional time-zone offset part,
|
| * possibly separated from the previous by a space.
|
| * The time zone is either 'z' or 'Z', or it is a signed two digit hour
|
| - * part and an optional two digit minute part.
|
| + * part and an optional two digit minute part. The sign must be either
|
| + * "+" or "-", and can not be omitted.
|
| * The minutes may be separted from the hours by a ':'.
|
| * Examples: "Z", "-10", "01:30", "1130".
|
| *
|
| @@ -262,9 +263,9 @@ class DateTime implements Comparable {
|
| * timezonemins_opt ::= <empty> | colon_opt digit{2}
|
| */
|
| final RegExp re = new RegExp(
|
| - r'^([+-]?\d{4,6})-?(\d\d)-?(\d\d)' // The day part.
|
| - r'(?:[ T](\d\d)(?::?(\d\d)(?::?(\d\d)(.\d{1,6})?)?)?' // The time part
|
| - r'( ?[zZ]| ?([-+])(\d\d)(?::?(\d\d))?)?)?$'); // The timezone part
|
| + r'^([+-]?\d{4,6})-?(\d\d)-?(\d\d)' // Day part.
|
| + r'(?:[ T](\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d{1,6}))?)?)?' // Time part.
|
| + r'( ?[zZ]| ?([-+])(\d\d)(?::?(\d\d))?)?)?$'); // Timezone part.
|
|
|
| Match match = re.firstMatch(formattedString);
|
| if (match != null) {
|
| @@ -273,9 +274,37 @@ class DateTime implements Comparable {
|
| return int.parse(matched);
|
| }
|
|
|
| - double parseDoubleOrZero(String matched) {
|
| - if (matched == null) return 0.0;
|
| - return double.parse(matched);
|
| + // Parses fractional second digits of '.(\d{1,6})' into milliseconds.
|
| + // Uses first three digits (assumed to be zero if not there), and
|
| + // rounds up if fourth digit is 5 or greater.
|
| + // Should be equivalent to `(double.parse(".$matchd")*1000).round()`.
|
| + int parseMilliseconds(String matched) {
|
| + if (matched == null) return 0;
|
| + int length = matched.length;
|
| + assert(length >= 1);
|
| + assert(length <= 6);
|
| +
|
| + int result = (matched.codeUnitAt(0) ^ 0x30);
|
| + if (length <= 3) {
|
| + int i = 1;
|
| + while (i < length) {
|
| + result *= 10;
|
| + result += matched.codeUnitAt(i) ^ 0x30;
|
| + i++;
|
| + }
|
| + while (i < 3) {
|
| + result *= 10;
|
| + i++;
|
| + }
|
| + return result;
|
| + }
|
| + // Parse the prefix from 0..3 without creating a new substring.
|
| + result = result * 10 + (matched.codeUnitAt(1) ^ 0x30);
|
| + result = result * 10 + (matched.codeUnitAt(2) ^ 0x30);
|
| + if (matched.codeUnitAt(3) >= 0x35) {
|
| + result += 1;
|
| + }
|
| + return result;
|
| }
|
|
|
| int years = int.parse(match[1]);
|
| @@ -285,7 +314,7 @@ class DateTime implements Comparable {
|
| int minute = parseIntOrZero(match[5]);
|
| int second = parseIntOrZero(match[6]);
|
| bool addOneMillisecond = false;
|
| - int millisecond = (parseDoubleOrZero(match[7]) * 1000).round();
|
| + int millisecond = parseMilliseconds(match[7]);
|
| if (millisecond == 1000) {
|
| addOneMillisecond = true;
|
| millisecond = 999;
|
|
|