From 3e1f751fedd9ea38964da4f6b0f817929e0d9ff7 Mon Sep 17 00:00:00 2001 From: Aaron Raddon Date: Wed, 26 Jul 2017 16:55:21 -0700 Subject: [PATCH 1/2] new date format for 2013-Feb-03 --- README.md | 64 +++++++++++++++++++++++++----------------------- example/main.go | 4 ++- parseany.go | 11 +++++++++ parseany_test.go | 3 +++ 4 files changed, 50 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 629579a..2eea50b 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ Extended example https://github.com/araddon/dateparse/blob/master/example/main.g package main import ( + "flag" "fmt" "time" @@ -33,7 +34,6 @@ import ( "github.com/araddon/dateparse" ) - var examples = []string{ "May 8, 2009 5:57:51 PM", "Mon Jan 2 15:04:05 2006", @@ -46,6 +46,7 @@ var examples = []string{ "Mon Aug 10 15:44:11 UTC+0100 2015", "Fri Jul 03 2015 18:04:07 GMT+0100 (GMT Daylight Time)", "12 Feb 2006, 19:17", + "2013-Feb-03", // mm/dd/yy "3/31/2014", "03/31/2014", @@ -102,40 +103,38 @@ var examples = []string{ "1384216367189", } +var ( + timezone = "" +) func main() { + flag.StringVar(&timezone, "timezone", "UTC", "Timezone aka `America/Los_Angeles` formatted time-zone") + flag.Parse() + + if timezone != "" { + // NOTE: This is very, very important to understand + // time-parsing in go + loc, err := time.LoadLocation(timezone) + if err != nil { + panic(err.Error()) + } + time.Local = loc + } table := termtables.CreateTable() table.AddHeaders("Input", "Parsed, and Output as %v") for _, dateExample := range examples { - t, err := dateparse.ParseAny(dateExample) + t, err := dateparse.ParseLocal(dateExample) if err != nil { panic(err.Error()) } - table.AddRow(dateExample, fmt.Sprintf("%v",t)) + table.AddRow(dateExample, fmt.Sprintf("%v", t)) } fmt.Println(table.Render()) } -func init() { - // NOTE: This is very, very important to understand timezone parsing - // The time.Local global tells the parse function to use given - // location/zone for use in the time.Parse() function - // used by this library. It uses UTC by default. - if uzeTimeZone { - loc, _ := time.LoadLocation("America/Denver") - time.Local = loc - } else { - // This is the default behavior - //loc, _ := time.LoadLocation("UTC") - //time.Local = loc - } -} -``` - -**outputs** -``` +/* +-------------------------------------------------------+----------------------------------------+ | Input | Parsed, and Output as %v | +-------------------------------------------------------+----------------------------------------+ @@ -150,8 +149,7 @@ func init() { | Mon Aug 10 15:44:11 UTC+0100 2015 | 2015-08-10 15:44:11 +0000 UTC | | Fri Jul 03 2015 18:04:07 GMT+0100 (GMT Daylight Time) | 2015-07-03 18:04:07 +0100 GMT | | 12 Feb 2006, 19:17 | 2006-02-12 19:17:00 +0000 UTC | -| 2015-02-18 00:12:00 +0000 GMT | 2015-02-18 00:12:00 +0000 UTC | -| 2015-02-18 00:12:00 +0000 UTC | 2015-02-18 00:12:00 +0000 UTC | +| 2013-Feb-03 | 2013-02-03 00:00:00 +0000 UTC | | 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 | @@ -175,22 +173,24 @@ func init() { | 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 | -| 2009-08-12T22:15:09-07:00 | 2009-08-12 22:15:09 -0700 -0700 | -| 2009-08-12T22:15:09Z | 2009-08-12 22:15:09 +0000 UTC | -| 2009-08-12T22:15:09 | 2009-08-12 22:15:09 +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 | +| 2009-08-12T22:15:09 | 2009-08-12 22:15:09 +0000 UTC | +| 2009-08-12T22:15:09Z | 2009-08-12 22:15:09 +0000 UTC | | 2014-04-26 17:24:37.3186369 | 2014-04-26 17:24:37.3186369 +0000 UTC | -| 2014-04-26 17:24:37.318636 | 2014-04-26 17:24:37.318636 +0000 UTC | -| 2012-08-03 18:31:59.257000000 +0000 UTC | 2012-08-03 18:31:59.257 +0000 UTC | -| 2015-09-30 18:48:56.35272715 +0000 UTC | 2015-09-30 18:48:56.35272715 +0000 UTC | | 2012-08-03 18:31:59.257000000 | 2012-08-03 18:31:59.257 +0000 UTC | -| 2013-04-01 22:43:22 | 2013-04-01 22:43:22 +0000 UTC | | 2014-04-26 17:24:37.123 | 2014-04-26 17:24:37.123 +0000 UTC | +| 2013-04-01 22:43:22 | 2013-04-01 22:43:22 +0000 UTC | | 2014-12-16 06:20:00 UTC | 2014-12-16 06:20:00 +0000 UTC | | 2014-12-16 06:20:00 GMT | 2014-12-16 06:20:00 +0000 UTC | | 2014-04-26 05:24:37 PM | 2014-04-26 17:24:37 +0000 UTC | | 2014-04-26 13:13:43 +0800 | 2014-04-26 13:13:43 +0800 +0800 | | 2014-04-26 13:13:44 +09:00 | 2014-04-26 13:13:44 +0900 +0900 | +| 2012-08-03 18:31:59.257000000 +0000 UTC | 2012-08-03 18:31:59.257 +0000 UTC | +| 2015-09-30 18:48:56.35272715 +0000 UTC | 2015-09-30 18:48:56.35272715 +0000 UTC | +| 2015-02-18 00:12:00 +0000 GMT | 2015-02-18 00:12:00 +0000 UTC | +| 2015-02-18 00:12:00 +0000 UTC | 2015-02-18 00:12:00 +0000 UTC | +| 2017-07-19 03:21:51+00:00 | 2017-07-19 03:21:51 +0000 UTC | | 2014-04-26 | 2014-04-26 00:00:00 +0000 UTC | | 2014-04 | 2014-04-01 00:00:00 +0000 UTC | | 2014 | 2014-01-01 00:00:00 +0000 UTC | @@ -199,4 +199,6 @@ func init() { | 1332151919 | 2012-03-19 10:11:59 +0000 UTC | | 1384216367189 | 2013-11-12 00:32:47.189 +0000 UTC | +-------------------------------------------------------+----------------------------------------+ -``` \ No newline at end of file +*/ + +``` diff --git a/example/main.go b/example/main.go index d1dd24d..163f871 100644 --- a/example/main.go +++ b/example/main.go @@ -21,6 +21,7 @@ var examples = []string{ "Mon Aug 10 15:44:11 UTC+0100 2015", "Fri Jul 03 2015 18:04:07 GMT+0100 (GMT Daylight Time)", "12 Feb 2006, 19:17", + "2013-Feb-03", // mm/dd/yy "3/31/2014", "03/31/2014", @@ -99,7 +100,7 @@ func main() { table.AddHeaders("Input", "Parsed, and Output as %v") for _, dateExample := range examples { - t, err := dateparse.ParseAny(dateExample) + t, err := dateparse.ParseLocal(dateExample) if err != nil { panic(err.Error()) } @@ -123,6 +124,7 @@ func main() { | Mon Aug 10 15:44:11 UTC+0100 2015 | 2015-08-10 15:44:11 +0000 UTC | | Fri Jul 03 2015 18:04:07 GMT+0100 (GMT Daylight Time) | 2015-07-03 18:04:07 +0100 GMT | | 12 Feb 2006, 19:17 | 2006-02-12 19:17:00 +0000 UTC | +| 2013-Feb-03 | 2013-02-03 00:00:00 +0000 UTC | | 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 | diff --git a/parseany.go b/parseany.go index 5fe80ac..f42dea2 100644 --- a/parseany.go +++ b/parseany.go @@ -25,6 +25,7 @@ const ( ST_START DateState = iota ST_DIGIT ST_DIGITDASH + ST_DIGITDASHALPHA ST_DIGITDASHWS ST_DIGITDASHWSWS ST_DIGITDASHWSWSAMPMMAYBE @@ -155,11 +156,17 @@ iterRunes: // 2006-01-02 // 2013-04-01 22:43:22 // 2014-04-26 05:24:37 PM + // 2013-Feb-03 switch { case r == ' ': state = ST_DIGITDASHWS case r == 'T': state = ST_DIGITDASHT + default: + if unicode.IsLetter(r) { + state = ST_DIGITDASHALPHA + break iterRunes + } } case ST_DIGITDASHWS: // 2013-04-01 22:43:22 @@ -569,6 +576,10 @@ iterRunes: } else if len(datestr) == len("2014-04") { return parse("2006-01", datestr, loc) } + case ST_DIGITDASHALPHA: + // 2013-Feb-03 + return parse("2006-Jan-02", datestr, loc) + case ST_DIGITDASHTDELTA: // 2006-01-02T15:04:05+0000 return parse("2006-01-02T15:04:05-0700", datestr, loc) diff --git a/parseany_test.go b/parseany_test.go index 6d30c61..e7cac6c 100644 --- a/parseany_test.go +++ b/parseany_test.go @@ -232,6 +232,9 @@ func TestParse(t *testing.T) { ts = MustParse("12 Feb 2006, 19:17:22") assert.Equal(t, "2006-02-12 19:17:22 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) + ts = MustParse("2013-Feb-03") + assert.Equal(t, "2013-02-03 00:00:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) + //--------------------------------------------- // mm/dd/yyyy ? From 7dedf040d6385aa33eafb2dfc17bffb9b24418d1 Mon Sep 17 00:00:00 2001 From: Aaron Raddon Date: Wed, 26 Jul 2017 17:08:58 -0700 Subject: [PATCH 2/2] Improve doc on time.Location usage --- README.md | 17 ++++++++++++++--- parseany.go | 10 ++++++++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2eea50b..1902a4f 100644 --- a/README.md +++ b/README.md @@ -11,14 +11,25 @@ Parse any date string without knowing format in advance. Uses a scanner to read ```go -// Normal parse +// Normal parse. If no recognized Timezone/Offset info +// exists in the datestring, it uses UTC. t, err := dateparse.ParseAny("3/1/2014") -// Parse with Location +// Parse with Location. If no recognized Timezone/Offset info +// exists in the datestring, it uses given location. +// IF there IS timezone/offset info it uses the given location +// info for any zone interpretation. That is, MST means one thing +// when using America/Denver and something else in other locations. denverLoc, _ := time.LoadLocation("America/Denver") - t, err := dateparse.ParseIn("3/1/2014", denverLoc) +// Set Location to time.Local. Same as ParseIn Location but +// Lazily uses a global variable for Location Info. +denverLoc, _ := time.LoadLocation("America/Denver") +// use time.Local global variable to store location +time.Local = denverLoc +t, err := dateparse.ParseLocal("3/1/2014") + ``` Extended example https://github.com/araddon/dateparse/blob/master/example/main.go diff --git a/parseany.go b/parseany.go index f42dea2..f16a888 100644 --- a/parseany.go +++ b/parseany.go @@ -87,12 +87,22 @@ func ParseAny(datestr string) (time.Time, error) { // ParseIn Given an unknown date format, detect the layout, // using given location, parse. +// +// If no recognized Timezone/Offset info exists in the datestring, it uses +// given location. IF there IS timezone/offset info it uses the given location +// info for any zone interpretation. That is, MST means one thing when using +// America/Denver and something else in other locations. func ParseIn(datestr string, loc *time.Location) (time.Time, error) { return parseTime(datestr, loc) } // ParseLocal Given an unknown date format, detect the layout, // using time.Local, parse. +// +// If no recognized Timezone/Offset info exists in the datestring, it uses +// given location. IF there IS timezone/offset info it uses the given location +// info for any zone interpretation. That is, MST means one thing when using +// America/Denver and something else in other locations. func ParseLocal(datestr string) (time.Time, error) { return parseTime(datestr, time.Local) }