time: improve parse_iso8601 (#7006)

pull/7012/head
Takahiro Yaota 2020-11-29 17:38:14 +09:00 committed by GitHub
parent 1192dfdc8a
commit 49a083fe79
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 32 additions and 7 deletions

View File

@ -62,20 +62,22 @@ pub fn parse_iso8601(s string) ?Time {
second := 0 second := 0
mic_second := 0 mic_second := 0
time_char := `a` time_char := `a`
plus_min := `a` plus_min_z := `a`
offset_hour := 0 offset_hour := 0
offset_min := 0 offset_min := 0
count := unsafe {C.sscanf(charptr(s.str), '%4d-%2d-%2d%c%2d:%2d:%2d.%6d%c%2d:%2d', 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), &offset_hour, &year, &month, &day, charptr(&time_char), &hour, &minute, &second, &mic_second, charptr(&plus_min_z), &offset_hour,
&offset_min)} &offset_min)}
if count != 11 { 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 {
return error('Invalid 8601 format') return error('Invalid 8601 format')
} }
if time_char != `T` && time_char != ` ` { if time_char != `T` && time_char != ` ` {
return error('Invalid 8601 format, expected space or `T` as time separator') return error('Invalid 8601 format, expected space or `T` as time separator')
} }
if plus_min != `+` && plus_min != `-` { if plus_min_z != `+` && plus_min_z != `-` && plus_min_z != `Z` && !is_local_time {
return error('Invalid 8601 format, expected `+` or `-` as time separator') return error('Invalid 8601 format, expected `Z` or `+` or `-` as time separator')
} }
mut t := new_time(Time{ mut t := new_time(Time{
year: year year: year
@ -86,6 +88,10 @@ pub fn parse_iso8601(s string) ?Time {
second: second second: second
microsecond: mic_second microsecond: mic_second
}) })
if is_local_time {
return to_local_time(t)
}
mut unix_time := t.unix mut unix_time := t.unix
mut unix_offset := int(0) mut unix_offset := int(0)
if offset_hour > 0 { if offset_hour > 0 {
@ -95,7 +101,7 @@ pub fn parse_iso8601(s string) ?Time {
unix_offset += 60 * offset_min unix_offset += 60 * offset_min
} }
if unix_offset != 0 { if unix_offset != 0 {
if plus_min == `+` { if plus_min_z == `+` {
unix_time -= u64(unix_offset) unix_time -= u64(unix_offset)
} else { } else {
unix_time += u64(unix_offset) unix_time += u64(unix_offset)

View File

@ -45,6 +45,25 @@ fn test_parse_rfc2822_invalid() {
assert false assert false
} }
fn test_iso8601_parse_utc() {
format_utc := '2020-06-05T15:38:06.015959Z'
t_utc := time.parse_iso8601(format_utc) or {panic(err)}
assert t_utc.year == 2020
assert t_utc.month == 6
assert t_utc.day == 5
}
fn test_iso8601_parse_loacl() {
format_utc := '2020-06-05T15:38:06.015959'
t_utc := time.parse_iso8601(format_utc) or {panic(err)}
assert t_utc.year == 2020
assert t_utc.month == 6
assert t_utc.day == 5
}
fn test_iso8601_parse_utc_diff() { fn test_iso8601_parse_utc_diff() {
format_utc := '2020-06-05T15:38:06.015959+00:00' format_utc := '2020-06-05T15:38:06.015959+00:00'
format_cest := '2020-06-05T15:38:06.015959+02:00' format_cest := '2020-06-05T15:38:06.015959+02:00'
@ -68,4 +87,4 @@ fn test_iso8601_parse_utc_diff() {
assert t_cest.second == 6 assert t_cest.second == 6
assert t_utc.microsecond == 15959 assert t_utc.microsecond == 15959
assert t_cest.microsecond == 15959 assert t_cest.microsecond == 15959
} }