From 89c8cfc1bf061b38c76faba2d15e8be3ad1478d7 Mon Sep 17 00:00:00 2001 From: Aaron Raddon Date: Sat, 30 Jun 2018 10:20:13 -0700 Subject: [PATCH] parse dates with double offsets, closes #64 --- README.md | 9 +++++--- example/main.go | 4 +++- parseany.go | 55 ++++++++++++++++++++++++++++++++++++------------ parseany_test.go | 11 ++++++---- 4 files changed, 57 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 77375f5..e234d64 100644 --- a/README.md +++ b/README.md @@ -137,6 +137,7 @@ var examples = []string{ "2014-12-16 06:20:00 GMT", "2014-04-26 05:24:37 PM", "2014-04-26 13:13:43 +0800", + "2014-04-26 13:13:43 +0800 +08", "2014-04-26 13:13:44 +09:00", "2012-08-03 18:31:59.257000000 +0000 UTC", "2015-09-30 18:48:56.35272715 +0000 UTC", @@ -199,7 +200,8 @@ func main() { | May 8, 2009 5:57:51 PM | 2009-05-08 17:57:51 +0000 UTC | | oct 7, 1970 | 1970-10-07 00:00:00 +0000 UTC | | oct 7, '70 | 1970-10-07 00:00:00 +0000 UTC | -| oct. 7, '70 | 1970-10-07 00:00:00 +0000 UTC | +| oct. 7, 1970 | 1970-10-07 00:00:00 +0000 UTC | +| oct. 7, 70 | 1970-10-07 00:00:00 +0000 UTC | | Mon Jan 2 15:04:05 2006 | 2006-01-02 15:04:05 +0000 UTC | | Mon Jan 2 15:04:05 MST 2006 | 2006-01-02 15:04:05 +0000 MST | | Mon Jan 02 15:04:05 -0700 2006 | 2006-01-02 15:04:05 -0700 -0700 | @@ -242,7 +244,7 @@ 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年04月08日 | 2014-04-08 00:00:00 +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 | | 2009-08-12T22:15:09 | 2009-08-12 22:15:09 +0000 UTC | @@ -256,7 +258,8 @@ func main() { | 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 +0000 UTC | +| 2014-04-26 13:13:43 +0800 +08 | 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 | diff --git a/example/main.go b/example/main.go index a460bf0..0ceee4b 100644 --- a/example/main.go +++ b/example/main.go @@ -76,6 +76,7 @@ var examples = []string{ "2014-12-16 06:20:00 GMT", "2014-04-26 05:24:37 PM", "2014-04-26 13:13:43 +0800", + "2014-04-26 13:13:43 +0800 +08", "2014-04-26 13:13:44 +09:00", "2012-08-03 18:31:59.257000000 +0000 UTC", "2015-09-30 18:48:56.35272715 +0000 UTC", @@ -182,7 +183,7 @@ 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年04月08日 | 2014-04-08 00:00:00 +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 | | 2009-08-12T22:15:09 | 2009-08-12 22:15:09 +0000 UTC | @@ -196,6 +197,7 @@ func main() { | 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:43 +0800 +08 | 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 | diff --git a/parseany.go b/parseany.go index ed908bc..da150c9 100644 --- a/parseany.go +++ b/parseany.go @@ -101,6 +101,8 @@ const ( ) var ( + // ErrAmbiguousMMDD for date formats such as 04/02/2014 the mm/dd vs dd/mm are + // ambiguous, so it is an error for strict parse rules. ErrAmbiguousMMDD = fmt.Errorf("This date has ambiguous mm/dd vs dd/mm type format") ) @@ -1123,6 +1125,8 @@ iterRunes: case timeWsOffset: // timeWsOffset // 15:04:05 -0700 + // timeWsOffsetWsOffset + // 17:57:51 -0700 -07 // timeWsOffsetWs // 17:57:51 -0700 2009 // 00:12:00 +0000 UTC @@ -1142,24 +1146,37 @@ iterRunes: // 17:57:51 -0700 2009 // 00:12:00 +0000 UTC // 22:18:00.001 +0000 UTC m=+0.000000001 - - switch { - case unicode.IsDigit(r): - p.yearlen = i - p.yeari + 1 - if p.yearlen == 4 { - p.setYear() - } - case unicode.IsLetter(r): - if p.tzi == 0 { - p.tzi = i - } - case r == '=': + // w Extra + // 17:57:51 -0700 -07 + switch r { + case '=': // eff you golang if datestr[i-1] == 'm' { p.extra = i - 2 p.trimExtra() break } + case '+', '-': + // This really doesn't seem valid, but for some reason when round-tripping a go date + // their is an extra +03 printed out. seems like go bug to me, but, parsing anyway. + // 00:00:00 +0300 +03 + // 00:00:00 +0300 +0300 + p.extra = i - 1 + p.stateTime = timeWsOffset + p.trimExtra() + break + default: + switch { + case unicode.IsDigit(r): + p.yearlen = i - p.yeari + 1 + if p.yearlen == 4 { + p.setYear() + } + case unicode.IsLetter(r): + if p.tzi == 0 { + p.tzi = i + } + } } case timeWsOffsetColon: @@ -1172,7 +1189,6 @@ iterRunes: p.stateTime = timeWsOffsetColonAlpha break iterTimeRunes } - case timePeriod: // 15:04:05.999999999+07:00 // 15:04:05.999999999-07:00 @@ -1193,6 +1209,8 @@ iterRunes: // timePeriodWsOffset // 00:07:31.945167 +0000 // 00:00:00.000 +0000 + // With Extra + // 00:00:00.000 +0300 +03 // timePeriodWsOffsetAlpha // 00:07:31.945167 +0000 UTC // 00:00:00.000 +0000 UTC @@ -1266,11 +1284,12 @@ iterRunes: } case timePeriodWsOffset: - // timePeriodWs // timePeriodWsOffset // 00:07:31.945167 +0000 // 00:00:00.000 +0000 + // With Extra + // 00:00:00.000 +0300 +03 // timePeriodWsOffsetAlpha // 00:07:31.945167 +0000 UTC // 00:00:00.000 +0000 UTC @@ -1284,6 +1303,14 @@ iterRunes: p.stateTime = timePeriodWsOffsetColon case ' ': p.set(p.offseti, "-0700") + case '+', '-': + // This really doesn't seem valid, but for some reason when round-tripping a go date + // their is an extra +03 printed out. seems like go bug to me, but, parsing anyway. + // 00:00:00.000 +0300 +03 + // 00:00:00.000 +0300 +0300 + p.extra = i - 1 + p.trimExtra() + break default: if unicode.IsLetter(r) { // 00:07:31.945167 +0000 UTC diff --git a/parseany_test.go b/parseany_test.go index 0758048..be29368 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("jun. 7, 2012") - assert.Equal(t, "2012-06-07 00:00:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) + ts = MustParse("2018-06-29 19:09:57.77297118 +0300 +03") + assert.Equal(t, "2018-06-29 16:09:57.77297118 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) } type dateTest struct { @@ -201,9 +201,12 @@ var testInputs = []dateTest{ {in: "2014-04-26 17:24:37.12 +0000", out: "2014-04-26 17:24:37.12 +0000 UTC"}, {in: "2014-04-26 17:24:37.1 +0000", out: "2014-04-26 17:24:37.1 +0000 UTC"}, {in: "2014-05-11 08:20:13 +0000", out: "2014-05-11 08:20:13 +0000 UTC"}, - // yyyy-mm-dd hh:mm:ss+0000 - // yyyy-mm-dd hh:mm+0000 {in: "2014-05-11 08:20:13 +0530", out: "2014-05-11 02:50:13 +0000 UTC"}, + // yyyy-mm-dd hh:mm:ss +0300 +03 ?? issue author said this is from golang? + {in: "2018-06-29 19:09:57.77297118 +0300 +03", out: "2018-06-29 16:09:57.77297118 +0000 UTC"}, + {in: "2018-06-29 19:09:57.77297118 +0300 +0300", out: "2018-06-29 16:09:57.77297118 +0000 UTC"}, + {in: "2018-06-29 19:09:57 +0300 +03", out: "2018-06-29 16:09:57 +0000 UTC"}, + {in: "2018-06-29 19:09:57 +0300 +0300", out: "2018-06-29 16:09:57 +0000 UTC"}, // 13:31:51.999 -07:00 MST // yyyy-mm-dd hh:mm:ss +00:00