time: make parse_iso8601 support format without microseconds (#7176)

pull/7200/head
Takahiro Yaota 2020-12-09 01:53:54 +09:00 committed by GitHub
parent d5915bde7c
commit 036e762446
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 27 additions and 8 deletions

View File

@ -51,7 +51,7 @@ pub fn parse_rfc2822(s string) ?Time {
// parse_iso8601 parses rfc8601 time format yyyy-MM-ddTHH:mm:ss.dddddd+dd:dd as local time
// the fraction part is difference in milli seconds and the last part is offset
// from UTC time and can be both +/- HH:mm
// remarks: not all iso8601 is supported only the 'yyyy-MM-ddTHH:mm:ss.dddddd+dd:dd'
// remarks: not all iso8601 is supported
// also checks and support for leapseconds should be added in future PR
pub fn parse_iso8601(s string) ?Time {
year := 0
@ -65,9 +65,16 @@ pub fn parse_iso8601(s string) ?Time {
plus_min_z := `a`
offset_hour := 0
offset_min := 0
count := unsafe {C.sscanf(charptr(s.str), '%4d-%2d-%2d%c%2d:%2d:%2d.%6d%c%2d:%2d',
mut count := unsafe {C.sscanf(charptr(s.str), '%4d-%2d-%2d%c%2d:%2d:%2d.%6d%c%2d:%2d',
&year, &month, &day, charptr(&time_char), &hour, &minute, &second, &mic_second, charptr(&plus_min_z),
&offset_hour, &offset_min)}
// Missread microsec ([Year Month Day T Sec Hour Minute].len == 7 < 8)
if count < 8 {
count = unsafe {C.sscanf(charptr(s.str), '%4d-%2d-%2d%c%2d:%2d:%2d%c%2d:%2d',
&year, &month, &day, charptr(&time_char), &hour, &minute, &second, charptr(&plus_min_z),
&offset_hour, &offset_min)}
count++ // Increment count because skipped microsec
}
is_local_time := plus_min_z == `a` && count == 8
is_utc := plus_min_z == `Z` && count == 9
if count != 11 && !is_local_time && !is_utc {

View File

@ -49,13 +49,25 @@ fn test_parse_rfc2822_invalid() {
}
fn test_iso8601_parse_utc() {
format_utc := '2020-06-05T15:38:06.015959Z'
t_utc := time.parse_iso8601(format_utc) or {
panic(err)
formats := [
'2020-06-05T15:38:06.015959Z',
'2020-06-05T15:38:06Z',
]
times := [
[2020, 6, 5, 15, 38, 6, 15959],
[2020, 6, 5, 15, 38, 6, 0],
]
for i, format in formats {
t := time.parse_iso8601(format) or { panic(err) }
tt := times[i]
assert t.year == tt[0]
assert t.month == tt[1]
assert t.day == tt[2]
assert t.hour == tt[3]
assert t.minute == tt[4]
assert t.second == tt[5]
assert t.microsecond == tt[6]
}
assert t_utc.year == 2020
assert t_utc.month == 6
assert t_utc.day == 5
}
fn test_iso8601_parse_local() {