diff --git a/parseany.go b/parseany.go index a31ae54..29c3ff8 100644 --- a/parseany.go +++ b/parseany.go @@ -61,8 +61,10 @@ const ( stateAlphaWSAlphaColonAlphaOffset stateAlphaWSAlphaColonAlphaOffsetAlpha stateWeekdayComma + stateWeekdayCommaDash stateWeekdayCommaOffset stateWeekdayAbbrevComma + stateWeekdayAbbrevCommaDash stateWeekdayAbbrevCommaOffset stateWeekdayAbbrevCommaOffsetZone ) @@ -127,6 +129,7 @@ func parseTime(datestr string, loc *time.Location) (time.Time, error) { part1Len := 0 part2Len := 0 + dayLen := 0 // General strategy is to read rune by rune through the date looking for // certain hints of what type of date we are dealing with. @@ -495,13 +498,16 @@ iterRunes: // May 8, 2009 5:57:51 PM // // stateWeekdayComma - // Monday, 02-Jan-06 15:04:05 MST + // Monday, 02 Jan 2006 15:04:05 MST + // stateWeekdayCommaDash + // Monday, 02-Jan-06 15:04:05 MST // stateWeekdayCommaOffset // Monday, 02 Jan 2006 15:04:05 -0700 // Monday, 02 Jan 2006 15:04:05 +0100 // stateWeekdayAbbrevComma - // Mon, 02-Jan-06 15:04:05 MST // Mon, 02 Jan 2006 15:04:05 MST + // stateWeekdayAbbrevCommaDash + // Mon, 02-Jan-06 15:04:05 MST // stateWeekdayAbbrevCommaOffset // Mon, 02 Jan 2006 15:04:05 -0700 // Thu, 13 Jul 2017 08:58:40 +0100 @@ -513,47 +519,35 @@ iterRunes: case r == ' ': state = stateAlphaWS case r == ',': + part1Len = i if i == 3 { state = stateWeekdayAbbrevComma } else { state = stateWeekdayComma } + i++ } case stateWeekdayComma: // Starts alpha then comma - // Mon, 02-Jan-06 15:04:05 MST - // Mon, 02 Jan 2006 15:04:05 MST + // Monday, 02 Jan 2006 15:04:05 MST + // stateWeekdayCommaDash + // Monday, 02-Jan-06 15:04:05 MST // stateWeekdayCommaOffset // Monday, 02 Jan 2006 15:04:05 -0700 // Monday, 02 Jan 2006 15:04:05 +0100 switch { case r == '-': if i < 15 { - for _, layout := range []string{ - "Monday, 02-Jan-06 15:04:05 MST", - "Monday, 02-Jan-06 15:4:05 MST", - "Monday, 02-Jan-06 15:04:5 MST", - "Monday, 02-Jan-06 15:4:5 MST", - "Monday, 2-Jan-06 15:04:05 MST", - "Monday, 2-Jan-06 15:4:05 MST", - "Monday, 2-Jan-06 15:4:5 MST", - "Monday, 2-Jan-06 15:04:5 MST", - "Monday, 2-Jan-6 15:04:05 MST", - "Monday, 2-Jan-6 15:4:05 MST", - "Monday, 2-Jan-6 15:4:5 MST", - "Monday, 2-Jan-6 15:04:5 MST", - } { - if t, err := parse(layout, datestr, loc); err == nil { - return t, nil - } - } + state = stateWeekdayCommaDash + break iterRunes } state = stateWeekdayCommaOffset case r == '+': state = stateWeekdayCommaOffset } case stateWeekdayAbbrevComma: // Starts alpha then comma - // Mon, 02-Jan-06 15:04:05 MST // Mon, 02 Jan 2006 15:04:05 MST + // stateWeekdayAbbrevCommaDash + // Mon, 02-Jan-06 15:04:05 MST // stateWeekdayAbbrevCommaOffset // Mon, 02 Jan 2006 15:04:05 -0700 // Thu, 13 Jul 2017 08:58:40 +0100 @@ -561,26 +555,12 @@ iterRunes: // stateWeekdayAbbrevCommaOffsetZone // Tue, 11 Jul 2017 16:28:13 +0200 (CEST) switch { + case r == ' ' && dayLen == 0: + dayLen = i - part1Len - 2 case r == '-': if i < 15 { - for _, layout := range []string{ - "Mon, 02-Jan-06 15:04:05 MST", - "Mon, 02-Jan-06 15:4:05 MST", - "Mon, 02-Jan-06 15:04:5 MST", - "Mon, 02-Jan-06 15:4:5 MST", - "Mon, 2-Jan-06 15:04:05 MST", - "Mon, 2-Jan-06 15:4:05 MST", - "Mon, 2-Jan-06 15:4:5 MST", - "Mon, 2-Jan-06 15:04:5 MST", - "Mon, 2-Jan-6 15:04:05 MST", - "Mon, 2-Jan-6 15:4:05 MST", - "Mon, 2-Jan-6 15:4:5 MST", - "Mon, 2-Jan-6 15:04:5 MST", - } { - if t, err := parse(layout, datestr, loc); err == nil { - return t, nil - } - } + state = stateWeekdayAbbrevCommaDash + break iterRunes } state = stateWeekdayAbbrevCommaOffset case r == '+': @@ -1474,6 +1454,27 @@ iterRunes: } } + case stateWeekdayCommaDash: + // Monday, 02-Jan-06 15:04:05 MST + for _, layout := range []string{ + "Monday, 02-Jan-06 15:04:05 MST", + "Monday, 02-Jan-06 15:4:05 MST", + "Monday, 02-Jan-06 15:04:5 MST", + "Monday, 02-Jan-06 15:4:5 MST", + "Monday, 2-Jan-06 15:04:05 MST", + "Monday, 2-Jan-06 15:4:05 MST", + "Monday, 2-Jan-06 15:4:5 MST", + "Monday, 2-Jan-06 15:04:5 MST", + "Monday, 2-Jan-6 15:04:05 MST", + "Monday, 2-Jan-6 15:4:05 MST", + "Monday, 2-Jan-6 15:4:5 MST", + "Monday, 2-Jan-6 15:04:5 MST", + } { + if t, err := parse(layout, datestr, loc); err == nil { + return t, nil + } + } + case stateWeekdayAbbrevComma: // Starts alpha then comma // Mon, 02-Jan-06 15:04:05 MST // Mon, 02 Jan 2006 15:04:05 MST @@ -1488,6 +1489,28 @@ iterRunes: } } + case stateWeekdayAbbrevCommaDash: + // Mon, 02-Jan-06 15:04:05 MST + // Mon, 2-Jan-06 15:04:05 MST + for _, layout := range []string{ + "Mon, 02-Jan-06 15:04:05 MST", + "Mon, 02-Jan-06 15:4:05 MST", + "Mon, 02-Jan-06 15:04:5 MST", + "Mon, 02-Jan-06 15:4:5 MST", + "Mon, 2-Jan-06 15:04:05 MST", + "Mon, 2-Jan-06 15:4:05 MST", + "Mon, 2-Jan-06 15:4:5 MST", + "Mon, 2-Jan-06 15:04:5 MST", + "Mon, 2-Jan-6 15:04:05 MST", + "Mon, 2-Jan-6 15:4:05 MST", + "Mon, 2-Jan-6 15:4:5 MST", + "Mon, 2-Jan-6 15:04:5 MST", + } { + if t, err := parse(layout, datestr, loc); err == nil { + return t, nil + } + } + case stateWeekdayAbbrevCommaOffset: // Mon, 02 Jan 2006 15:04:05 -0700 // Thu, 13 Jul 2017 08:58:40 +0100 @@ -1507,7 +1530,10 @@ iterRunes: case stateWeekdayAbbrevCommaOffsetZone: // Tue, 11 Jul 2017 16:28:13 +0200 (CEST) - return parse("Mon, _2 Jan 2006 15:04:05 -0700 (CEST)", datestr, loc) + if dayLen == 1 { + 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) } return time.Time{}, fmt.Errorf("Could not find date format for %s", datestr) diff --git a/parseany_test.go b/parseany_test.go index 4cb400c..543ad37 100644 --- a/parseany_test.go +++ b/parseany_test.go @@ -38,6 +38,9 @@ func TestInLocation(t *testing.T) { assert.Equal(t, "UTC", zone, "Should have found zone = UTC %v", zone) assert.Equal(t, "2013-02-01 00:00:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) + ts = MustParse("Tue, 5 Jul 2017 16:28:13 -0700 (MST)") + assert.Equal(t, "2017-07-05 23:28:13 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) + // Now we are going to use ParseIn() and see that it gives different answer // with different zone, offset time.Local = nil @@ -178,6 +181,9 @@ func TestParse(t *testing.T) { ts = MustParse("Tue, 11 Jul 2017 16:28:13 +0200 (CEST)") assert.Equal(t, "2017-07-11 14:28:13 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) + ts = MustParse("Tue, 5 Jul 2017 16:28:13 -0700 (CEST)") + assert.Equal(t, "2017-07-05 23:28:13 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) + ts = MustParse("Thu, 13 Jul 2017 08:58:40 +0100") assert.Equal(t, "2017-07-13 07:58:40 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))