From 375d67e59fcbf448d56118166d22c67335a2be3e Mon Sep 17 00:00:00 2001 From: Aaron Raddon Date: Thu, 10 Jul 2014 15:25:23 -0700 Subject: [PATCH] update to handle yyyy/?? formats --- parseany.go | 161 +++++++++++++++++++++++++++++++++++++---------- parseany_test.go | 65 +++++++++++++++++-- 2 files changed, 187 insertions(+), 39 deletions(-) diff --git a/parseany.go b/parseany.go index d4a0bbd..e3c8ae4 100644 --- a/parseany.go +++ b/parseany.go @@ -40,6 +40,8 @@ func ParseAny(datestr string) (time.Time, error) { state := ST_START + firstSlash := 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. // Hopefully we only need to read about 5 or 6 bytes before @@ -51,6 +53,7 @@ iterRunes: i += (bytesConsumed - 1) } + //u.Infof("char=%s i=%d datestr=%s", r, i, datestr) switch state { case ST_START: if unicode.IsDigit(r) { @@ -71,6 +74,7 @@ iterRunes: state = ST_DIGITCOLON case '/': state = ST_DIGITSLASH + firstSlash = i } case ST_DIGITDASH: // starts digit then dash 02- // 2006-01-02T15:04:05Z07:00 @@ -135,6 +139,7 @@ iterRunes: } } case ST_DIGITSLASH: // starts digit then slash 02/ + // 2014/07/10 06:55:38.156283 // 03/19/2012 10:11:59 // 04/2/2014 03:00:37 // 3/1/2012 10:11:59 @@ -150,6 +155,7 @@ iterRunes: state = ST_DIGITSLASHWS } case ST_DIGITSLASHWS: // starts digit then slash 02/ more digits/slashes then whitespace + // 2014/07/10 06:55:38.156283 // 03/19/2012 10:11:59 // 04/2/2014 03:00:37 // 3/1/2012 10:11:59 @@ -159,6 +165,7 @@ iterRunes: state = ST_DIGITSLASHWSCOLON } case ST_DIGITSLASHWSCOLON: // starts digit then slash 02/ more digits/slashes then whitespace + // 2014/07/10 06:55:38.156283 // 03/19/2012 10:11:59 // 04/2/2014 03:00:37 // 3/1/2012 10:11:59 @@ -315,72 +322,158 @@ iterRunes: // 3/1/2014 // 10/13/2014 // 01/02/2006 - - if len(datestr) == len("01/02/2006") { - if t, err := time.Parse("01/02/2006", datestr); err == nil { - return t, nil + // 2014/10/13 + if firstSlash == 4 { + if len(datestr) == len("2006/01/02") { + if t, err := time.Parse("2006/01/02", datestr); err == nil { + return t, nil + } else { + u.Errorf("hm: %v %s", err, datestr) + return time.Time{}, err + } } else { - return time.Time{}, err + if t, err := time.Parse("2006/1/2", datestr); err == nil { + return t, nil + } else { + return time.Time{}, err + } } } else { - if t, err := time.Parse("1/2/2006", datestr); err == nil { - return t, nil + if len(datestr) == len("01/02/2006") { + if t, err := time.Parse("01/02/2006", datestr); err == nil { + return t, nil + } else { + return time.Time{}, err + } } else { - return time.Time{}, err + if t, err := time.Parse("1/2/2006", datestr); err == nil { + return t, nil + } else { + return time.Time{}, err + } } } case ST_DIGITSLASHWSCOLON: // starts digit then slash 02/ more digits/slashes then whitespace // 4/8/2014 22:05 - if len(datestr) == len("01/02/2006 15:04") { - if t, err := time.Parse("01/02/2006 15:04", datestr); err == nil { - return t, nil + // 04/08/2014 22:05 + // 2014/4/8 22:05 + // 2014/04/08 22:05 + if firstSlash == 4 { + if len(datestr) == len("2006/01/02 15:04") { + if t, err := time.Parse("2006/01/02 15:04", datestr); err == nil { + return t, nil + } else { + return time.Time{}, err + } + } else if len(datestr) == len("2006/01/2 15:04") { + if t, err := time.Parse("2006/01/2 15:04", datestr); err == nil { + return t, nil + } else { + if t, err := time.Parse("2006/1/02 15:04", datestr); err == nil { + return t, nil + } else { + return time.Time{}, err + } + } } else { - return time.Time{}, err - } - } else if len(datestr) == len("01/2/2006 15:04") { - if t, err := time.Parse("01/2/2006 15:04", datestr); err == nil { - return t, nil - } else { - if t, err := time.Parse("1/02/2006 15:04", datestr); err == nil { + if t, err := time.Parse("2006/1/2 15:04", datestr); err == nil { return t, nil } else { return time.Time{}, err } } } else { - if t, err := time.Parse("1/2/2006 15:04", datestr); err == nil { - return t, nil + if len(datestr) == len("01/02/2006 15:04") { + if t, err := time.Parse("01/02/2006 15:04", datestr); err == nil { + return t, nil + } else { + return time.Time{}, err + } + } else if len(datestr) == len("01/2/2006 15:04") { + if t, err := time.Parse("01/2/2006 15:04", datestr); err == nil { + return t, nil + } else { + if t, err := time.Parse("1/02/2006 15:04", datestr); err == nil { + return t, nil + } else { + return time.Time{}, err + } + } } else { - return time.Time{}, err + if t, err := time.Parse("1/2/2006 15:04", datestr); err == nil { + return t, nil + } else { + return time.Time{}, err + } } } case ST_DIGITSLASHWSCOLONCOLON: // starts digit then slash 02/ more digits/slashes then whitespace double colons + // 2014/07/10 06:55:38.156283 // 03/19/2012 10:11:59 // 3/1/2012 10:11:59 // 03/1/2012 10:11:59 // 3/01/2012 10:11:59 - if len(datestr) == len("01/02/2006 15:04:05") { - if t, err := time.Parse("01/02/2006 15:04:05", datestr); err == nil { - return t, nil + + if firstSlash == 4 { + if len(datestr) == len("2014/07/10 06:55:38.156283") { + if t, err := time.Parse("2006/01/02 15:04:05.000000", datestr); err == nil { + return t, nil + } else { + return time.Time{}, err + } + } else if len(datestr) == len("2006/01/02 15:04:05") { + if t, err := time.Parse("2006/01/02 15:04:05", datestr); err == nil { + return t, nil + } else { + return time.Time{}, err + } + } else if len(datestr) == len("2006/01/2 15:04:05") { + if t, err := time.Parse("2006/01/2 15:04:05", datestr); err == nil { + return t, nil + } else { + if t, err := time.Parse("2006/1/02 15:04:05", datestr); err == nil { + return t, nil + } else { + return time.Time{}, err + } + } } else { - return time.Time{}, err - } - } else if len(datestr) == len("01/2/2006 15:04:05") { - if t, err := time.Parse("01/2/2006 15:04:05", datestr); err == nil { - return t, nil - } else { - if t, err := time.Parse("1/02/2006 15:04:05", datestr); err == nil { + if t, err := time.Parse("2006/1/2 15:04:05", datestr); err == nil { return t, nil } else { return time.Time{}, err } } } else { - if t, err := time.Parse("1/2/2006 15:04:05", datestr); err == nil { - return t, nil + if len(datestr) == len("07/10/2014 06:55:38.156283") { + if t, err := time.Parse("01/02/2006 15:04:05.000000", datestr); err == nil { + return t, nil + } else { + return time.Time{}, err + } + } else if len(datestr) == len("01/02/2006 15:04:05") { + if t, err := time.Parse("01/02/2006 15:04:05", datestr); err == nil { + return t, nil + } else { + return time.Time{}, err + } + } else if len(datestr) == len("01/2/2006 15:04:05") { + if t, err := time.Parse("01/2/2006 15:04:05", datestr); err == nil { + return t, nil + } else { + if t, err := time.Parse("1/02/2006 15:04:05", datestr); err == nil { + return t, nil + } else { + return time.Time{}, err + } + } } else { - return time.Time{}, err + if t, err := time.Parse("1/2/2006 15:04:05", datestr); err == nil { + return t, nil + } else { + return time.Time{}, err + } } } case ST_ALPHACOMMA: // Starts alpha then comma but no DASH diff --git a/parseany_test.go b/parseany_test.go index ff4037c..957fa55 100644 --- a/parseany_test.go +++ b/parseany_test.go @@ -35,6 +35,7 @@ import ( Apr 7, 2014 4:58:55 PM + 2014/07/10 06:55:38.156283 03/19/2012 10:11:59 04/2/2014 03:00:37 3/1/2014 @@ -89,10 +90,8 @@ func TestParse(t *testing.T) { //u.Debug(ts.In(time.UTC).Unix(), ts.In(time.UTC)) //assert.T(t, "2006-01-02 15:04:05 +0000 UTC" == fmt.Sprintf("%v", ts.In(time.UTC))) - ts, err = ParseAny("03/19/2012 10:11:59") - assert.Tf(t, err == nil, "%v", err) - //u.Debug(ts.In(time.UTC).Unix(), ts.In(time.UTC)) - assert.T(t, "2012-03-19 10:11:59 +0000 UTC" == fmt.Sprintf("%v", ts.In(time.UTC))) + //--------------------------------------------- + // mm/dd/yyyy ? ts, err = ParseAny("3/31/2014") assert.Tf(t, err == nil, "%v", err) @@ -124,11 +123,61 @@ func TestParse(t *testing.T) { //u.Debug(ts.In(time.UTC).Unix(), ts.In(time.UTC)) assert.T(t, "2014-04-02 03:00:51 +0000 UTC" == fmt.Sprintf("%v", ts.In(time.UTC))) - ts, err = ParseAny("1332151919") + ts, err = ParseAny("03/19/2012 10:11:59") assert.Tf(t, err == nil, "%v", err) //u.Debug(ts.In(time.UTC).Unix(), ts.In(time.UTC)) assert.T(t, "2012-03-19 10:11:59 +0000 UTC" == fmt.Sprintf("%v", ts.In(time.UTC))) + ts, err = ParseAny("03/19/2012 10:11:59.3186369") + assert.Tf(t, err == nil, "%v", err) + //u.Debug(ts.In(time.UTC).Unix(), ts.In(time.UTC)) + assert.T(t, "2012-03-19 10:11:59.3186369 +0000 UTC" == fmt.Sprintf("%v", ts.In(time.UTC))) + + //--------------------------------------------- + // yyyy/mm/dd ? + + ts, err = ParseAny("2014/3/31") + assert.Tf(t, err == nil, "%v", err) + //u.Debug(ts.In(time.UTC).Unix(), ts.In(time.UTC)) + assert.T(t, "2014-03-31 00:00:00 +0000 UTC" == fmt.Sprintf("%v", ts.In(time.UTC))) + + ts, err = ParseAny("2014/03/31") + assert.Tf(t, err == nil, "%v", err) + //u.Debug(ts.In(time.UTC).Unix(), ts.In(time.UTC)) + assert.T(t, "2014-03-31 00:00:00 +0000 UTC" == fmt.Sprintf("%v", ts.In(time.UTC))) + + ts, err = ParseAny("2014/4/8 22:05") + assert.Tf(t, err == nil, "%v", err) + //u.Debug(ts.In(time.UTC).Unix(), ts.In(time.UTC)) + assert.T(t, "2014-04-08 22:05:00 +0000 UTC" == fmt.Sprintf("%v", ts.In(time.UTC))) + + ts, err = ParseAny("2014/04/08 22:05") + assert.Tf(t, err == nil, "%v", err) + //u.Debug(ts.In(time.UTC).Unix(), ts.In(time.UTC)) + assert.T(t, "2014-04-08 22:05:00 +0000 UTC" == fmt.Sprintf("%v", ts.In(time.UTC))) + + ts, err = ParseAny("2014/04/2 03:00:51") + assert.Tf(t, err == nil, "%v", err) + //u.Debug(ts.In(time.UTC).Unix(), ts.In(time.UTC)) + assert.T(t, "2014-04-02 03:00:51 +0000 UTC" == fmt.Sprintf("%v", ts.In(time.UTC))) + + ts, err = ParseAny("2014/4/02 03:00:51") + assert.Tf(t, err == nil, "%v", err) + //u.Debug(ts.In(time.UTC).Unix(), ts.In(time.UTC)) + assert.T(t, "2014-04-02 03:00:51 +0000 UTC" == fmt.Sprintf("%v", ts.In(time.UTC))) + + ts, err = ParseAny("2012/03/19 10:11:59") + assert.Tf(t, err == nil, "%v", err) + //u.Debug(ts.In(time.UTC).Unix(), ts.In(time.UTC)) + assert.T(t, "2012-03-19 10:11:59 +0000 UTC" == fmt.Sprintf("%v", ts.In(time.UTC))) + + ts, err = ParseAny("2012/03/19 10:11:59.3186369") + assert.Tf(t, err == nil, "%v", err) + //u.Debug(ts.In(time.UTC).Unix(), ts.In(time.UTC)) + assert.T(t, "2012-03-19 10:11:59.3186369 +0000 UTC" == fmt.Sprintf("%v", ts.In(time.UTC))) + + //--------------------------------------------- + // yyyy-mm-dd ? ts, err = ParseAny("2009-08-12T22:15:09-07:00") assert.Tf(t, err == nil, "%v", err) //u.Debug(ts.In(time.UTC).Unix(), ts.In(time.UTC)) @@ -168,6 +217,12 @@ func TestParse(t *testing.T) { assert.Tf(t, err == nil, "%v", err) //u.Debug(ts.In(time.UTC).Unix(), ts.In(time.UTC)) assert.T(t, "2014-05-11 08:20:13.787 +0000 UTC" == fmt.Sprintf("%v", ts.In(time.UTC))) + + ts, err = ParseAny("1332151919") + assert.Tf(t, err == nil, "%v", err) + //u.Debug(ts.In(time.UTC).Unix(), ts.In(time.UTC)) + assert.T(t, "2012-03-19 10:11:59 +0000 UTC" == fmt.Sprintf("%v", ts.In(time.UTC))) + } // func TestWIP(t *testing.T) {