Go解析自定义日期格式为time报错parsing time xxx out of range/ cannot parse xxx as xxx

1.问题

将一个自定义的日期格式,如"2020-08-10 15:04:35",转为时间戳:

    myDateString2 := "2020-08-10 15:04:35"
    myDate2, err := time.Parse("2020-08-10 15:04:35", myDateString2)
    if err != nil {
        log.Println("err:", err.Error())
        return
    }
    fmt.Println("My Starting Date2:\t", myDateString2, "---->", myDate2.UnixNano()/1e6)

执行报错:
err: parsing time "2020-08-10 15:04:35" as "2020-08-10 15:04:35": cannot parse "-08-10 15:04:35" as "0-08-"

当修改layout为2016-01-02 15:04:05,还会报错:
err: parsing time "2020-08-10 15:04:35": month out of range

2.原因

对layout解析过程中, src/pkg/time/format.g中定义了格式常量(年月日等),对常量涵盖的年月日和其他的年月日解析不同,自定义的layout可能导致解析有问题。
比如在解析年份时,如果年份不等于2006,会被解析为stdDay,那么在解析2020-08-10 15:04:35的时候年被当成2:

        case '2': // 2006, 2
            if len(layout) >= i+4 && layout[i:i+4] == "2006" {
                return layout[0:i], stdLongYear, layout[i+4:]
            }
            return layout[0:i], stdDay, layout[i+1:] //不是2006 返回这个

后面的解析自然就出问题了。

3.解决

如,constant定义的年份为2006(或06),月为1月(January/1/01/Jan)..,那么在进行自定义layout时,按照constant中已经定义的就可以正常解析了

    stdLongMonth             = iota + stdNeedDate  // "January"
    stdMonth                                       // "Jan"
    stdNumMonth                                    // "1"
    stdZeroMonth                                   // "01"
    stdLongWeekDay                                 // "Monday"
    stdWeekDay                                     // "Mon"
    stdDay                                         // "2"
    stdUnderDay                                    // "_2"
    stdZeroDay                                     // "02"
    stdUnderYearDay                                // "__2"
    stdZeroYearDay                                 // "002"
    stdHour                  = iota + stdNeedClock // "15"
    stdHour12                                      // "3"
    stdZeroHour12                                  // "03"
    stdMinute                                      // "4"
    stdZeroMinute                                  // "04"
    stdSecond                                      // "5"
    stdZeroSecond                                  // "05"
    stdLongYear              = iota + stdNeedDate  // "2006"
    stdYear                                        // "06"
    stdPM                    = iota + stdNeedClock // "PM"
    stdpm                                          // "pm"
    stdTZ                    = iota                // "MST"
    stdISO8601TZ                                   // "Z0700"  // prints Z for UTC
    stdISO8601SecondsTZ                            // "Z070000"
    stdISO8601ShortTZ                              // "Z07"
    stdISO8601ColonTZ                              // "Z07:00" // prints Z for UTC
    stdISO8601ColonSecondsTZ                       // "Z07:00:00"
    stdNumTZ                                       // "-0700"  // always numeric
    stdNumSecondsTz                                // "-070000"
    stdNumShortTZ                                  // "-07"    // always numeric
    stdNumColonTZ                                  // "-07:00" // always numeric
    stdNumColonSecondsTZ                           // "-07:00:00"
    stdFracSecond0                                 // ".0", ".00", ... , trailing zeros included
    stdFracSecond9                                 // ".9", ".99", ..., trailing zeros omitted

将layout修改为里面定义了的年月日时分秒,如2006-01-02 15:04:05即可,修改后代码:

myDate2, err := time.Parse("2006-01-02 15:04:05", myDateString2)

参考

[1]https://stackoverflow.com/questions/14106541/parsing-date-time-strings-which-are-not-standard-formats

你可能感兴趣的:(Go解析自定义日期格式为time报错parsing time xxx out of range/ cannot parse xxx as xxx)