golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
121.26k stars 17.37k forks source link

time: time.Parse unable to parse timestamps with unusual UTC offsets #26032

Open ALTree opened 6 years ago

ALTree commented 6 years ago
$ gotip version
go version devel +d6a27e8edc Sat Jun 23 00:16:14 2018 +0000 linux/amd64

I dumped the time for each of the 425 timezones in my system's tz database in a file and tried to parse the timestamps. I got 17 errors, all caused by time.Parse inability to parse unusual offsets like +0545 (used in Asia/Kathmandu) or +13 (used in Pacific/Fakaofo).

Complete failures log:

Timezone:    America/Scoresbysund
zdump time:  Sun Jun 24 10:43:46 2018 +00
time.Parse:  parsing time "Sun Jun 24 10:43:46 2018 +00": extra text: +00 

Timezone:    Asia/Colombo
zdump time:  Sun Jun 24 16:13:46 2018 +0530
time.Parse:  parsing time "Sun Jun 24 16:13:46 2018 +0530": extra text: +0530 

Timezone:    Asia/Kabul
zdump time:  Sun Jun 24 15:13:46 2018 +0430
time.Parse:  parsing time "Sun Jun 24 15:13:46 2018 +0430": extra text: +0430 

Timezone:    Asia/Kathmandu
zdump time:  Sun Jun 24 16:28:46 2018 +0545
time.Parse:  parsing time "Sun Jun 24 16:28:46 2018 +0545": extra text: +0545 

Timezone:    Asia/Tehran
zdump time:  Sun Jun 24 15:13:46 2018 +0430
time.Parse:  parsing time "Sun Jun 24 15:13:46 2018 +0430": extra text: +0430 

Timezone:    Asia/Yangon
zdump time:  Sun Jun 24 17:13:46 2018 +0630
time.Parse:  parsing time "Sun Jun 24 17:13:46 2018 +0630": extra text: +0630 

Timezone:    Atlantic/Azores
zdump time:  Sun Jun 24 10:43:46 2018 +00
time.Parse:  parsing time "Sun Jun 24 10:43:46 2018 +00": extra text: +00 

Timezone:    Australia/Eucla
zdump time:  Sun Jun 24 19:28:46 2018 +0845
time.Parse:  parsing time "Sun Jun 24 19:28:46 2018 +0845": extra text: +0845 

Timezone:    Australia/Lord_Howe
zdump time:  Sun Jun 24 21:13:46 2018 +1030
time.Parse:  parsing time "Sun Jun 24 21:13:46 2018 +1030": extra text: +1030 

Timezone:    Indian/Cocos
zdump time:  Sun Jun 24 17:13:46 2018 +0630
time.Parse:  parsing time "Sun Jun 24 17:13:46 2018 +0630": extra text: +0630 

Timezone:    Pacific/Apia
zdump time:  Sun Jun 24 23:43:46 2018 +13
time.Parse:  parsing time "Sun Jun 24 23:43:46 2018 +13": extra text: +13 

Timezone:    Pacific/Chatham
zdump time:  Sun Jun 24 23:28:46 2018 +1245
time.Parse:  parsing time "Sun Jun 24 23:28:46 2018 +1245": extra text: +1245 

Timezone:    Pacific/Enderbury
zdump time:  Sun Jun 24 23:43:46 2018 +13
time.Parse:  parsing time "Sun Jun 24 23:43:46 2018 +13": extra text: +13 

Timezone:    Pacific/Fakaofo
zdump time:  Sun Jun 24 23:43:46 2018 +13
time.Parse:  parsing time "Sun Jun 24 23:43:46 2018 +13": extra text: +13 

Timezone:    Pacific/Kiritimati
zdump time:  Mon Jun 25 00:43:46 2018 +14
time.Parse:  parsing time "Mon Jun 25 00:43:46 2018 +14": extra text: +14 

Timezone:    Pacific/Marquesas
zdump time:  Sun Jun 24 01:13:46 2018 -0930
time.Parse:  parsing time "Sun Jun 24 01:13:46 2018 -0930": extra text: -0930 

Timezone:    Pacific/Tongatapu
zdump time:  Sun Jun 24 23:43:46 2018 +13
time.Parse:  parsing time "Sun Jun 24 23:43:46 2018 +13": extra text: +13 

https://gist.github.com/ALTree/de33561c1cc00ac46e2e9e6d6cca52fe

gopherbot commented 6 years ago

Change https://golang.org/cl/120558 mentions this issue: time: accept UTC offsets +13,+14 in Parse, reject -13,-14

gopherbot commented 5 years ago

Change https://golang.org/cl/130696 mentions this issue: time: allow +00 as numeric timezone name and GMT offset

ALTree commented 5 years ago

+14 and +00 are now parsed correctly, down to 10 failures, all caused by non-integral UTC offsets:

$ gotip run parse_timezones.go 
Timezone:    Indian/Cocos
zdump time:  Sun Aug 5 18:25:10 2018 +0630
time.Parse:  parsing time "Sun Aug 5 18:25:10 2018 +0630" as "Mon Jan 2 15:04:05 2006 MST": cannot parse "+0630" as "MST" 

Timezone:    Asia/Kabul
zdump time:  Sun Aug 5 16:25:10 2018 +0430
time.Parse:  parsing time "Sun Aug 5 16:25:10 2018 +0430" as "Mon Jan 2 15:04:05 2006 MST": cannot parse "+0430" as "MST" 

Timezone:    Australia/Lord_Howe
zdump time:  Sun Aug 5 22:25:10 2018 +1030
time.Parse:  parsing time "Sun Aug 5 22:25:10 2018 +1030" as "Mon Jan 2 15:04:05 2006 MST": cannot parse "+1030" as "MST" 

Timezone:    Australia/Eucla
zdump time:  Sun Aug 5 20:40:10 2018 +0845
time.Parse:  parsing time "Sun Aug 5 20:40:10 2018 +0845" as "Mon Jan 2 15:04:05 2006 MST": cannot parse "+0845" as "MST" 

Timezone:    Asia/Kathmandu
zdump time:  Sun Aug 5 17:40:10 2018 +0545
time.Parse:  parsing time "Sun Aug 5 17:40:10 2018 +0545" as "Mon Jan 2 15:04:05 2006 MST": cannot parse "+0545" as "MST" 

Timezone:    Pacific/Chatham
zdump time:  Mon Aug 6 00:40:10 2018 +1245
time.Parse:  parsing time "Mon Aug 6 00:40:10 2018 +1245" as "Mon Jan 2 15:04:05 2006 MST": cannot parse "+1245" as "MST" 

Timezone:    Pacific/Marquesas
zdump time:  Sun Aug 5 02:25:10 2018 -0930
time.Parse:  parsing time "Sun Aug 5 02:25:10 2018 -0930" as "Mon Jan 2 15:04:05 2006 MST": cannot parse "-0930" as "MST" 

Timezone:    Asia/Colombo
zdump time:  Sun Aug 5 17:25:10 2018 +0530
time.Parse:  parsing time "Sun Aug 5 17:25:10 2018 +0530" as "Mon Jan 2 15:04:05 2006 MST": cannot parse "+0530" as "MST" 

Timezone:    Asia/Yangon
zdump time:  Sun Aug 5 18:25:10 2018 +0630
time.Parse:  parsing time "Sun Aug 5 18:25:10 2018 +0630" as "Mon Jan 2 15:04:05 2006 MST": cannot parse "+0630" as "MST" 

Timezone:    Asia/Tehran
zdump time:  Sun Aug 5 16:25:10 2018 +0430
time.Parse:  parsing time "Sun Aug 5 16:25:10 2018 +0430" as "Mon Jan 2 15:04:05 2006 MST": cannot parse "+0430" as "MST" 

Failures:    10
cstockton commented 4 years ago

I just ran into some timestamps formatted as 2019-08-22T10:41:59.006928+0000 - I know time parsing is complex but I believe the above is ISO8601 compliant. I believe the below should return the same times as date command, and definitely not have a parse failure:

Format Cmd Result
2019-08-22T10:41:59.006928+0000 date Thu Aug 22 03:41:59 MST 2019
2019-08-22T10:41:59.006928+0000 go parsing time ""2019-08-22T10:41:59.006928+0000"" as ""2006-01-02T15:04:05Z07:00"": cannot parse "+0000"" as "Z07:00"
2019-08-22T10:41:59.006928+00:00 date Thu Aug 22 03:41:59 MST 2019
2019-08-22T10:41:59.006928+00:00 go 2019-08-22 10:41:59.006928 +0000 +0000
2019-08-22T10:41:59.006928Z date Thu Aug 22 03:41:59 MST 2019
2019-08-22T10:41:59.006928Z go 2019-08-22 10:41:59.006928 +0000 UTC

Go 1.8-1.12.9 all have same result.

edit: sorry, I left out the fact it's parsing JSON. I could work around it easily if it was just a regular string. But there is never a clean way to fix JSON time parsing in without wrapping it in a custom type which makes working with the data structure unfortunate since you have to unwrap the type to do anything with it, or have a multiple step json.Unmarshal in the parent type which doesn't scale very well for nested occurrences. That said I think it may be worth fixing in json.Unmarshal even if it's a simple special case that accepts another set of 00 in place of a :.

ALTree commented 4 years ago

@cstockton It seems to be working (if you use the right parsing format):

package main

import (
    "fmt"
    "time"
)

func main() {
    tstamp := "2019-08-22T10:41:59.006928+0000"
    t, err := time.Parse("2006-01-02T15:04:05-0700", tstamp)
    if err != nil {
        panic(err)
    }
    fmt.Println(t.Format(time.UnixDate))
}

https://play.golang.org/p/RjhP0xB6AtX

what am I missing?

cstockton commented 4 years ago

I am using JSON Unmarshal.

goku321 commented 3 years ago

I am not able to parse Tue Jun 11 2019 13:26:45 GMT+0000 using Mon Jan 02 2006 15:04:05 MST-0700 as a layout. What am I doing wrong?

goku321 commented 3 years ago

Using Mon Jan 02 2006 15:04:05 GMT-0700 as the layout works and I get the output as 2019-06-11 13:26:45 +0000 +0000. Is this the desired behavior and solution?

gopherbot commented 2 years ago

Change https://golang.org/cl/357450 mentions this issue: time: allow +0430,-0930 UTC offsets in Parse