Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to parse 0000-00-00 00:00:00?

I'm parsing some time values from a mysql database and some of them are zero. Why does Go fail to parse this and how can I fix it?

checkTime := "0000-00-00 00:00:00"
t, err := time.Parse("2006-01-02 15:04:05", checkTime)
if err !=nil{
    log.Errorf("err %v, checkTime %v, ID %v", err, checkTime, bk.ID)
}

I get:

err parsing time "0000-00-00 00:00:00": month out of range, checkin 0000-00-00 00:00:00
like image 902
Anthony Hunt Avatar asked Sep 07 '15 05:09

Anthony Hunt


3 Answers

First a comile time error in your code: there is no log.Errorf() function (that is if you're using the standard log package). Instead use for example log.Printf().

Second, as your error states: month out of range. Month is in range if 1..12. A month value of 0 or 00 is invalid. See valid months here.

The zero time (or the more precise term: the zero value of the type time.Time) is as printed by:

log.Println("Zero time is:", time.Time{}.Format("2006-01-02 15:04:05"))

Output:

2009/11/10 23:00:00 Zero time is: 0001-01-01 00:00:00

Note that year, month and day are all 1.

Also note that even though days start from 1, day 0 is also accepted and is interpreted as -1 day from the first day of month specified by the year and month parts.

So while "0000-01-01 00:00:00" can be parsed and properly gives "0000-01-01 00:00:00 +0000 UTC", the time "0000-01-00 00:00:00" will give "-0001-12-31 00:00:00 +0000 UTC".

The exact date "0000-00-00 00:00:00" represents the zero date from your source (MySql db?), and so in Go when this date is detected I would return the zero value for the Go time.Time so you can check it from Go with the Time.IsZero() method. Use this simple helper function to parse your times:

func parseTime(s string) (time.Time, err) {
    if s == "0000-00-00 00:00:00" {
        return time.Time{}, nil
    }
    return time.Parse("2006-01-02 15:04:05", s)
}

See the examples in action on the Go Playground.

like image 136
icza Avatar answered Nov 20 '22 09:11

icza


That does not parse because there was no year zero. After 1 B.C. is 1 A.D.

With most contexts, it probably makes sense to make a special check for year zero and store a NULL value in its place.


From a practical viewpoint, any dates given as being in a year between 1 AD and around 600 A.D. are poorly documented and likely wrong. Somewhere in there are a few missed years. Academics aren't sure how many, but they mostly agree that at least 4 years are missing and maybe as many as 8 or 10. That is, the year 2015 actually should be 2019 to 2029.

like image 28
wallyk Avatar answered Nov 20 '22 10:11

wallyk


The zero value of type Time is January 1, year 1, 00:00:00.000000000 UTC. So there is no month 0 in Go.

like image 1
reedobrien Avatar answered Nov 20 '22 10:11

reedobrien