mirror of
https://github.com/araddon/dateparse.git
synced 2024-11-10 11:51:54 +08:00
time-parse fixes
This commit is contained in:
parent
7825aa09f1
commit
20cd681f46
570
parseany.go
570
parseany.go
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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))
|
||||||
|
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user