diff --git a/README.md b/README.md index 1e415f4..3e78308 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,6 @@ var examples = []string{ "Mon, 02 Jan 2006 15:04:05 MST", "Tue, 11 Jul 2017 16:28:13 +0200 (CEST)", "Mon, 02 Jan 2006 15:04:05 -0700", - "Thu, 4 Jan 2018 17:53:36 +0000", "Mon 30 Sep 2018 09:09:09 PM UTC", "Mon Aug 10 15:44:11 UTC+0100 2015", "Thu, 4 Jan 2018 17:53:36 +0000", @@ -77,11 +76,15 @@ var examples = []string{ "October 7th, 1970", "12 Feb 2006, 19:17", "12 Feb 2006 19:17", + "14 May 2019 19:11:40.164", "7 oct 70", "7 oct 1970", "03 February 2013", "1 July 2013", "2013-Feb-03", + // dd/Mon/yyy alpha Months + "06/Jan/2008:15:04:05 -0700", + "06/Jan/2008 15:04:05 -0700", // mm/dd/yy "3/31/2014", "03/31/2014", @@ -156,6 +159,9 @@ var examples = []string{ // yyyymmdd and similar "20140601", "20140722105203", + // yymmdd hh:mm:yy mysql log + // 080313 05:21:55 mysqld started + "171113 14:14:20", // unix seconds, ms, micro, nano "1332151919", "1384216367189", @@ -221,11 +227,14 @@ func main() { | October 7th, 1970 | 1970-10-07 00:00:00 +0000 UTC | | 12 Feb 2006, 19:17 | 2006-02-12 19:17:00 +0000 UTC | | 12 Feb 2006 19:17 | 2006-02-12 19:17:00 +0000 UTC | +| 14 May 2019 19:11:40.164 | 2019-05-14 19:11:40.164 +0000 UTC | | 7 oct 70 | 1970-10-07 00:00:00 +0000 UTC | | 7 oct 1970 | 1970-10-07 00:00:00 +0000 UTC | | 03 February 2013 | 2013-02-03 00:00:00 +0000 UTC | | 1 July 2013 | 2013-07-01 00:00:00 +0000 UTC | | 2013-Feb-03 | 2013-02-03 00:00:00 +0000 UTC | +| 06/Jan/2008:15:04:05 -0700 | 2008-01-06 15:04:05 -0700 -0700 | +| 06/Jan/2008 15:04:05 -0700 | 2008-01-06 15:04:05 -0700 -0700 | | 3/31/2014 | 2014-03-31 00:00:00 +0000 UTC | | 03/31/2014 | 2014-03-31 00:00:00 +0000 UTC | | 08/21/71 | 1971-08-21 00:00:00 +0000 UTC | @@ -250,6 +259,14 @@ func main() { | 2014/4/02 03:00:51 | 2014-04-02 03:00:51 +0000 UTC | | 2012/03/19 10:11:59 | 2012-03-19 10:11:59 +0000 UTC | | 2012/03/19 10:11:59.3186369 | 2012-03-19 10:11:59.3186369 +0000 UTC | +| 2014:3:31 | 2014-03-31 00:00:00 +0000 UTC | +| 2014:03:31 | 2014-03-31 00:00:00 +0000 UTC | +| 2014:4:8 22:05 | 2014-04-08 22:05:00 +0000 UTC | +| 2014:04:08 22:05 | 2014-04-08 22:05:00 +0000 UTC | +| 2014:04:2 03:00:51 | 2014-04-02 03:00:51 +0000 UTC | +| 2014:4:02 03:00:51 | 2014-04-02 03:00:51 +0000 UTC | +| 2012:03:19 10:11:59 | 2012-03-19 10:11:59 +0000 UTC | +| 2012:03:19 10:11:59.3186369 | 2012-03-19 10:11:59.3186369 +0000 UTC | | 2014年04月08日 | 2014-04-08 00:00:00 +0000 UTC | | 2006-01-02T15:04:05+0000 | 2006-01-02 15:04:05 +0000 UTC | | 2009-08-12T22:15:09-07:00 | 2009-08-12 22:15:09 -0700 -0700 | @@ -284,6 +301,7 @@ func main() { | 2014.03.30 | 2014-03-30 00:00:00 +0000 UTC | | 20140601 | 2014-06-01 00:00:00 +0000 UTC | | 20140722105203 | 2014-07-22 10:52:03 +0000 UTC | +| 171113 14:14:20 | 2017-11-13 14:14:20 +0000 UTC | | 1332151919 | 2012-03-19 10:11:59 +0000 UTC | | 1384216367189 | 2013-11-12 00:32:47.189 +0000 UTC | | 1384216367111222 | 2013-11-12 00:32:47.111222 +0000 UTC | diff --git a/example/main.go b/example/main.go index 3618fbe..301593d 100644 --- a/example/main.go +++ b/example/main.go @@ -29,19 +29,19 @@ 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", "12 Feb 2006 19:17", + "14 May 2019 19:11:40.164", "7 oct 70", "7 oct 1970", "03 February 2013", "1 July 2013", "2013-Feb-03", + // dd/Mon/yyy alpha Months + "06/Jan/2008:15:04:05 -0700", + "06/Jan/2008 15:04:05 -0700", // mm/dd/yy "3/31/2014", "03/31/2014", @@ -68,6 +68,15 @@ var examples = []string{ "2014/4/02 03:00:51", "2012/03/19 10:11:59", "2012/03/19 10:11:59.3186369", + // yyyy:mm:dd + "2014:3:31", + "2014:03:31", + "2014:4:8 22:05", + "2014:04:08 22:05", + "2014:04:2 03:00:51", + "2014:4:02 03:00:51", + "2012:03:19 10:11:59", + "2012:03:19 10:11:59.3186369", // Chinese "2014年04月08日", // yyyy-mm-ddThh @@ -107,6 +116,9 @@ var examples = []string{ // yyyymmdd and similar "20140601", "20140722105203", + // yymmdd hh:mm:yy mysql log + // 080313 05:21:55 mysqld started + "171113 14:14:20", // unix seconds, ms, micro, nano "1332151919", "1384216367189", @@ -172,11 +184,14 @@ func main() { | October 7th, 1970 | 1970-10-07 00:00:00 +0000 UTC | | 12 Feb 2006, 19:17 | 2006-02-12 19:17:00 +0000 UTC | | 12 Feb 2006 19:17 | 2006-02-12 19:17:00 +0000 UTC | +| 14 May 2019 19:11:40.164 | 2019-05-14 19:11:40.164 +0000 UTC | | 7 oct 70 | 1970-10-07 00:00:00 +0000 UTC | | 7 oct 1970 | 1970-10-07 00:00:00 +0000 UTC | | 03 February 2013 | 2013-02-03 00:00:00 +0000 UTC | | 1 July 2013 | 2013-07-01 00:00:00 +0000 UTC | | 2013-Feb-03 | 2013-02-03 00:00:00 +0000 UTC | +| 06/Jan/2008:15:04:05 -0700 | 2008-01-06 15:04:05 -0700 -0700 | +| 06/Jan/2008 15:04:05 -0700 | 2008-01-06 15:04:05 -0700 -0700 | | 3/31/2014 | 2014-03-31 00:00:00 +0000 UTC | | 03/31/2014 | 2014-03-31 00:00:00 +0000 UTC | | 08/21/71 | 1971-08-21 00:00:00 +0000 UTC | @@ -201,6 +216,14 @@ func main() { | 2014/4/02 03:00:51 | 2014-04-02 03:00:51 +0000 UTC | | 2012/03/19 10:11:59 | 2012-03-19 10:11:59 +0000 UTC | | 2012/03/19 10:11:59.3186369 | 2012-03-19 10:11:59.3186369 +0000 UTC | +| 2014:3:31 | 2014-03-31 00:00:00 +0000 UTC | +| 2014:03:31 | 2014-03-31 00:00:00 +0000 UTC | +| 2014:4:8 22:05 | 2014-04-08 22:05:00 +0000 UTC | +| 2014:04:08 22:05 | 2014-04-08 22:05:00 +0000 UTC | +| 2014:04:2 03:00:51 | 2014-04-02 03:00:51 +0000 UTC | +| 2014:4:02 03:00:51 | 2014-04-02 03:00:51 +0000 UTC | +| 2012:03:19 10:11:59 | 2012-03-19 10:11:59 +0000 UTC | +| 2012:03:19 10:11:59.3186369 | 2012-03-19 10:11:59.3186369 +0000 UTC | | 2014年04月08日 | 2014-04-08 00:00:00 +0000 UTC | | 2006-01-02T15:04:05+0000 | 2006-01-02 15:04:05 +0000 UTC | | 2009-08-12T22:15:09-07:00 | 2009-08-12 22:15:09 -0700 -0700 | @@ -235,6 +258,7 @@ func main() { | 2014.03.30 | 2014-03-30 00:00:00 +0000 UTC | | 20140601 | 2014-06-01 00:00:00 +0000 UTC | | 20140722105203 | 2014-07-22 10:52:03 +0000 UTC | +| 171113 14:14:20 | 2017-11-13 14:14:20 +0000 UTC | | 1332151919 | 2012-03-19 10:11:59 +0000 UTC | | 1384216367189 | 2013-11-12 00:32:47.189 +0000 UTC | | 1384216367111222 | 2013-11-12 00:32:47.111222 +0000 UTC | diff --git a/go.mod b/go.mod index b99eec7..071cd5e 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/araddon/dateparse go 1.12 require ( - github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mattn/go-runewidth v0.0.10 // indirect github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4 - github.com/stretchr/testify v1.6.1 + github.com/stretchr/testify v1.7.0 ) diff --git a/go.sum b/go.sum index 56be791..40bf744 100644 --- a/go.sum +++ b/go.sum @@ -1,14 +1,17 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg= +github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY= +github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4 h1:8qmTC5ByIXO3GP/IzBkxcZ/99VITvnIETDhdFz/om7A= github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg= +github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= diff --git a/parseany.go b/parseany.go index b97e54e..185e6e5 100644 --- a/parseany.go +++ b/parseany.go @@ -67,27 +67,29 @@ const ( dateDigitDot // 10 dateDigitDotDot dateDigitSlash - dateDigitColon + dateDigitYearSlash + dateDigitSlashAlpha + dateDigitColon // 15 dateDigitChineseYear - dateDigitChineseYearWs // 15 + dateDigitChineseYearWs dateDigitWs dateDigitWsMoYear - dateDigitWsMolong + dateDigitWsMolong // 20 dateAlpha - dateAlphaWs // 20 + dateAlphaWs dateAlphaWsDigit dateAlphaWsDigitMore - dateAlphaWsDigitMoreWs + dateAlphaWsDigitMoreWs // 25 dateAlphaWsDigitMoreWsYear - dateAlphaWsMonth // 25 + dateAlphaWsMonth dateAlphaWsDigitYearmaybe dateAlphaWsMonthMore - dateAlphaWsMonthSuffix + dateAlphaWsMonthSuffix // 30 dateAlphaWsMore - dateAlphaWsAtTime // 30 + dateAlphaWsAtTime dateAlphaWsAlpha dateAlphaWsAlphaYearmaybe - dateAlphaPeriodWsDigit + dateAlphaPeriodWsDigit // 35 dateWeekdayComma dateWeekdayAbbrevComma ) @@ -268,7 +270,7 @@ iterRunes: i += (bytesConsumed - 1) } - //gou.Debugf("i=%d r=%s state=%d %s", i, string(r), p.stateDate, datestr) + // gou.Debugf("i=%d r=%s state=%d %s", i, string(r), p.stateDate, datestr) switch p.stateDate { case dateStart: if unicode.IsDigit(r) { @@ -301,13 +303,32 @@ iterRunes: // 2014/02/24 p.stateDate = dateDigitSlash if i == 4 { - p.yearlen = i + // 2014/02/24 - Year first / + p.yearlen = i // since it was start of datestr, i=len p.moi = i + 1 p.setYear() + p.stateDate = dateDigitYearSlash } else { + // Either Ambiguous dd/mm vs mm/dd OR dd/month/yy + // 08/May/2005 + // 03/31/2005 + // 31/03/2005 + if i+2 < len(p.datestr) && unicode.IsLetter(rune(datestr[i+1])) { + // 08/May/2005 + p.stateDate = dateDigitSlashAlpha + p.moi = i + 1 + p.daylen = 2 + p.dayi = 0 + p.setDay() + continue + } + // Ambiguous dd/mm vs mm/dd the bane of date-parsing + // 03/31/2005 + // 31/03/2005 p.ambiguousMD = true if p.preferMonthFirst { if p.molen == 0 { + // 03/31/2005 p.molen = i p.setMonth() p.dayi = i + 1 @@ -319,6 +340,7 @@ iterRunes: p.moi = i + 1 } } + } case ':': @@ -452,18 +474,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: // 13-Feb-03 ambiguous // 28-Feb-03 ambiguous - // 29-Jun-2016 + // 29-Jun-2016 dd-month(alpha)-yyyy switch r { case ' ': // we need to find if this was 4 digits, aka year @@ -493,8 +509,49 @@ iterRunes: break iterRunes } - case dateDigitSlash: + case dateDigitYearSlash: // 2014/07/10 06:55:38.156283 + // I honestly don't know if this format ever shows up as yyyy/ + + switch r { + case ' ', ':': + p.stateTime = timeStart + if p.daylen == 0 { + p.daylen = i - p.dayi + p.setDay() + } + break iterRunes + case '/': + if p.molen == 0 { + p.molen = i - p.moi + p.setMonth() + p.dayi = i + 1 + } + } + + case dateDigitSlashAlpha: + // 06/May/2008 + + switch r { + case '/': + // | + // 06/May/2008 + if p.molen == 0 { + p.set(p.moi, "Jan") + p.yeari = i + 1 + } + // We aren't breaking because we are going to re-use this case + // to find where the date starts, and possible time begins + case ' ', ':': + p.stateTime = timeStart + if p.yearlen == 0 { + p.yearlen = i - p.yeari + p.setYear() + } + break iterRunes + } + + case dateDigitSlash: // 03/19/2012 10:11:59 // 04/2/2014 03:00:37 // 3/1/2012 10:11:59 @@ -505,35 +562,9 @@ iterRunes: // 1/2/06 switch r { - 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 ':': - 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 - if p.molen == 0 { - p.molen = i - p.moi - p.setMonth() - p.dayi = i + 1 - } - } else if p.preferMonthFirst { + // This is the 2nd / so now we should know start pts of all of the dd, mm, yy + if p.preferMonthFirst { if p.daylen == 0 { p.daylen = i - p.dayi p.setDay() @@ -546,11 +577,15 @@ iterRunes: p.yeari = i + 1 } } - default: - if unicode.IsLetter(r) { - p.moi = i - p.stateDate = dateDigitDashAlpha + // Note no break, we are going to pass by and re-enter this dateDigitSlash + // and look for ending (space) or not (just date) + case ' ': + p.stateTime = timeStart + if p.yearlen == 0 { + p.yearlen = i - p.yeari + p.setYear() } + break iterRunes } case dateDigitColon: @@ -1792,6 +1827,13 @@ iterRunes: // 3/1/2014 // 10/13/2014 // 01/02/2006 + return p, nil + + case dateDigitSlashAlpha: + // 03/Jun/2014 + return p, nil + + case dateDigitYearSlash: // 2014/10/13 return p, nil diff --git a/parseany_test.go b/parseany_test.go index 8e19076..2b9e61d 100644 --- a/parseany_test.go +++ b/parseany_test.go @@ -11,8 +11,8 @@ import ( func TestOne(t *testing.T) { time.Local = time.UTC var ts time.Time - ts = MustParse("Mon 30 Sep 2018 09:09:09 PM UTC") - assert.Equal(t, "2018-09-30 21:09:09 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) + ts = MustParse("06/May/2008 15:04:05 -0700") + assert.Equal(t, "2008-05-06 22:04:05 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) } type dateTest struct { @@ -222,6 +222,12 @@ var testInputs = []dateTest{ {in: "2014/4/2 04:08:09 AM", out: "2014-04-02 04:08:09 +0000 UTC"}, {in: "2014/04/02 04:08:09.123 AM", out: "2014-04-02 04:08:09.123 +0000 UTC"}, {in: "2014/04/02 04:08:09.123 PM", out: "2014-04-02 16:08:09.123 +0000 UTC"}, + // dd/mon/yyyy:hh:mm:ss tz redis log? + {in: "06/May/2008:08:11:17 -0700", out: "2008-05-06 15:11:17 +0000 UTC"}, + {in: "30/May/2008:08:11:17 -0700", out: "2008-05-30 15:11:17 +0000 UTC"}, + // dd/mon/yyy hh:mm:ss tz + {in: "06/May/2008:08:11:17 -0700", out: "2008-05-06 15:11:17 +0000 UTC"}, + {in: "30/May/2008:08:11:17 -0700", out: "2008-05-30 15:11:17 +0000 UTC"}, // yyyy-mm-dd {in: "2014-04-02", out: "2014-04-02 00:00:00 +0000 UTC"}, {in: "2014-03-31", out: "2014-03-31 00:00:00 +0000 UTC"}, @@ -388,6 +394,10 @@ var testInputs = []dateTest{ {in: "2014", out: "2014-01-01 00:00:00 +0000 UTC"}, {in: "20140601", out: "2014-06-01 00:00:00 +0000 UTC"}, {in: "20140722105203", out: "2014-07-22 10:52:03 +0000 UTC"}, + // yymmdd hh:mm:yy mysql log https://github.com/araddon/dateparse/issues/119 + // 080313 05:21:55 mysqld started + // 080313 5:21:55 InnoDB: Started; log sequence number 0 43655 + {in: "171113 14:14:20", out: "2017-11-13 14:14:20 +0000 UTC"}, // all digits: unix secs, ms etc {in: "1332151919", out: "2012-03-19 10:11:59 +0000 UTC"}, @@ -501,40 +511,43 @@ 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: "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"}, -} - func TestParseLayout(t *testing.T) { + // These tests are verifying that the layout returned by ParseFormat + // are correct. Above tests correct parsing, this tests correct + // re-usable formatting string + 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: "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"}, + } + for _, th := range testParseFormat { l, err := ParseFormat(th.in) if th.err {