diff --git a/vlib/time/parse.v b/vlib/time/parse.v index 284620420e..015f5f1360 100644 --- a/vlib/time/parse.v +++ b/vlib/time/parse.v @@ -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 { diff --git a/vlib/time/parse_test.v b/vlib/time/parse_test.v index 478dbdf827..decafea825 100644 --- a/vlib/time/parse_test.v +++ b/vlib/time/parse_test.v @@ -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() {