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.
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
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? :)