From b87b24a51fb97e1fafac8c3dec4030a20fe30ee1 Mon Sep 17 00:00:00 2001 From: liushaobo Date: Wed, 3 Feb 2021 18:10:39 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- parseany.go | 37 +++++++++++++++++++++++++++++++++++++ parseany_test.go | 4 ++++ 2 files changed, 41 insertions(+) diff --git a/parseany.go b/parseany.go index 61a021e..ef74009 100644 --- a/parseany.go +++ b/parseany.go @@ -5,6 +5,7 @@ package dateparse import ( "fmt" + "regexp" "strconv" "strings" "time" @@ -49,6 +50,33 @@ var months = []string{ "december", } +var datePattern = []struct { + desc string + pattern string + goFmt string +}{ + { + desc: "nginx log datetime, 02/Jan/2006:15:04:05 -0700", + pattern: `\d{2}/\w+/\d{4}:\d{2}:\d{2}:\d{2} \+\d{4}`, + goFmt: "02/Jan/2006:15:04:05 -0700", + }, + { + desc: "redis log datetime, 14 May 2019 19:11:40.164", + pattern: `\d{2} \w+ \d{4} \d{2}:\d{2}:\d{2}.\d{3}`, + goFmt: "02 Jan 2006 15:04:05.000", + }, + { + desc: "redis log datetime, 14 May 19:11:40.164", + pattern: `\d{2} \w+ \d{2}:\d{2}:\d{2}.\d{3}`, + goFmt: "02 Jan 15:04:05.000", + }, + { + desc: "mysql, 171113 14:14:20", + pattern: `\d{6} \d{2}:\d{2}:\d{2}`, + goFmt: "060102 15:04:05", + }, +} + type dateState uint8 type timeState uint8 @@ -1790,6 +1818,15 @@ iterRunes: } + for _, d := range datePattern { + if match, err := regexp.MatchString(d.pattern, datestr); err != nil { + return nil, err + } else if match { + p.format = []byte(d.goFmt) + return p, nil + } + } + return nil, unknownErr(datestr) } diff --git a/parseany_test.go b/parseany_test.go index 35e212c..1faee76 100644 --- a/parseany_test.go +++ b/parseany_test.go @@ -508,6 +508,10 @@ var testParseFormat = []dateTest{ {in: "2009-15-12T22:15Z", err: true}, {in: "5,000-9,999", err: true}, // + {in: "02/Jan/2006:15:04:05 -0700", out: "01/Jan/2006:15:04:05 -0700"}, + {in: "14 May 2019 19:11:40.164", out: "02 Jan 2006 15:04:05.000"}, + {in: "171113 14:14:20", out: "060102 15:04:05"}, + {in: "oct 7, 1970", out: "Jan 2, 2006"}, {in: "sept. 7, 1970", out: "Jan. 2, 2006"}, {in: "May 05, 2015, 05:05:07", out: "Jan 02, 2006, 15:04:05"}, From a7e3619d4751eb7a4f934c33e7e66e35d025e1c4 Mon Sep 17 00:00:00 2001 From: liushaobo Date: Thu, 4 Feb 2021 14:23:19 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E6=89=A9=E5=85=85=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- parseany.go | 67 +++++++++++++++++++----------------------------- parseany_test.go | 2 +- 2 files changed, 28 insertions(+), 41 deletions(-) diff --git a/parseany.go b/parseany.go index ef74009..839a598 100644 --- a/parseany.go +++ b/parseany.go @@ -5,7 +5,6 @@ package dateparse import ( "fmt" - "regexp" "strconv" "strings" "time" @@ -50,39 +49,13 @@ var months = []string{ "december", } -var datePattern = []struct { - desc string - pattern string - goFmt string -}{ - { - desc: "nginx log datetime, 02/Jan/2006:15:04:05 -0700", - pattern: `\d{2}/\w+/\d{4}:\d{2}:\d{2}:\d{2} \+\d{4}`, - goFmt: "02/Jan/2006:15:04:05 -0700", - }, - { - desc: "redis log datetime, 14 May 2019 19:11:40.164", - pattern: `\d{2} \w+ \d{4} \d{2}:\d{2}:\d{2}.\d{3}`, - goFmt: "02 Jan 2006 15:04:05.000", - }, - { - desc: "redis log datetime, 14 May 19:11:40.164", - pattern: `\d{2} \w+ \d{2}:\d{2}:\d{2}.\d{3}`, - goFmt: "02 Jan 15:04:05.000", - }, - { - desc: "mysql, 171113 14:14:20", - pattern: `\d{6} \d{2}:\d{2}:\d{2}`, - goFmt: "060102 15:04:05", - }, -} - type dateState uint8 type timeState uint8 const ( dateStart dateState = iota // 0 dateDigit + dateDigitSt dateYearDash dateYearDashAlphaDash dateYearDashDash @@ -391,9 +364,13 @@ iterRunes: // 02 Jan 2018 23:59:34 // 12 Feb 2006, 19:17 // 12 Feb 2006, 19:17:22 - p.stateDate = dateDigitWs - p.dayi = 0 - p.daylen = i + if i == 6 { + p.stateDate = dateDigitSt + } else { + p.stateDate = dateDigitWs + p.dayi = 0 + p.daylen = i + } case '年': // Chinese Year p.stateDate = dateDigitChineseYear @@ -404,6 +381,11 @@ iterRunes: } p.part1Len = i + case dateDigitSt: + p.set(0, "060102") + i = i -1 + p.stateTime = timeStart + break iterRunes case dateYearDash: // dateYearDashDashT // 2006-01-02T15:04:05Z07:00 @@ -526,6 +508,16 @@ iterRunes: p.setDay() } break iterRunes + case ':': + p.stateTime = timeStart + if p.yearlen == 0 { + p.yearlen = i - p.yeari + p.setYear() + } else if p.daylen == 0 { + p.daylen = i - p.dayi + p.setDay() + } + break iterRunes case '/': if p.yearlen > 0 { // 2014/07/10 06:55:38.156283 @@ -1666,6 +1658,9 @@ iterRunes: p.t = &t return p, nil } + case dateDigitSt: + // 171113 14:14:20 + return p, nil case dateYearDash: // 2006-01 @@ -1818,15 +1813,6 @@ iterRunes: } - for _, d := range datePattern { - if match, err := regexp.MatchString(d.pattern, datestr); err != nil { - return nil, err - } else if match { - p.format = []byte(d.goFmt) - return p, nil - } - } - return nil, unknownErr(datestr) } @@ -2039,6 +2025,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 %q", p.datestr, string(p.format)) if p.loc == nil { return time.Parse(string(p.format), p.datestr) diff --git a/parseany_test.go b/parseany_test.go index 1faee76..92a96be 100644 --- a/parseany_test.go +++ b/parseany_test.go @@ -508,7 +508,7 @@ var testParseFormat = []dateTest{ {in: "2009-15-12T22:15Z", err: true}, {in: "5,000-9,999", err: true}, // - {in: "02/Jan/2006:15:04:05 -0700", out: "01/Jan/2006:15:04:05 -0700"}, + {in: "06/Jan/2008:15:04:05 -0700", out: "01/Jan/2006:15:04:05 -0700"}, {in: "14 May 2019 19:11:40.164", out: "02 Jan 2006 15:04:05.000"}, {in: "171113 14:14:20", out: "060102 15:04:05"}, From e92c493a75cd66cebe6e0557fe729bb42da11780 Mon Sep 17 00:00:00 2001 From: liushaobo Date: Thu, 4 Feb 2021 15:51:24 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E5=AE=8C=E5=96=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/main.go | 4 ++++ parseany.go | 14 ++++++++++++- parseany_test.go | 53 ++++++++++++++++++++++++------------------------ 3 files changed, 44 insertions(+), 27 deletions(-) diff --git a/example/main.go b/example/main.go index 56cec98..3618fbe 100644 --- a/example/main.go +++ b/example/main.go @@ -29,6 +29,10 @@ var examples = []string{ "September 17, 2012 10:09am", "September 17, 2012 at 10:09am PST-08", "September 17, 2012, 10:10:09", + "06/Jan/2008:15:04:05 -0700", + "06/Jan/2008 15:04:05 -0700", + "171113 14:14:20", + "14 May 2019 19:11:40.164", "October 7, 1970", "October 7th, 1970", "12 Feb 2006, 19:17", diff --git a/parseany.go b/parseany.go index 839a598..b97e54e 100644 --- a/parseany.go +++ b/parseany.go @@ -296,6 +296,7 @@ iterRunes: p.stateDate = dateDigitDash } case '/': + // 08/May/2005 // 03/31/2005 // 2014/02/24 p.stateDate = dateDigitSlash @@ -383,7 +384,7 @@ iterRunes: case dateDigitSt: p.set(0, "060102") - i = i -1 + i = i - 1 p.stateTime = timeStart break iterRunes case dateYearDash: @@ -451,6 +452,12 @@ iterRunes: p.set(p.moi, "Jan") p.yeari = i + 1 p.stateDate = dateDigitDashAlphaDash + case '/': + p.set(0, "02") + p.molen = i - p.moi + p.set(p.moi, "Jan") + p.yeari = i + 1 + p.stateDate = dateDigitSlash } case dateDigitDashAlphaDash: @@ -539,6 +546,11 @@ iterRunes: p.yeari = i + 1 } } + default: + if unicode.IsLetter(r) { + p.moi = i + p.stateDate = dateDigitDashAlpha + } } case dateDigitColon: diff --git a/parseany_test.go b/parseany_test.go index 92a96be..603cae2 100644 --- a/parseany_test.go +++ b/parseany_test.go @@ -503,34 +503,35 @@ func TestParseErrors(t *testing.T) { var testParseFormat = []dateTest{ // errors - {in: "3", err: true}, - {in: `{"hello"}`, err: true}, - {in: "2009-15-12T22:15Z", err: true}, - {in: "5,000-9,999", err: true}, + // {in: "3", err: true}, + // {in: `{"hello"}`, err: true}, + // {in: "2009-15-12T22:15Z", err: true}, + // {in: "5,000-9,999", err: true}, // - {in: "06/Jan/2008:15:04:05 -0700", out: "01/Jan/2006:15:04:05 -0700"}, - {in: "14 May 2019 19:11:40.164", out: "02 Jan 2006 15:04:05.000"}, - {in: "171113 14:14:20", out: "060102 15:04:05"}, + {in: "06/May/2008 15:04:05 -0700", out: "02/Jan/2006 15:04:05 -0700"}, + {in: "06/May/2008:15:04:05 -0700", out: "02/Jan/2006:15:04:05 -0700"}, + // {in: "14 May 2019 19:11:40.164", out: "02 Jan 2006 15:04:05.000"}, + // {in: "171113 14:14:20", out: "060102 15:04:05"}, - {in: "oct 7, 1970", out: "Jan 2, 2006"}, - {in: "sept. 7, 1970", out: "Jan. 2, 2006"}, - {in: "May 05, 2015, 05:05:07", out: "Jan 02, 2006, 15:04:05"}, - // 03 February 2013 - {in: "03 February 2013", out: "02 January 2006"}, - // 13:31:51.999 -07:00 MST - // yyyy-mm-dd hh:mm:ss +00:00 - {in: "2012-08-03 18:31:59 +00:00", out: "2006-01-02 15:04:05 -07:00"}, - // yyyy-mm-dd hh:mm:ss +0000 TZ - // Golang Native Format - {in: "2012-08-03 18:31:59 +0000 UTC", out: "2006-01-02 15:04:05 -0700 UTC"}, - // yyyy-mm-dd hh:mm:ss TZ - {in: "2012-08-03 18:31:59 UTC", out: "2006-01-02 15:04:05 UTC"}, - // yyyy-mm-ddThh:mm:ss-07:00 - {in: "2009-08-12T22:15:09-07:00", out: "2006-01-02T15:04:05-07:00"}, - // yyyy-mm-ddThh:mm:ss-0700 - {in: "2009-08-12T22:15:09-0700", out: "2006-01-02T15:04:05-0700"}, - // yyyy-mm-ddThh:mm:ssZ - {in: "2009-08-12T22:15Z", out: "2006-01-02T15:04Z"}, + // {in: "oct 7, 1970", out: "Jan 2, 2006"}, + // {in: "sept. 7, 1970", out: "Jan. 2, 2006"}, + // {in: "May 05, 2015, 05:05:07", out: "Jan 02, 2006, 15:04:05"}, + // // 03 February 2013 + // {in: "03 February 2013", out: "02 January 2006"}, + // // 13:31:51.999 -07:00 MST + // // yyyy-mm-dd hh:mm:ss +00:00 + // {in: "2012-08-03 18:31:59 +00:00", out: "2006-01-02 15:04:05 -07:00"}, + // // yyyy-mm-dd hh:mm:ss +0000 TZ + // // Golang Native Format + // {in: "2012-08-03 18:31:59 +0000 UTC", out: "2006-01-02 15:04:05 -0700 UTC"}, + // // yyyy-mm-dd hh:mm:ss TZ + // {in: "2012-08-03 18:31:59 UTC", out: "2006-01-02 15:04:05 UTC"}, + // // yyyy-mm-ddThh:mm:ss-07:00 + // {in: "2009-08-12T22:15:09-07:00", out: "2006-01-02T15:04:05-07:00"}, + // // yyyy-mm-ddThh:mm:ss-0700 + // {in: "2009-08-12T22:15:09-0700", out: "2006-01-02T15:04:05-0700"}, + // // yyyy-mm-ddThh:mm:ssZ + // {in: "2009-08-12T22:15Z", out: "2006-01-02T15:04Z"}, } func TestParseLayout(t *testing.T) { From ab345927d5d2ec82478d60954cfcdfad6cd50558 Mon Sep 17 00:00:00 2001 From: liushaobo Date: Thu, 4 Feb 2021 16:11:30 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- parseany_test.go | 50 ++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/parseany_test.go b/parseany_test.go index 603cae2..8e19076 100644 --- a/parseany_test.go +++ b/parseany_test.go @@ -503,35 +503,35 @@ func TestParseErrors(t *testing.T) { var testParseFormat = []dateTest{ // errors - // {in: "3", err: true}, - // {in: `{"hello"}`, err: true}, - // {in: "2009-15-12T22:15Z", err: true}, - // {in: "5,000-9,999", err: true}, + {in: "3", err: true}, + {in: `{"hello"}`, err: true}, + {in: "2009-15-12T22:15Z", err: true}, + {in: "5,000-9,999", err: true}, // {in: "06/May/2008 15:04:05 -0700", out: "02/Jan/2006 15:04:05 -0700"}, {in: "06/May/2008:15:04:05 -0700", out: "02/Jan/2006:15:04:05 -0700"}, - // {in: "14 May 2019 19:11:40.164", out: "02 Jan 2006 15:04:05.000"}, - // {in: "171113 14:14:20", out: "060102 15:04:05"}, + {in: "14 May 2019 19:11:40.164", out: "02 Jan 2006 15:04:05.000"}, + {in: "171113 14:14:20", out: "060102 15:04:05"}, - // {in: "oct 7, 1970", out: "Jan 2, 2006"}, - // {in: "sept. 7, 1970", out: "Jan. 2, 2006"}, - // {in: "May 05, 2015, 05:05:07", out: "Jan 02, 2006, 15:04:05"}, - // // 03 February 2013 - // {in: "03 February 2013", out: "02 January 2006"}, - // // 13:31:51.999 -07:00 MST - // // yyyy-mm-dd hh:mm:ss +00:00 - // {in: "2012-08-03 18:31:59 +00:00", out: "2006-01-02 15:04:05 -07:00"}, - // // yyyy-mm-dd hh:mm:ss +0000 TZ - // // Golang Native Format - // {in: "2012-08-03 18:31:59 +0000 UTC", out: "2006-01-02 15:04:05 -0700 UTC"}, - // // yyyy-mm-dd hh:mm:ss TZ - // {in: "2012-08-03 18:31:59 UTC", out: "2006-01-02 15:04:05 UTC"}, - // // yyyy-mm-ddThh:mm:ss-07:00 - // {in: "2009-08-12T22:15:09-07:00", out: "2006-01-02T15:04:05-07:00"}, - // // yyyy-mm-ddThh:mm:ss-0700 - // {in: "2009-08-12T22:15:09-0700", out: "2006-01-02T15:04:05-0700"}, - // // yyyy-mm-ddThh:mm:ssZ - // {in: "2009-08-12T22:15Z", out: "2006-01-02T15:04Z"}, + {in: "oct 7, 1970", out: "Jan 2, 2006"}, + {in: "sept. 7, 1970", out: "Jan. 2, 2006"}, + {in: "May 05, 2015, 05:05:07", out: "Jan 02, 2006, 15:04:05"}, + // 03 February 2013 + {in: "03 February 2013", out: "02 January 2006"}, + // 13:31:51.999 -07:00 MST + // yyyy-mm-dd hh:mm:ss +00:00 + {in: "2012-08-03 18:31:59 +00:00", out: "2006-01-02 15:04:05 -07:00"}, + // yyyy-mm-dd hh:mm:ss +0000 TZ + // Golang Native Format + {in: "2012-08-03 18:31:59 +0000 UTC", out: "2006-01-02 15:04:05 -0700 UTC"}, + // yyyy-mm-dd hh:mm:ss TZ + {in: "2012-08-03 18:31:59 UTC", out: "2006-01-02 15:04:05 UTC"}, + // yyyy-mm-ddThh:mm:ss-07:00 + {in: "2009-08-12T22:15:09-07:00", out: "2006-01-02T15:04:05-07:00"}, + // yyyy-mm-ddThh:mm:ss-0700 + {in: "2009-08-12T22:15:09-0700", out: "2006-01-02T15:04:05-0700"}, + // yyyy-mm-ddThh:mm:ssZ + {in: "2009-08-12T22:15Z", out: "2006-01-02T15:04Z"}, } func TestParseLayout(t *testing.T) {