Sdk: DateTime.parse() does not strictly include RFC 3339: limited millisecond length

Created on 26 Aug 2015  路  11Comments  路  Source: dart-lang/sdk

RFC 3339 defines the "time-secfrac" component of a timestamp to be "." 1*DIGIT, which permits second fractions of unlimited length. DateTime.parse() only accepts a second fraction component of up to length 6.

The length limitation on "millis_opt" should be removed, or the documentation should be updated to note that DateTime.parse() does not strictly support RFC 3339.

area-library core-a library-core

Most helpful comment

Is there a reason why Dart refers to "ISO8601" while Go refers to "RFC3339".

Could the two teams in Google maybe agree on a standard to follow? :)

All 11 comments

I have this problem as well. Dart fails to parse dates generated by Go, f.e.: 2018-01-29T18:39:51.396781283+01:00.

Is there a reason why Dart refers to "ISO8601" while Go refers to "RFC3339".

Could the two teams in Google maybe agree on a standard to follow? :)

I'm having this issue too. It is really annoying having to chop off some digits of the string I get from Go's time.Time in order for DateTime to parse it correctly.

I think I solved it by in Go, making a newTime := time.Unix(oldTime.Unix()), which truncate to seconds.

@stevenroose I solved it in dart by just taking a substring. But I think the Dart SDK should address this specifically. A default server timestamp from Go should have no issues parsing through Dart. Even if we lose precision. Perhaps the parse could optionally chop off the extra digits?

@curtiscovington I had a substring thing first, but it broke when using different time zones etc. Yeah Dart should surely solve this.

See also #1878.
We should extend the formats recognized by DateTime.parse.
Accepting more formats does come with a cost, since all the necessary code will be included when you use the function, even if you only use a single simple format.

I have the same issue with creating Dart DateTime object coming from a Go backend (for example: const invalid = "2019-05-31T10:35:45.347333481Z";).

As you see this format is using nanoseconds (10^-9) and the Dart DateTime.parse code only allows up to microseconds (10^-6).

The quick fix I used: drop the sub-microsecond digits (from between 7th to 9th)

// You could add a stricter/looser verification, but for my usecase, this was enough.
// Also, decide what you want to do with an invalid input: return null, return the original string, or throw an exception?
String _ignoreSubMicro(String s) {
  if (s.length > 27) return s.substring(0, 26) + s[s.length - 1];
  return s;
}
// Example usage
void main() {
  const invalidNano = "2019-05-31T10:35:45.347333481Z";
  // DateTime.parse(invalidNano); // This would fail:
  final date = DateTime.parse(_ignoreSubMicro(invalidNano));
  print(date);
}

What would be the implications of allowing nanosecond values? Or is it complicated because of the time zones? As I see the parse method could ignore extra digits relatively easily, so I assume there are other reasons you decided not to update the parse method. Would you merge a pull request adding the nano support? Which solution would you merge (ignore sub-microsecond values, round sub-microsecond values to the microsecond, complete nanoseconds support)?

Same problem with date strings created in C#: For example:
c# DateTimeOffset.Now.ToString("O")
outputs: "2019-08-09T06:55:01.8968264+00:00"

Can we get a response to vargavince91's comment please?

I created a pub package to address this exact problem for built_value: https://pub.dev/packages/rfc_3339_date_time_serializer

Was this page helpful?
0 / 5 - 0 ratings