From ceeeb70dcb12c06b5770d2c7c416663d72585b97 Mon Sep 17 00:00:00 2001 From: Aaron Raddon Date: Fri, 5 Dec 2014 15:20:57 -0800 Subject: [PATCH] Benchmark tests for DateParse --- README.md | 6 ++- bench_test.go | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 bench_test.go diff --git a/README.md b/README.md index 02ba288..710ab33 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,11 @@ Go Date Parser --------------------------- -Parse Any date format without knowing format in advance. +Parse Any date format without knowing format in advance. Uses +a Scan/Lex based approach to minimize shotgun based parse attempts. +See bench_test.go for performance comparison. + + ```go diff --git a/bench_test.go b/bench_test.go new file mode 100644 index 0000000..0b87270 --- /dev/null +++ b/bench_test.go @@ -0,0 +1,118 @@ +package dateparse + +import ( + "fmt" + //"github.com/bmizerany/assert" + "testing" + "time" +) + +/* + +go test -bench Parse + +BenchmarkShotgunParse 50000 37588 ns/op 13258 B/op 167 allocs/op +BenchmarkDateparseParseAny 500000 5752 ns/op 0 B/op 0 allocs/op + +*/ +func BenchmarkShotgunParse(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + for _, dateStr := range testDates { + parseShotgun(dateStr) + } + } +} + +func BenchmarkDateparseParseAny(b *testing.B) { + b.ReportAllocs() + for i := 0; i < b.N; i++ { + for _, dateStr := range testDates { + ParseAny(dateStr) + } + } +} + +var ( + testDates = []string{ + "2012/03/19 10:11:59", + "2012/03/19 10:11:59.3186369", + "2009-08-12T22:15:09-07:00", + "2014-04-26 17:24:37.3186369", + "2012-08-03 18:31:59.257000000", + "2013-04-01 22:43:22", + "2014-04-26 17:24:37.123", + "2014-12-16 06:20:00 UTC", + "1384216367189", + "1332151919", + "2014-05-11 08:20:13,787", + "2014-04-26 05:24:37 PM", + "2014-04-26", + } + + DateFormatError = fmt.Errorf("Invalid Date Format") + + timeFormats = []string{ + // ISO 8601ish formats + time.RFC3339Nano, + time.RFC3339, + + // Unusual formats, prefer formats with timezones + time.RFC1123Z, + time.RFC1123, + time.RFC822Z, + time.RFC822, + time.UnixDate, + time.RubyDate, + time.ANSIC, + + // Hilariously, Go doesn't have a const for it's own time layout. + // See: https://code.google.com/p/go/issues/detail?id=6587 + "2006-01-02 15:04:05.999999999 -0700 MST", + + // No timezone information + "2006-01-02T15:04:05.999999999", + "2006-01-02T15:04:05", + "2006-01-02 15:04:05.999999999", + "2006-01-02 15:04:05", + } +) + +/* + + ts, err = ParseAny("May 8, 2009 5:57:51 PM") + ts, err = ParseAny("Mon Jan 2 15:04:05 2006") + ts, err = ParseAny("Mon Jan 2 15:04:05 MST 2006") + ts, err = ParseAny("Mon Jan 02 15:04:05 -0700 2006") + ts, err = ParseAny("Monday, 02-Jan-06 15:04:05 MST") + ts, err = ParseAny("3/31/2014") + ts, err = ParseAny("03/31/2014") + ts, err = ParseAny("4/8/2014 22:05") + ts, err = ParseAny("04/08/2014 22:05") + ts, err = ParseAny("04/2/2014 03:00:51") + ts, err = ParseAny("4/02/2014 03:00:51") + ts, err = ParseAny("03/19/2012 10:11:59") + ts, err = ParseAny("03/19/2012 10:11:59.3186369") + ts, err = ParseAny("2014/3/31") + ts, err = ParseAny("2014/03/31") + ts, err = ParseAny("2014/4/8 22:05") + ts, err = ParseAny("2014/04/08 22:05") + ts, err = ParseAny("2014/04/2 03:00:51") + ts, err = ParseAny("2014/4/02 03:00:51") + ts, err = ParseAny() +*/ + +// Normalizes a variety of string representations to a time.Time in UTC. +func parseShotgun(raw string) (time.Time, error) { + + // We shouldn't need these, dupes of above + // Well it's not a UNIX timestamp, try ISO standards + for _, format := range timeFormats { + t, err := time.Parse(format, raw) + if err == nil { + // Parsed successfully + return t, nil + } + } + return time.Time{}, DateFormatError +}