diff --git a/parseany.go b/parseany.go index eaec7d0..ffa713a 100644 --- a/parseany.go +++ b/parseany.go @@ -9,8 +9,15 @@ import ( "time" "unicode" "unicode/utf8" + + "github.com/araddon/gou" ) +func init() { + gou.SetupLogging("debug") + gou.SetColorOutput() +} + type dateState uint8 type timeState uint8 @@ -55,6 +62,7 @@ const ( timeWsAMPMMaybe timeWsAMPM timeWsOffset + timeWsOffsetWs timeWsOffsetAlpha timeWsOffsetColonAlpha timeWsOffsetColon @@ -278,7 +286,7 @@ func (p *parser) parse() (time.Time, error) { p.format = p.format[p.skip:] p.datestr = p.datestr[p.skip:] } - //gou.Debugf("parse %q AS %s", p.datestr, string(p.format)) + gou.Debugf("parse %q AS %s", p.datestr, string(p.format)) if p.loc == nil { return time.Parse(string(p.format), p.datestr) } @@ -715,11 +723,13 @@ iterRunes: // Fri Jul 03 2015 18:04:07 GMT+0100 (GMT Daylight Time) if r == ' ' { if p.dayi > 0 { + p.daylen = i - p.dayi p.setDay() p.yeari = i + 1 p.stateDate = dateAlphaWsAlphaYearmaybe p.stateTime = timeStart + gou.Infof("%d %s dateAlphaWsAlpha %s %s", i, string(r), p.ds(), p.ts()) } } else if unicode.IsDigit(r) { if p.dayi == 0 { @@ -734,6 +744,7 @@ iterRunes: i = i - 3 p.stateDate = dateAlphaWsAlpha p.yeari = 0 + gou.Warnf("hm, not year") break iterRunes } else if r == ' ' { // must be year format, not 15:04 @@ -757,6 +768,8 @@ iterRunes: for ; i < len(datestr); i++ { r := rune(datestr[i]) + gou.Debugf("%d %s iterTimeRunes %s %s", i, string(r), p.ds(), p.ts()) + switch p.stateTime { case timeStart: // 22:43:22 @@ -850,6 +863,7 @@ iterRunes: // 15:04:05 -0700 // timeWsOffsetColon // 15:04:05 -07:00 + // 17:57:51 -0700 2009 // timeWsOffsetColonAlpha // 00:12:00 +00:00 UTC // timeWsOffsetAlpha @@ -858,6 +872,7 @@ iterRunes: // 00:12:00 2008 // timeZ // 15:04:05.99Z + gou.Infof("timeWs") switch r { case 'A', 'P': // Could be AM/PM or could be PST or similar @@ -954,18 +969,22 @@ iterRunes: case timeWsOffset: // timeWsOffset // 15:04:05 -0700 + // timeWsOffsetWs + // 17:57:51 -0700 2009 // timeWsOffsetColon // 15:04:05 -07:00 // timeWsOffsetColonAlpha // 00:12:00 +00:00 UTC // timeWsOffsetAlpha // 00:12:00 +0000 UTC + gou.Infof("timeWsOffset") switch r { case ':': p.stateTime = timeWsOffsetColon case ' ': p.set(p.offseti, "-0700") - p.stateTime = timeWsOffset + gou.Warnf("end of offset?") + p.stateTime = timeWsOffsetWs default: if unicode.IsLetter(r) { // 00:12:00 +0000 UTC @@ -973,6 +992,7 @@ iterRunes: break iterTimeRunes } } + case timeWsOffsetWs: case timeWsOffsetColon: // timeWsOffsetColon @@ -1117,6 +1137,8 @@ iterRunes: p.set(p.offseti, "-0700") case timeWsOffset: p.set(p.offseti, "-0700") + case timeWsOffsetWs: + // 17:57:51 -0700 2009 case timeOffsetColon: // 15:04:05+07:00 p.set(p.offseti, "-07:00") diff --git a/parseany_test.go b/parseany_test.go index 904f649..b104b3f 100644 --- a/parseany_test.go +++ b/parseany_test.go @@ -124,22 +124,32 @@ type dateTest struct { in, out string } +// {in: , out: }, + var testInputs = []dateTest{ {in: "oct 7, 1970", out: "1970-10-07 00:00:00 +0000 UTC"}, {in: "oct 7, '70", out: "1970-10-07 00:00:00 +0000 UTC"}, + {in: "Oct 7, '70", out: "1970-10-07 00:00:00 +0000 UTC"}, + {in: "Feb 8, 2009 5:57:51 AM", out: "2009-02-08 05:57:51 +0000 UTC"}, + {in: "May 8, 2009 5:57:51 PM", out: "2009-05-08 17:57:51 +0000 UTC"}, + {in: "May 8, 2009 5:57:1 PM", out: "2009-05-08 17:57:01 +0000 UTC"}, + {in: "May 8, 2009 5:7:51 PM", out: "2009-05-08 17:07:51 +0000 UTC"}, {in: "7 oct 70", out: "1970-10-07 00:00:00 +0000 UTC"}, {in: "7 oct 1970", out: "1970-10-07 00:00:00 +0000 UTC"}, + // ANSIC = "Mon Jan _2 15:04:05 2006" + {in: "Mon Jan 2 15:04:05 2006", out: "2006-01-02 15:04:05 +0000 UTC"}, + {in: "Thu May 8 17:57:51 2009", out: "2009-05-08 17:57:51 +0000 UTC"}, + {in: "Thu May 8 17:57:51 2009", out: "2009-05-08 17:57:51 +0000 UTC"}, + // RubyDate = "Mon Jan 02 15:04:05 -0700 2006" + {in: "Mon Jan 02 15:04:05 -0700 2006", out: "2006-01-02 22:04:05 +0000 UTC"}, + {in: "Thu May 08 17:57:51 -0700 2009", out: "2009-05-08 17:57:51 +0000 UTC"}, + // UnixDate = "Mon Jan _2 15:04:05 MST 2006" + {in: "Mon Jan 2 15:04:05 MST 2006", out: "2006-01-02 15:04:05 +0000 UTC"}, + {in: "Thu May 8 17:57:51 MST 2009", out: "2009-05-08 17:57:51 +0000 UTC"}, } func TestParse(t *testing.T) { - /* - TODO: - - move to testharness - - replace all the default go dates 2006 with others - - more tests on AM/PM zones, offsets for each variation - */ - // Lets ensure we are operating on UTC time.Local = time.UTC @@ -156,29 +166,6 @@ func TestParse(t *testing.T) { assert.Equal(t, th.out, got, "Expected %q but got %q from %q", th.out, got, th.in) } - // TODO: Is a utf8 date valid? - // ts = MustParse("2014-04\u221226") - // assert.Equal(t, "2014-04-26 00:00:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) - - ts = MustParse("May 8, 2009 5:57:51 PM") - assert.Equal(t, "2009-05-08 17:57:51 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) - ts = MustParse("May 8, 2009 5:57:1 PM") - assert.Equal(t, "2009-05-08 17:57:01 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) - ts = MustParse("May 8, 2009 5:7:51 PM") - assert.Equal(t, "2009-05-08 17:07:51 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) - - // ANSIC = "Mon Jan _2 15:04:05 2006" - ts = MustParse("Mon Jan 2 15:04:05 2006") - assert.Equal(t, "2006-01-02 15:04:05 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) - - // RubyDate = "Mon Jan 02 15:04:05 -0700 2006" - ts = MustParse("Mon Jan 02 15:04:05 -0700 2006") - assert.Equal(t, "2006-01-02 22:04:05 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)), "%v") - - // UnixDate = "Mon Jan _2 15:04:05 MST 2006" - ts = MustParse("Mon Jan 2 15:04:05 MST 2006") - assert.Equal(t, "2006-01-02 15:04:05 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) - // RFC850 = "Monday, 02-Jan-06 15:04:05 MST" ts = MustParse("Wednesday, 07-May-09 08:00:43 MST") assert.Equal(t, "2009-05-07 08:00:43 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))