time-parse fixes

This commit is contained in:
Aaron Raddon 2018-02-27 20:05:14 -08:00
parent 7825aa09f1
commit 20cd681f46
2 changed files with 281 additions and 314 deletions

View File

@ -28,7 +28,6 @@ const (
dateDigitDashDash dateDigitDashDash
dateDigitDashDashWs dateDigitDashDashWs
dateDigitDashDashT dateDigitDashDashT
dateDigitDashDashTZ
dateDigitDashDashAlpha dateDigitDashDashAlpha
dateDigitDot dateDigitDot
dateDigitDotDot dateDigitDotDot
@ -41,10 +40,7 @@ const (
dateDigitChineseYear dateDigitChineseYear
dateDigitChineseYearWs dateDigitChineseYearWs
dateDigitWs dateDigitWs
dateDigitWsMoShort dateDigitWsMoYear
dateDigitWsMoShortColon
dateDigitWsMoShortColonColon
dateDigitWsMoShortComma
dateAlpha dateAlpha
dateAlphaWS dateAlphaWS
dateAlphaWSDigit dateAlphaWSDigit
@ -72,7 +68,7 @@ const (
timeWs timeWs
timeWsAMPMMaybe timeWsAMPMMaybe
timeWsAMPM timeWsAMPM
timeWsOffset timeWsOffset // 5
timeWsAlpha timeWsAlpha
timeWsOffsetAlpha timeWsOffsetAlpha
timeWsOffsetColonAlpha timeWsOffsetColonAlpha
@ -81,11 +77,13 @@ const (
timeOffsetColon timeOffsetColon
timeAlpha timeAlpha
timePeriod timePeriod
timePeriodAlpha
timePeriodOffset timePeriodOffset
timePeriodOffsetColon // 15
timePeriodWs timePeriodWs
timePeriodWsAlpha
timePeriodWsOffset timePeriodWsOffset
timePeriodWsOffsetAlpha // 18 timePeriodWsOffsetWs
timePeriodWsOffsetWsAlpha // 20
timeZ timeZ
timeZDigit timeZDigit
) )
@ -177,13 +175,16 @@ func newParser(dateStr string, loc *time.Location) parser {
stateDate: dateStart, stateDate: dateStart,
stateTime: timeIgnore, stateTime: timeIgnore,
datestr: dateStr, datestr: dateStr,
loc: loc,
} }
p.format = []byte(dateStr) p.format = []byte(dateStr)
return p return p
} }
func (p parser) set(start int, val string) { func (p parser) set(start int, val string) {
if start < 0 {
return
}
if len(p.format) < start+len(val) { if len(p.format) < start+len(val) {
u.Warnf("invalid format %d: %v", start, val)
return return
} }
for i, r := range val { for i, r := range val {
@ -191,8 +192,8 @@ func (p parser) set(start int, val string) {
} }
} }
func (p parser) setMonth() { func (p parser) setMonth() {
if p.moi == 0 { if p.moi <= 0 {
u.Warnf("not set %+v", p) return
} }
if p.molen == 2 { if p.molen == 2 {
p.set(p.moi, "01") p.set(p.moi, "01")
@ -200,9 +201,19 @@ func (p parser) setMonth() {
p.set(p.moi, "1") p.set(p.moi, "1")
} }
} }
func (p parser) monthConvert(start, end int, mo string) {
if len(p.format) <= end {
return
}
for i := start; i < end; i++ {
p.format[i] = ' '
}
p.set(start, mo)
}
func (p parser) setDay() { func (p parser) setDay() {
if p.dayi == 0 { if p.dayi < 0 {
u.Warnf("not set %+v", p) return
} }
if p.daylen == 2 { if p.daylen == 2 {
p.set(p.dayi, "02") p.set(p.dayi, "02")
@ -210,13 +221,34 @@ func (p parser) setDay() {
p.set(p.dayi, "2") p.set(p.dayi, "2")
} }
} }
func (p parser) coalesceDate(end int) {
if p.yeari > 0 {
if p.yearlen == 0 {
p.yearlen = end - p.yeari
}
if p.yearlen == 2 {
p.set(p.yeari, "06")
} else if p.yearlen == 4 {
p.set(p.yeari, "2006")
}
}
if p.moi > 0 && p.molen == 0 {
p.molen = end - p.moi
p.setMonth()
}
if p.dayi > 0 && p.daylen == 0 {
p.daylen = end - p.dayi
p.setDay()
}
}
func (p parser) coalesceTime(end int) { func (p parser) coalesceTime(end int) {
// 03:04:05 // 03:04:05
// 15:04:05 // 15:04:05
// 3:04:05 // 3:04:05
// 3:4:5 // 3:4:5
// 15:04:05.00 // 15:04:05.00
u.Infof("coalesceTime: %+v", p)
if p.houri > 0 { if p.houri > 0 {
if p.hourlen == 2 { if p.hourlen == 2 {
p.set(p.houri, "15") p.set(p.houri, "15")
@ -237,7 +269,7 @@ func (p parser) coalesceTime(end int) {
if p.seci > 0 { if p.seci > 0 {
if p.seclen == 0 { if p.seclen == 0 {
p.seclen = end - p.seci p.seclen = end - p.seci
u.Infof("fixing seconds p.seci=%d seclen=%d end=%d", p.seci, p.seclen, end) //u.Infof("fixing seconds p.seci=%d seclen=%d end=%d", p.seci, p.seclen, end)
} }
if p.seclen == 2 { if p.seclen == 2 {
p.set(p.seci, "05") p.set(p.seci, "05")
@ -249,17 +281,17 @@ func (p parser) coalesceTime(end int) {
if p.msi > 0 { if p.msi > 0 {
if p.mslen == 0 { if p.mslen == 0 {
p.mslen = end - p.msi p.mslen = end - p.msi
u.Warnf("set mslen??? %v", p.datestr) //u.Warnf("set mslen??? %v", p.datestr)
} }
for i := 0; i < p.mslen; i++ { for i := 0; i < p.mslen; i++ {
p.format[p.msi+i] = '0' p.format[p.msi+i] = '0'
} }
} }
//u.Debugf("coalesce %+v", p)
u.Debugf("coalesce %+v", p)
} }
func (p parser) parse() (time.Time, error) { func (p parser) parse() (time.Time, error) {
u.Debugf("parse() %50s AS %50s", p.datestr, p.format) u.Debugf("parse() loc=%v %50s AS %50s", p.loc.String(), p.datestr, p.format)
if p.loc == nil { if p.loc == nil {
return time.Parse(string(p.format), p.datestr) return time.Parse(string(p.format), p.datestr)
} }
@ -307,9 +339,21 @@ iterRunes:
case '/': case '/':
p.stateDate = dateDigitSlash p.stateDate = dateDigitSlash
case '.': case '.':
// 3.31.2014
p.moi = 0
p.molen = i
p.dayi = i + 1
p.stateDate = dateDigitDot p.stateDate = dateDigitDot
case ' ': case ' ':
// 18 January 2018
// 8 January 2018
// 02 Jan 2018 23:59
// 02 Jan 2018 23:59:34
// 12 Feb 2006, 19:17
// 12 Feb 2006, 19:17:22
p.stateDate = dateDigitWs p.stateDate = dateDigitWs
p.dayi = 0
p.daylen = i
case '年': case '年':
// Chinese Year // Chinese Year
p.stateDate = dateDigitChineseYear p.stateDate = dateDigitChineseYear
@ -320,6 +364,7 @@ iterRunes:
p.part1Len = i p.part1Len = i
case dateDigitDash: case dateDigitDash:
// 2006-01
// 2006-01-02 // 2006-01-02
// dateDigitDashDashT // dateDigitDashDashT
// 2006-01-02T15:04:05Z07:00 // 2006-01-02T15:04:05Z07:00
@ -387,6 +432,7 @@ iterRunes:
// 13-Feb-03 // 13-Feb-03
switch r { switch r {
case '-': case '-':
p.molen = i - p.moi
p.set(p.moi, "Jan") p.set(p.moi, "Jan")
p.dayi = i + 1 p.dayi = i + 1
} }
@ -452,42 +498,43 @@ iterRunes:
case dateDigitWs: case dateDigitWs:
// 18 January 2018 // 18 January 2018
// 8 January 2018 // 8 January 2018
//dateDigitWsMoShort // 02 Jan 2018 23:59
// 02 Jan 2018 23:59 // 02 Jan 2018 23:59:34
// 02 Jan 2018 23:59:34 // 12 Feb 2006, 19:17
// dateDigitWsMoShortComma // 12 Feb 2006, 19:17:22
// 12 Feb 2006, 19:17
// 12 Feb 2006, 19:17:22
if r == ' ' {
if i <= p.part1Len+len(" Feb") {
p.stateDate = dateDigitWsMoShort
} else {
break iterRunes
}
}
case dateDigitWsMoShort:
// 18 January 2018
// 8 January 2018
// dateDigitWsMoShort
// dateDigitWsMoShortColon
// 02 Jan 2018 23:59
// dateDigitWsMoShortComma
// 12 Feb 2006, 19:17
// 12 Feb 2006, 19:17:22
switch r { switch r {
case ':': case ' ':
p.stateDate = dateDigitWsMoShortColon u.Infof("part1=%d i=%d", p.part1Len, i)
case ',': p.yeari = i + 1
p.stateDate = dateDigitWsMoShortComma p.yearlen = 4
} p.dayi = 0
case dateDigitWsMoShortColon: p.daylen = p.part1Len
// 02 Jan 2018 23:59 p.setDay()
// dateDigitWsMoShortColonColon p.stateTime = timeStart
// 02 Jan 2018 23:59:45 if i <= len("12 Feb") {
p.moi = p.daylen + 1
p.molen = 3
p.set(p.moi, "Jan")
u.Infof("set day dayi=%d len=%d", p.dayi, p.daylen)
} else {
u.Warnf("unhandled long month")
p.monthConvert(p.daylen+1, i, "Jan")
}
p.stateDate = dateDigitWsMoYear
}
case dateDigitWsMoYear:
u.Debugf("dateDigitWsMoYear ")
// 02 Jan 2018 23:59
// 02 Jan 2018 23:59:34
// 12 Feb 2006, 19:17
// 12 Feb 2006, 19:17:22
switch r { switch r {
case ':': case ',':
p.stateDate = dateDigitWsMoShortColonColon i++
break iterRunes
case ' ':
break iterRunes break iterRunes
} }
@ -503,8 +550,9 @@ iterRunes:
case dateDigitDot: case dateDigitDot:
// 3.31.2014 // 3.31.2014
if r == '.' { if r == '.' {
p.daylen = i - p.dayi
p.yeari = i + 1
p.stateDate = dateDigitDotDot p.stateDate = dateDigitDotDot
p.part2Len = i
} }
case dateDigitDotDot: case dateDigitDotDot:
// iterate all the way through // iterate all the way through
@ -685,20 +733,18 @@ iterRunes:
} }
} }
p.coalesceDate(i)
if p.stateTime == timeStart { if p.stateTime == timeStart {
// increment first one, since the i++ occurs at end of loop // increment first one, since the i++ occurs at end of loop
i++ i++
iterTimeRunes: iterTimeRunes:
for ; i < len(datestr); i++ { for ; i < len(datestr); i++ {
r, bytesConsumed := utf8.DecodeRuneInString(datestr[i:]) r := rune(datestr[i])
if bytesConsumed > 1 {
i += (bytesConsumed - 1)
}
u.Debugf("i=%d r=%s timeState=%d", i, string(r), p.stateTime)
switch p.stateTime { switch p.stateTime {
case timeIgnore:
// not used
case timeStart: case timeStart:
// 22:43:22 // 22:43:22
// timeComma // timeComma
@ -711,21 +757,25 @@ iterRunes:
// 15:04:05 -07:00 // 15:04:05 -07:00
// timeOffset // timeOffset
// 03:21:51+00:00 // 03:21:51+00:00
// 19:55:00+0100
// timePeriod // timePeriod
// 17:24:37.3186369 // 17:24:37.3186369
// 00:07:31.945167 // 00:07:31.945167
// 18:31:59.257000000 // 18:31:59.257000000
// 00:00:00.000 // 00:00:00.000
// 15:04:05.999-07:00
// timePeriodOffset // timePeriodOffset
// 00:07:31.945167 +0000 // 19:55:00.799+0100
// 00:00:00.000 +0000 // timePeriodOffsetColon
// timePeriodOffsetAlpha // 15:04:05.999-07:00
// timePeriodWs
// timePeriodWsOffset
// 00:07:31.945167 +0000
// 00:00:00.000 +0000
// timePeriodWsOffsetAlpha
// 00:07:31.945167 +0000 UTC // 00:07:31.945167 +0000 UTC
// 00:00:00.000 +0000 UTC // 00:00:00.000 +0000 UTC
// timePeriodAlpha // timePeriodWsAlpha
// 06:20:00.000 UTC // 06:20:00.000 UTC
if p.houri == 0 { if p.houri == 0 {
p.houri = i p.houri = i
} }
@ -755,16 +805,13 @@ iterRunes:
p.stateTime = timeZ p.stateTime = timeZ
if p.seci == 0 { if p.seci == 0 {
p.minlen = i - p.mini p.minlen = i - p.mini
u.Infof("mini:%d minlen:%d", p.mini, p.minlen)
} else { } else {
p.seclen = i - p.seci p.seclen = i - p.seci
u.Infof("seci:%d seclen:%d", p.seci, p.seclen)
} }
case ' ': case ' ':
p.stateTime = timeWs p.stateTime = timeWs
p.seclen = i - p.seci p.seclen = i - p.seci
case ':': case ':':
u.Infof("sss %s for %v", string(r), datestr)
if p.mini == 0 { if p.mini == 0 {
p.mini = i + 1 p.mini = i + 1
p.hourlen = i - p.houri p.hourlen = i - p.houri
@ -775,9 +822,10 @@ iterRunes:
} }
case timeOffset: case timeOffset:
// 19:55:00+0100
// timeOffsetColon // timeOffsetColon
// 15:04:05+07:00 // 15:04:05+07:00
// 15:04:05-07:00 // 15:04:05-07:00
if r == ':' { if r == ':' {
p.stateTime = timeOffsetColon p.stateTime = timeOffsetColon
} }
@ -801,6 +849,7 @@ iterRunes:
// Could be AM/PM or could be PST or similar // Could be AM/PM or could be PST or similar
p.stateTime = timeWsAMPMMaybe p.stateTime = timeWsAMPMMaybe
case '+', '-': case '+', '-':
p.offseti = i
p.stateTime = timeWsOffset p.stateTime = timeWsOffset
default: default:
if unicode.IsLetter(r) { if unicode.IsLetter(r) {
@ -819,6 +868,7 @@ iterRunes:
if r == 'M' { if r == 'M' {
//return parse("2006-01-02 03:04:05 PM", datestr, loc) //return parse("2006-01-02 03:04:05 PM", datestr, loc)
p.stateTime = timeWsAMPM p.stateTime = timeWsAMPM
p.set(i-1, "PM")
} else { } else {
p.stateTime = timeWsAlpha p.stateTime = timeWsAlpha
} }
@ -832,12 +882,18 @@ iterRunes:
// 00:12:00 +00:00 UTC // 00:12:00 +00:00 UTC
// timeWsOffsetAlpha // timeWsOffsetAlpha
// 00:12:00 +0000 UTC // 00:12:00 +0000 UTC
if r == ':' { switch r {
case ':':
p.stateTime = timeWsOffsetColon p.stateTime = timeWsOffsetColon
} else if unicode.IsLetter(r) { case ' ':
// 2015-02-18 00:12:00 +0000 UTC p.set(p.offseti, "-0700")
p.stateTime = timeWsOffsetAlpha p.stateTime = timeWsOffset
break iterTimeRunes default:
if unicode.IsLetter(r) {
// 00:12:00 +0000 UTC
p.stateTime = timeWsOffsetAlpha
break iterTimeRunes
}
} }
case timeWsOffsetColon: case timeWsOffsetColon:
@ -859,56 +915,111 @@ iterRunes:
// 15:04:05.999+07:00 // 15:04:05.999+07:00
// 15:04:05.999-07:00 // 15:04:05.999-07:00
// timePeriod // timePeriod
// 17:24:37.3186369 // 17:24:37.3186369
// 00:07:31.945167 // 00:07:31.945167
// 18:31:59.257000000 // 18:31:59.257000000
// 00:00:00.000 // 00:00:00.000
// timePeriodWs // timePeriodOffset
// timePeriodWsOffset // 19:55:00.799+0100
// 00:07:31.945167 +0000 // timePeriodOffsetColon
// 00:00:00.000 +0000 // 15:04:05.999-07:00
// timePeriodWsOffsetAlpha // timePeriodWs
// 00:07:31.945167 +0000 UTC // timePeriodWsOffset
// 00:00:00.000 +0000 UTC // 00:07:31.945167 +0000
// timePeriodWsAlpha // 00:00:00.000 +0000
// 06:20:00.000 UTC // timePeriodWsOffsetAlpha
// 00:07:31.945167 +0000 UTC
// 00:00:00.000 +0000 UTC
// timePeriodWsAlpha
// 06:20:00.000 UTC
switch r { switch r {
// case '.':
// p.stateTime = timePeriod
// p.seclen = i - p.seci
// p.msi = i + 1
case ' ': case ' ':
p.mslen = i - p.msi p.mslen = i - p.msi
p.stateTime = timePeriodWs p.stateTime = timePeriodWs
case '+', '-': case '+', '-':
// This really shouldn't happen
p.mslen = i - p.msi p.mslen = i - p.msi
p.offseti = i
p.stateTime = timePeriodOffset p.stateTime = timePeriodOffset
default: default:
if unicode.IsLetter(r) { if unicode.IsLetter(r) {
// 06:20:00.000 UTC // 06:20:00.000 UTC
p.mslen = i - p.msi p.mslen = i - p.msi
p.stateTime = timePeriodAlpha p.stateTime = timePeriodWsAlpha
} }
} }
case timePeriodOffset:
// timePeriodOffset
// 19:55:00.799+0100
// timePeriodOffsetColon
// 15:04:05.999-07:00
switch r {
case ':':
p.stateTime = timePeriodOffsetColon
default:
if unicode.IsLetter(r) {
// 00:07:31.945167 +0000 UTC
// 00:00:00.000 +0000 UTC
p.stateTime = timePeriodWsOffsetWsAlpha
break iterTimeRunes
}
}
case timePeriodOffsetColon:
// timePeriodOffset
// timePeriodOffsetColon
// 15:04:05.999-07:00
case timePeriodWs: case timePeriodWs:
if unicode.IsLetter(r) { // timePeriodWs
// 00:07:31.945167 +0000 UTC // timePeriodWsOffset
// 00:00:00.000 +0000 UTC // 00:07:31.945167 +0000
p.stateTime = timePeriodWsOffsetAlpha // 00:00:00.000 +0000
break iterTimeRunes // timePeriodWsOffsetAlpha
// 00:07:31.945167 +0000 UTC
// 00:00:00.000 +0000 UTC
// timePeriodWsAlpha
// 06:20:00.000 UTC
if p.offseti == 0 {
p.offseti = i
} }
switch r {
case '+', '-':
p.mslen = i - p.msi - 1
p.stateTime = timePeriodWsOffset
default:
if unicode.IsLetter(r) {
// 00:07:31.945167 +0000 UTC
// 00:00:00.000 +0000 UTC
p.stateTime = timePeriodWsOffsetWsAlpha
break iterTimeRunes
}
}
case timePeriodWsOffset: case timePeriodWsOffset:
// 00:07:31.945167 +0000
// 00:00:00.000 +0000 // timePeriodWs
// timePeriodWsOffsetAlpha // timePeriodWsOffset
// 00:07:31.945167 +0000 UTC // 00:07:31.945167 +0000
// 00:00:00.000 +0000 UTC // 00:00:00.000 +0000
if unicode.IsLetter(r) { // timePeriodWsOffsetAlpha
// 00:07:31.945167 +0000 UTC // 00:07:31.945167 +0000 UTC
// 00:00:00.000 +0000 UTC // 00:00:00.000 +0000 UTC
p.stateTime = timePeriodWsOffsetAlpha // timePeriodWsAlpha
break iterTimeRunes // 06:20:00.000 UTC
switch r {
case ' ':
p.set(p.offseti, "-0700")
case ':':
u.Errorf("timePeriodWsOffset UNHANDLED COLON")
default:
if unicode.IsLetter(r) {
// 00:07:31.945167 +0000 UTC
// 00:00:00.000 +0000 UTC
p.stateTime = timePeriodWsOffsetWsAlpha
break iterTimeRunes
}
} }
case timeZ: case timeZ:
// timeZ // timeZ
// 15:04:05.99Z // 15:04:05.99Z
@ -927,26 +1038,32 @@ iterRunes:
switch p.stateTime { switch p.stateTime {
case timePeriod: case timePeriod:
p.mslen = i - p.msi p.mslen = i - p.msi
case timeZ: case timeOffset:
u.Warnf("wtf? timeZ") // 19:55:00+0100
case timeZDigit: p.set(p.offseti, "-0700")
u.Warnf("got Z00:00") case timeOffsetColon:
// 15:04:05+07:00
p.set(p.offseti, "-07:00")
// case timeZ:
// u.Warnf("wtf? timeZ")
// case timeZDigit:
// u.Warnf("got timeZDigit Z00:00")
case timePeriodOffset:
// 19:55:00.799+0100
p.set(p.offseti, "-0700")
case timePeriodOffsetColon:
p.set(p.offseti, "-07:00")
case timePeriodWsOffset:
p.set(p.offseti, "-0700")
// case timePeriodWsOffsetWsAlpha:
// u.Warnf("timePeriodWsOffsetAlpha")
// case timeWsOffsetAlpha:
// u.Warnf("timeWsOffsetAlpha offseti=%d", p.offseti)
default: default:
u.Warnf("un-handled statetime: %d for %v", p.stateTime, p.datestr) //u.Warnf("un-handled statetime: %d for %v", p.stateTime, p.datestr)
} }
p.coalesceTime(i) p.coalesceTime(i)
switch p.stateTime {
case timeOffset:
// 15:04:05+0700
u.Warnf("not handled timeOffset?")
case timeOffsetColon:
// 15:04:05+07:00
u.Warnf("timeoffsetcolon ")
p.set(p.offseti, "-07:00")
case timeWsAMPMMaybe:
case timeZ:
}
} }
//u.Infof("%60s %q\n\t%+v", datestr, string(p.format), p) //u.Infof("%60s %q\n\t%+v", datestr, string(p.format), p)
@ -996,12 +1113,15 @@ iterRunes:
return t.In(loc), nil return t.In(loc), nil
} }
case dateDigitDash:
// 2006-01
return p.parse()
case dateDigitDashDash: case dateDigitDashDash:
// 2006-01-02 // 2006-01-02
// 2006-1-02 // 2006-1-02
// 2006-1-2 // 2006-1-2
// 2006-01-2 // 2006-01-2
// 2006-01
return p.parse() return p.parse()
case dateDigitDashDashAlpha: case dateDigitDashDashAlpha:
@ -1011,18 +1131,6 @@ iterRunes:
p.setDay() p.setDay()
return p.parse() return p.parse()
case dateDigitDashDashTZ: // starts digit then dash 02- then T Then Z
// 2006-01-02T15:04:05.999999999Z
// 2006-01-02T15:04:05.99999999Z
// 2006-01-02T15:04:05.9999999Z
// 2006-01-02T15:04:05.999999Z
// 2006-01-02T15:04:05.99999Z
// 2006-01-02T15:04:05.9999Z
// 2006-01-02T15:04:05.999Z
// 2006-01-02T15:04:05.99Z
// 2009-08-12T22:15Z -- No seconds/milliseconds
return p.parse()
case dateDigitDashDashWs: // starts digit then dash 02- then whitespace 1 << 2 << 5 + 3 case dateDigitDashDashWs: // starts digit then dash 02- then whitespace 1 << 2 << 5 + 3
// 2013-04-01 22:43:22 // 2013-04-01 22:43:22
// 2013-04-01 22:43 // 2013-04-01 22:43
@ -1031,191 +1139,25 @@ iterRunes:
case dateDigitDashDashT: case dateDigitDashDashT:
return p.parse() return p.parse()
/*
case dateDigitDashDashTOffset:
// 2006-01-02T15:04:05+0000
return p.parse()
case dateDigitDashDashTOffsetColon:
// With another +/- time-zone at end
// 2006-01-02T15:04:05.999999999+07:00
// 2006-01-02T15:04:05.999999999-07:00
// 2006-01-02T15:04:05.999999+07:00
// 2006-01-02T15:04:05.999999-07:00
// 2006-01-02T15:04:05.999+07:00
// 2006-01-02T15:04:05.999-07:00
// 2006-01-02T15:04:05+07:00
// 2006-01-02T15:04:05-07:00
return p.parse()
case dateDigitDashDashT: // starts digit then dash 02- then T
// 2006-01-02T15:04:05.999999
// 2006-01-02T15:04:05.999999
return p.parse()
case dateDigitDashDashTZDigit:
// With a time-zone at end after Z
// 2006-01-02T15:04:05.999999999Z07:00
// 2006-01-02T15:04:05Z07:00
// RFC3339 = "2006-01-02T15:04:05Z07:00"
// RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
return time.Time{}, fmt.Errorf("RFC339 Dates may not contain both Z & Offset for %q see https://github.com/golang/go/issues/5294", datestr)
case dateDigitDashDashWsWsOffset:
// 2006-01-02 15:04:05 -0700
return p.parse()
case dateDigitDashDashWsWsOffsetColon:
// 2006-01-02 15:04:05 -07:00
return p.parse()
case dateDigitDashDashWsWsOffsetAlpha:
// 2015-02-18 00:12:00 +0000 UTC
return p.parse()
case dateDigitDashDashWsWsOffsetColonAlpha:
// 2015-02-18 00:12:00 +00:00 UTC
return p.parse()
case dateDigitDashDashWsOffset:
// 2017-07-19 03:21:51+00:00
return p.parse()
case dateDigitDashDashWsWsAlpha:
// 2014-12-16 06:20:00 UTC
return p.parse()
// if len(datestr) > len("2006-01-02 03:04:05") {
// t, err := parse("2006-01-02 03:04:05", datestr[:len("2006-01-02 03:04:05")], loc)
// if err == nil {
// return t, nil
// }
// }
case dateDigitDashDashWsPeriod:
// 2012-08-03 18:31:59.257000000
// 2014-04-26 17:24:37.3186369
// 2017-01-27 00:07:31.945167
// 2016-03-14 00:00:00.000
return p.parse()
case dateDigitDashDashWsPeriodAlpha:
// 2012-08-03 18:31:59.257000000 UTC
// 2014-04-26 17:24:37.3186369 UTC
// 2017-01-27 00:07:31.945167 UTC
// 2016-03-14 00:00:00.000 UTC
return p.parse()
case dateDigitDashDashWsPeriodOffset:
// 2012-08-03 18:31:59.257000000 +0000
// 2014-04-26 17:24:37.3186369 +0000
// 2017-01-27 00:07:31.945167 +0000
// 2016-03-14 00:00:00.000 +0000
return p.parse()
case dateDigitDashDashWsPeriodOffsetAlpha:
// 2012-08-03 18:31:59.257000000 +0000 UTC
// 2014-04-26 17:24:37.3186369 +0000 UTC
// 2017-01-27 00:07:31.945167 +0000 UTC
// 2016-03-14 00:00:00.000 +0000 UTC
return p.parse()
*/
case dateDigitDotDot: case dateDigitDotDot:
switch { // 03.31.1981
case len(datestr) == len("01.02.2006"): // 3.2.1981
return parse("01.02.2006", datestr, loc) // 3.2.81
case len(datestr)-p.part2Len == 3: p.yearlen = i - p.yeari
for _, layout := range []string{"01.02.06", "1.02.06", "01.2.06", "1.2.06"} { return p.parse()
if t, err := parse(layout, datestr, loc); err == nil {
return t, nil
}
}
default:
for _, layout := range []string{"1.02.2006", "01.2.2006", "1.2.2006"} {
if t, err := parse(layout, datestr, loc); err == nil {
return t, nil
}
}
}
case dateDigitWs: case dateDigitWs:
// 18 January 2018 // 18 January 2018
// 8 January 2018 // 8 January 2018
if p.part1Len == 1 { return p.parse()
return parse("2 January 2006", datestr, loc)
} case dateDigitWsMoYear:
return parse("02 January 2006", datestr, loc)
// 02 Jan 2018 23:59
case dateDigitWsMoShortColon:
// 2 Jan 2018 23:59 // 2 Jan 2018 23:59
// 02 Jan 2018 23:59 // 02 Jan 2018 23:59
if p.part1Len == 1 {
for _, layout := range []string{
"2 Jan 2006 15:04",
"2 Jan 2006 15:4",
} {
if t, err := parse(layout, datestr, loc); err == nil {
return t, nil
}
}
}
for _, layout := range []string{
"02 Jan 2006 15:04",
"02 Jan 2006 15:4",
} {
if t, err := parse(layout, datestr, loc); err == nil {
return t, nil
}
}
case dateDigitWsMoShortColonColon:
// 02 Jan 2018 23:59:45 // 02 Jan 2018 23:59:45
if p.part1Len == 1 {
for _, layout := range []string{
"2 Jan 2006 15:04:05",
"2 Jan 2006 15:04:5",
"2 Jan 2006 15:4:5",
"2 Jan 2006 15:4:05",
} {
if t, err := parse(layout, datestr, loc); err == nil {
return t, nil
}
}
}
for _, layout := range []string{
"2 Jan 2006 15:04:05",
"2 Jan 2006 15:04:5",
"2 Jan 2006 15:4:5",
"2 Jan 2006 15:4:05",
} {
if t, err := parse(layout, datestr, loc); err == nil {
return t, nil
}
}
case dateDigitWsMoShortComma:
// 12 Feb 2006, 19:17 // 12 Feb 2006, 19:17
// 12 Feb 2006, 19:17:22 // 12 Feb 2006, 19:17:22
for _, layout := range []string{ return p.parse()
"02 Jan 2006, 15:04",
"02 Jan 2006, 15:4",
"2 Jan 2006, 15:04",
"2 Jan 2006, 15:4",
"02 Jan 2006, 15:04:05",
"02 Jan 2006, 15:4:05",
"02 Jan 2006, 15:4:5",
"02 Jan 2006, 15:04:5",
"2 Jan 2006, 15:04:05",
"2 Jan 2006, 15:04:5",
"2 Jan 2006, 15:4:5",
"2 Jan 2006, 15:4:05",
} {
if t, err := parse(layout, datestr, loc); err == nil {
return t, nil
}
}
case dateAlphaWSDigitCommaWsYear: case dateAlphaWSDigitCommaWsYear:
// May 8, 2009 5:57:51 PM // May 8, 2009 5:57:51 PM
@ -1483,7 +1425,7 @@ iterRunes:
return parse("Mon, _2 Jan 2006 15:04:05 -0700 (MST)", datestr, loc) return parse("Mon, _2 Jan 2006 15:04:05 -0700 (MST)", datestr, loc)
} }
u.Warnf("no format for %d %d %s", p.stateDate, p.stateTime, p.datestr) //u.Warnf("no format for %d %d %s", p.stateDate, p.stateTime, p.datestr)
return time.Time{}, fmt.Errorf("Could not find date format for %s", datestr) return time.Time{}, fmt.Errorf("Could not find date format for %s", datestr)
} }

View File

@ -106,6 +106,13 @@ func TestInLocation(t *testing.T) {
assert.Equal(t, "2006-01-02 22:04:05 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) assert.Equal(t, "2006-01-02 22:04:05 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
} }
func TestOne(t *testing.T) {
time.Local = time.UTC
var ts time.Time
ts = MustParse("03 February 2013")
assert.Equal(t, "2013-02-03 00:00:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
}
func TestParse(t *testing.T) { func TestParse(t *testing.T) {
// Lets ensure we are operating on UTC // Lets ensure we are operating on UTC
@ -632,3 +639,21 @@ func testDidPanic(datestr string) (paniced bool) {
MustParse(datestr) MustParse(datestr)
return false return false
} }
func TestPStruct(t *testing.T) {
denverLoc, err := time.LoadLocation("America/Denver")
assert.Equal(t, nil, err)
p := newParser("08.21.71", denverLoc)
p.setMonth()
assert.Equal(t, 0, p.moi)
p.setDay()
assert.Equal(t, 0, p.dayi)
p.set(-1, "not")
p.set(15, "not")
assert.Equal(t, "08.21.71", p.datestr)
assert.Equal(t, "08.21.71", string(p.format))
}