parse dates with double offsets, closes #64

This commit is contained in:
Aaron Raddon 2018-06-30 10:20:13 -07:00
parent 4109f1d4ab
commit 89c8cfc1bf
4 changed files with 57 additions and 22 deletions

View File

@ -137,6 +137,7 @@ var examples = []string{
"2014-12-16 06:20:00 GMT", "2014-12-16 06:20:00 GMT",
"2014-04-26 05:24:37 PM", "2014-04-26 05:24:37 PM",
"2014-04-26 13:13:43 +0800", "2014-04-26 13:13:43 +0800",
"2014-04-26 13:13:43 +0800 +08",
"2014-04-26 13:13:44 +09:00", "2014-04-26 13:13:44 +09:00",
"2012-08-03 18:31:59.257000000 +0000 UTC", "2012-08-03 18:31:59.257000000 +0000 UTC",
"2015-09-30 18:48:56.35272715 +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 | | 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, 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, '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 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 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 | | 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 | | 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 | 2012-03-19 10:11:59 +0000 UTC |
| 2012/03/19 10:11:59.3186369 | 2012-03-19 10:11:59.3186369 +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 | | 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-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: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-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 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 | 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 | | 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-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 GMT | 2015-02-18 00:12:00 +0000 UTC |

View File

@ -76,6 +76,7 @@ var examples = []string{
"2014-12-16 06:20:00 GMT", "2014-12-16 06:20:00 GMT",
"2014-04-26 05:24:37 PM", "2014-04-26 05:24:37 PM",
"2014-04-26 13:13:43 +0800", "2014-04-26 13:13:43 +0800",
"2014-04-26 13:13:43 +0800 +08",
"2014-04-26 13:13:44 +09:00", "2014-04-26 13:13:44 +09:00",
"2012-08-03 18:31:59.257000000 +0000 UTC", "2012-08-03 18:31:59.257000000 +0000 UTC",
"2015-09-30 18:48:56.35272715 +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 | | 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 | 2012-03-19 10:11:59 +0000 UTC |
| 2012/03/19 10:11:59.3186369 | 2012-03-19 10:11:59.3186369 +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 | | 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-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: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-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 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 | 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 | | 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 | | 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-09-30 18:48:56.35272715 +0000 UTC | 2015-09-30 18:48:56.35272715 +0000 UTC |

View File

@ -101,6 +101,8 @@ const (
) )
var ( 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") ErrAmbiguousMMDD = fmt.Errorf("This date has ambiguous mm/dd vs dd/mm type format")
) )
@ -1123,6 +1125,8 @@ iterRunes:
case timeWsOffset: case timeWsOffset:
// timeWsOffset // timeWsOffset
// 15:04:05 -0700 // 15:04:05 -0700
// timeWsOffsetWsOffset
// 17:57:51 -0700 -07
// timeWsOffsetWs // timeWsOffsetWs
// 17:57:51 -0700 2009 // 17:57:51 -0700 2009
// 00:12:00 +0000 UTC // 00:12:00 +0000 UTC
@ -1142,24 +1146,37 @@ iterRunes:
// 17:57:51 -0700 2009 // 17:57:51 -0700 2009
// 00:12:00 +0000 UTC // 00:12:00 +0000 UTC
// 22:18:00.001 +0000 UTC m=+0.000000001 // 22:18:00.001 +0000 UTC m=+0.000000001
// w Extra
switch { // 17:57:51 -0700 -07
case unicode.IsDigit(r): switch r {
p.yearlen = i - p.yeari + 1 case '=':
if p.yearlen == 4 {
p.setYear()
}
case unicode.IsLetter(r):
if p.tzi == 0 {
p.tzi = i
}
case r == '=':
// eff you golang // eff you golang
if datestr[i-1] == 'm' { if datestr[i-1] == 'm' {
p.extra = i - 2 p.extra = i - 2
p.trimExtra() p.trimExtra()
break 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: case timeWsOffsetColon:
@ -1172,7 +1189,6 @@ iterRunes:
p.stateTime = timeWsOffsetColonAlpha p.stateTime = timeWsOffsetColonAlpha
break iterTimeRunes break iterTimeRunes
} }
case timePeriod: case timePeriod:
// 15:04:05.999999999+07:00 // 15:04:05.999999999+07:00
// 15:04:05.999999999-07:00 // 15:04:05.999999999-07:00
@ -1193,6 +1209,8 @@ iterRunes:
// timePeriodWsOffset // timePeriodWsOffset
// 00:07:31.945167 +0000 // 00:07:31.945167 +0000
// 00:00:00.000 +0000 // 00:00:00.000 +0000
// With Extra
// 00:00:00.000 +0300 +03
// timePeriodWsOffsetAlpha // timePeriodWsOffsetAlpha
// 00:07:31.945167 +0000 UTC // 00:07:31.945167 +0000 UTC
// 00:00:00.000 +0000 UTC // 00:00:00.000 +0000 UTC
@ -1266,11 +1284,12 @@ iterRunes:
} }
case timePeriodWsOffset: case timePeriodWsOffset:
// timePeriodWs // timePeriodWs
// timePeriodWsOffset // timePeriodWsOffset
// 00:07:31.945167 +0000 // 00:07:31.945167 +0000
// 00:00:00.000 +0000 // 00:00:00.000 +0000
// With Extra
// 00:00:00.000 +0300 +03
// timePeriodWsOffsetAlpha // timePeriodWsOffsetAlpha
// 00:07:31.945167 +0000 UTC // 00:07:31.945167 +0000 UTC
// 00:00:00.000 +0000 UTC // 00:00:00.000 +0000 UTC
@ -1284,6 +1303,14 @@ iterRunes:
p.stateTime = timePeriodWsOffsetColon p.stateTime = timePeriodWsOffsetColon
case ' ': case ' ':
p.set(p.offseti, "-0700") 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: default:
if unicode.IsLetter(r) { if unicode.IsLetter(r) {
// 00:07:31.945167 +0000 UTC // 00:07:31.945167 +0000 UTC

View File

@ -11,8 +11,8 @@ import (
func TestOne(t *testing.T) { func TestOne(t *testing.T) {
time.Local = time.UTC time.Local = time.UTC
var ts time.Time var ts time.Time
ts = MustParse("jun. 7, 2012") ts = MustParse("2018-06-29 19:09:57.77297118 +0300 +03")
assert.Equal(t, "2012-06-07 00:00:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) assert.Equal(t, "2018-06-29 16:09:57.77297118 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
} }
type dateTest struct { 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.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-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"}, {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"}, {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 // 13:31:51.999 -07:00 MST
// yyyy-mm-dd hh:mm:ss +00:00 // yyyy-mm-dd hh:mm:ss +00:00