Last active
February 16, 2022 08:43
-
-
Save granoeste/886d9ff6ebd55e7bd857468404271ba8 to your computer and use it in GitHub Desktop.
RFC3339 DateTime Serializer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class DateTimeSerializer { | |
static DateTime? deserialize(String? serialized) { | |
if (serialized == null) return null; | |
final serializedString = serialized; | |
final fixed = serializedString.replaceAllMapped( | |
RegExp(r'(.*:\d\d)(\.\d+)?(Z|[+-]\d{2}:\d{2})'), | |
(match) { | |
// #1 capturing group is date and time without a fraction of a second | |
// #2 group is `time-secfrac` - if present | |
// #3 group is `time-offset` | |
var timeSecfrac = match[2] ?? ''; | |
if (timeSecfrac.length > 7) { | |
// 6 is 0th period + (up to) 6 characters accepted by ISO8601 | |
timeSecfrac = timeSecfrac.substring(0, 7); | |
} | |
return (match[1] ?? '') + timeSecfrac + (match[3] ?? ''); | |
}, | |
); | |
return DateTime.parse(fixed).toUtc(); | |
} | |
static String? serialize(DateTime? dateTime) { | |
// if (!dateTime.isUtc) { | |
// throw ArgumentError.value(dateTime, 'dateTime', 'Must be in utc for serialization.'); | |
// } | |
if (dateTime == null) return null; | |
if (!dateTime.isUtc) { | |
final utc = dateTime.toUtc(); | |
return DateTime.utc( | |
utc.year, utc.month, utc.day, utc.hour, utc.minute, utc.second, utc.millisecond, utc.microsecond) | |
.toIso8601String(); | |
} | |
return dateTime.toIso8601String(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:test/test.dart'; | |
void main() { | |
test('correctly parses RFC 3339 dates', () { | |
final cases = { | |
// ISO 8601 | |
'2019-08-09T06:55:01.896826+05:00': DateTime.utc(2019, 8, 9, 1, 55, 1, 896, 826), | |
'2019-08-09T06:55:01.896826Z': DateTime.utc(2019, 8, 9, 6, 55, 1, 896, 826), | |
'2019-08-09T06:55:01Z': DateTime.utc(2019, 8, 9, 6, 55, 1), | |
// RFC 3339 | |
'2019-05-31T10:35:45.347333481Z': DateTime.utc(2019, 5, 31, 10, 35, 45, 347, 333), | |
'2018-01-29T18:39:51.396781283+01:00': DateTime.utc(2018, 1, 29, 17, 39, 51, 396, 781), | |
'2019-08-09T06:55:01.8968264+00:00': DateTime.utc(2019, 8, 9, 6, 55, 1, 896, 826), | |
'2020-10-20T20:55:01+09:00': DateTime.utc(2020, 10, 20, 11, 55, 1, 0, 0), | |
'2020-10-20T20:35+09:00': DateTime.utc(2020, 10, 20, 11, 35, 0, 0, 0), | |
}; | |
cases.forEach((source, datetime) { | |
final deserialized = DateTimeSerializer.deserialize(source); | |
print('source :$source'); | |
print('datetime :$datetime'); | |
print('deserialized:$deserialized'); | |
print(' tz :${deserialized?.timeZoneName}'); | |
print(' offset:${deserialized?.timeZoneOffset}'); | |
print(' local :${deserialized?.toLocal()}'); | |
expect(deserialized, datetime); | |
final serialized = DateTimeSerializer.serialize(deserialized); | |
print('serialized :$serialized'); | |
print(''); | |
}); | |
final now = DateTime.now(); | |
print('source :$now'); | |
final serializedNow = DateTimeSerializer.serialize(now); | |
print('serializedNow :$serializedNow'); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment