From 335c1f9218f7bc47ce48b39b7a5bd26a8f760d72 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 15:40:47 +1100 Subject: [PATCH 01/27] added some actions --- .github/workflows/lint.yaml | 29 +++++++++++++++++++++++++++++ .github/workflows/test.yaml | 28 ++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 .github/workflows/lint.yaml create mode 100644 .github/workflows/test.yaml diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml new file mode 100644 index 0000000..fcf128a --- /dev/null +++ b/.github/workflows/lint.yaml @@ -0,0 +1,29 @@ +name: golangci-lint +on: + push: + tags: + - v* + branches: + - master + - main + pull_request: +jobs: + golangci: + name: lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Cache-Go + uses: actions/cache@v1 + with: + path: | + ~/go/pkg/mod # Module download cache + ~/.cache/go-build # Build cache (Linux) + ~/Library/Caches/go-build # Build cache (Mac) + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + - name: golangci-lint + uses: golangci/golangci-lint-action@v2 + with: + version: latest diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000..a882731 --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,28 @@ +on: [push, pull_request] +name: Test +jobs: + test: + strategy: + matrix: + go-version: [1.19.x] + os: [ubuntu-latest] + runs-on: ${{ matrix.os }} + steps: + - name: Install Go + uses: actions/setup-go@v2 + with: + go-version: ${{ matrix.go-version }} + - name: Checkout code + uses: actions/checkout@v2 + - name: Cache-Go + uses: actions/cache@v1 + with: + path: | + ~/go/pkg/mod # Module download cache + ~/.cache/go-build # Build cache (Linux) + ~/Library/Caches/go-build # Build cache (Mac) + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + - name: Test + run: go test ./... From 26d95ba3e65c512b6f7ea23f7ffaedc7189d6e28 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 15:46:27 +1100 Subject: [PATCH 02/27] My issue --- parseany_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/parseany_test.go b/parseany_test.go index 7fea1e6..2759fc8 100644 --- a/parseany_test.go +++ b/parseany_test.go @@ -21,6 +21,7 @@ type dateTest struct { } var testInputs = []dateTest{ + {in: "Wed, 8 Feb 2023 19:00:46 +1100 (AEDT)", out: "2023-02-08 19:00:46 +1100 AEDT"}, {in: "oct 7, 1970", out: "1970-10-07 00:00:00 +0000 UTC"}, {in: "oct 7, '70", out: "1970-10-07 00:00:00 +0000 UTC"}, {in: "Oct 7, '70", out: "1970-10-07 00:00:00 +0000 UTC"}, From 5335e6fe23159b2ccc2ca2b60d74e0482ef964ca Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 15:49:18 +1100 Subject: [PATCH 03/27] Error return value is not checked (errcheck) --- bench_test.go | 4 ++-- go.mod | 2 +- parseany.go | 11 ++++++++--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/bench_test.go b/bench_test.go index 0c6739a..575d795 100644 --- a/bench_test.go +++ b/bench_test.go @@ -28,7 +28,7 @@ func BenchmarkShotgunParse(b *testing.B) { for i := 0; i < b.N; i++ { for _, dateStr := range testDates { // This is the non dateparse traditional approach - parseShotgunStyle(dateStr) + _ = parseShotgunStyle(dateStr) } } } @@ -37,7 +37,7 @@ func BenchmarkParseAny(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { for _, dateStr := range testDates { - ParseAny(dateStr) + _ = ParseAny(dateStr) } } } diff --git a/go.mod b/go.mod index 071cd5e..3376d23 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/araddon/dateparse -go 1.12 +go 1.19 require ( github.com/mattn/go-runewidth v0.0.10 // indirect diff --git a/parseany.go b/parseany.go index b9668b2..3214143 100644 --- a/parseany.go +++ b/parseany.go @@ -234,7 +234,10 @@ func ParseStrict(datestr string, opts ...ParserOption) (time.Time, error) { func parseTime(datestr string, loc *time.Location, opts ...ParserOption) (p *parser, err error) { - p = newParser(datestr, loc, opts...) + p, err = newParser(datestr, loc, opts...) + if err != nil { + return + } if p.retryAmbiguousDateWithSwap { // month out of range signifies that a day/month swap is the correct solution to an ambiguous date // this is because it means that a day is being interpreted as a month and overflowing the valid value for that @@ -2008,7 +2011,7 @@ func RetryAmbiguousDateWithSwap(retryAmbiguousDateWithSwap bool) ParserOption { } } -func newParser(dateStr string, loc *time.Location, opts ...ParserOption) *parser { +func newParser(dateStr string, loc *time.Location, opts ...ParserOption) (*parser, error) { p := &parser{ stateDate: dateStart, stateTime: timeIgnore, @@ -2021,7 +2024,9 @@ func newParser(dateStr string, loc *time.Location, opts ...ParserOption) *parser // allow the options to mutate the parser fields from their defaults for _, option := range opts { - option(p) + if err := option(p); err != nil { + return nil, fmt.Sprintf("option error: %w", err) + } } return p } From 14cb70eacb3a918a0871e4696b2f32c2d15ff210 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 15:50:03 +1100 Subject: [PATCH 04/27] field `offsetlen` is unused (unused) --- parseany.go | 1 - 1 file changed, 1 deletion(-) diff --git a/parseany.go b/parseany.go index 3214143..f20e8fd 100644 --- a/parseany.go +++ b/parseany.go @@ -1985,7 +1985,6 @@ type parser struct { msi int mslen int offseti int - offsetlen int tzi int tzlen int t *time.Time From 2fb4c46691d362a2a2ef7715f6da39054ee72f28 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 15:50:42 +1100 Subject: [PATCH 05/27] S1021: should merge variable declaration with assignment on next line (gosimple) --- parseany_test.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/parseany_test.go b/parseany_test.go index 2759fc8..5760e37 100644 --- a/parseany_test.go +++ b/parseany_test.go @@ -10,8 +10,7 @@ import ( func TestOne(t *testing.T) { time.Local = time.UTC - var ts time.Time - ts = MustParse("2020-07-20+08:00") + var ts time.Time = MustParse("2020-07-20+08:00") assert.Equal(t, "2020-07-19 16:00:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) } From 5143d47e3e263c4fee712bf3cb87cd54edbe0298 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 15:51:14 +1100 Subject: [PATCH 06/27] S1023: redundant break statement (gosimple) --- parseany.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/parseany.go b/parseany.go index f20e8fd..a37bec5 100644 --- a/parseany.go +++ b/parseany.go @@ -1442,7 +1442,6 @@ iterRunes: 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 @@ -1452,7 +1451,6 @@ iterRunes: p.extra = i - 1 p.stateTime = timeWsOffset p.trimExtra() - break default: switch { case unicode.IsDigit(r): From 57a1767ebd6d936dea7700633b1a9f977e17b984 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 15:51:48 +1100 Subject: [PATCH 07/27] SA4006: this value of `err` is never used (staticcheck) --- parseany.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parseany.go b/parseany.go index a37bec5..02074e3 100644 --- a/parseany.go +++ b/parseany.go @@ -253,7 +253,7 @@ func parseTime(datestr string, loc *time.Location, opts ...ParserOption) (p *par // turn off the retry to avoid endless recursion retryAmbiguousDateWithSwap := RetryAmbiguousDateWithSwap(false) modifiedOpts := append(opts, preferMonthFirst, retryAmbiguousDateWithSwap) - p, err = parseTime(datestr, time.Local, modifiedOpts...) + p, _ = parseTime(datestr, time.Local, modifiedOpts...) } } From ad0ab84f6bfab649b0039583ce81c8c06d4ba58f Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 15:53:01 +1100 Subject: [PATCH 08/27] Lint action out of date. --- .github/workflows/lint.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index fcf128a..1a998e5 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -24,6 +24,6 @@ jobs: restore-keys: | ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - name: golangci-lint - uses: golangci/golangci-lint-action@v2 + uses: golangci/golangci-lint-action@v3 with: version: latest From a8e238d5d1b0afd42e78b3ebb5dd7facd7a071a3 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 15:55:15 +1100 Subject: [PATCH 09/27] Go mod tidy --- go.mod | 9 ++++++++- go.sum | 1 - 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 3376d23..baa649f 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,14 @@ module github.com/araddon/dateparse go 1.19 require ( - github.com/mattn/go-runewidth v0.0.10 // indirect github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4 github.com/stretchr/testify v1.7.0 ) + +require ( + github.com/davecgh/go-spew v1.1.0 // indirect + github.com/mattn/go-runewidth v0.0.10 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rivo/uniseg v0.1.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect +) diff --git a/go.sum b/go.sum index 40bf744..370a49d 100644 --- a/go.sum +++ b/go.sum @@ -8,7 +8,6 @@ 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.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= From e654ac7b35439e0f54497a819b012a4b3f855322 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 15:56:17 +1100 Subject: [PATCH 10/27] Bug fixes. --- parseany.go | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/parseany.go b/parseany.go index 02074e3..79cb927 100644 --- a/parseany.go +++ b/parseany.go @@ -170,15 +170,14 @@ func ParseIn(datestr string, loc *time.Location, opts ...ParserOption) (time.Tim // Set Location to time.Local. Same as ParseIn Location but lazily uses // the global time.Local variable for Location argument. // -// denverLoc, _ := time.LoadLocation("America/Denver") -// time.Local = denverLoc +// denverLoc, _ := time.LoadLocation("America/Denver") +// time.Local = denverLoc // -// t, err := dateparse.ParseLocal("3/1/2014") +// t, err := dateparse.ParseLocal("3/1/2014") // // Equivalent to: // -// t, err := dateparse.ParseIn("3/1/2014", denverLoc) -// +// t, err := dateparse.ParseIn("3/1/2014", denverLoc) func ParseLocal(datestr string, opts ...ParserOption) (time.Time, error) { p, err := parseTime(datestr, time.Local, opts...) if err != nil { @@ -204,9 +203,8 @@ func MustParse(datestr string, opts ...ParserOption) time.Time { // ParseFormat parse's an unknown date-time string and returns a layout // string that can parse this (and exact same format) other date-time strings. // -// layout, err := dateparse.ParseFormat("2013-02-01 00:00:00") -// // layout = "2006-01-02 15:04:05" -// +// layout, err := dateparse.ParseFormat("2013-02-01 00:00:00") +// // layout = "2006-01-02 15:04:05" func ParseFormat(datestr string, opts ...ParserOption) (string, error) { p, err := parseTime(datestr, nil, opts...) if err != nil { @@ -2022,10 +2020,10 @@ func newParser(dateStr string, loc *time.Location, opts ...ParserOption) (*parse // allow the options to mutate the parser fields from their defaults for _, option := range opts { if err := option(p); err != nil { - return nil, fmt.Sprintf("option error: %w", err) + return nil, fmt.Errorf("option error: %w", err) } } - return p + return p, nil } func (p *parser) nextIs(i int, b byte) bool { From cefe5b3dbe7d5586690a7a6850bf21313cd3e631 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 15:56:43 +1100 Subject: [PATCH 11/27] More typo changes --- bench_test.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/bench_test.go b/bench_test.go index 575d795..4322b86 100644 --- a/bench_test.go +++ b/bench_test.go @@ -7,7 +7,6 @@ import ( ) /* - go test -bench Parse BenchmarkShotgunParse 50000 37588 ns/op 13258 B/op 167 allocs/op @@ -21,14 +20,13 @@ BenchmarkParseAny-4 200000 8627 ns/op 144 B/op 3 allo BenchmarkShotgunParse-8 50000 33940 ns/op 13136 B/op 169 allocs/op BenchmarkParseAny-8 200000 10146 ns/op 912 B/op 29 allocs/op BenchmarkParseDateString-8 10000 123077 ns/op 208 B/op 13 allocs/op - */ func BenchmarkShotgunParse(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { for _, dateStr := range testDates { // This is the non dateparse traditional approach - _ = parseShotgunStyle(dateStr) + _, _ = parseShotgunStyle(dateStr) } } } @@ -37,7 +35,7 @@ func BenchmarkParseAny(b *testing.B) { b.ReportAllocs() for i := 0; i < b.N; i++ { for _, dateStr := range testDates { - _ = ParseAny(dateStr) + _, _ = ParseAny(dateStr) } } } From 4345a38e91b61174f1140f5313b8e55f3c9f3302 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 15:57:15 +1100 Subject: [PATCH 12/27] Another error --- parseany_test.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/parseany_test.go b/parseany_test.go index 5760e37..e4f9de9 100644 --- a/parseany_test.go +++ b/parseany_test.go @@ -488,7 +488,10 @@ func TestPStruct(t *testing.T) { denverLoc, err := time.LoadLocation("America/Denver") assert.Equal(t, nil, err) - p := newParser("08.21.71", denverLoc) + p, err := newParser("08.21.71", denverLoc) + if err != nil { + t.Fatalf("Parser build error: %s", err) + } p.setMonth() assert.Equal(t, 0, p.moi) From 515cd8176782b7e9ba7d31866085bbd56294d2e9 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 16:02:13 +1100 Subject: [PATCH 13/27] S1023: redundant break statement (gosimple) --- parseany.go | 1 - 1 file changed, 1 deletion(-) diff --git a/parseany.go b/parseany.go index 79cb927..c92ceec 100644 --- a/parseany.go +++ b/parseany.go @@ -1595,7 +1595,6 @@ iterRunes: // 00:00:00.000 +0300 +0300 p.extra = i - 1 p.trimExtra() - break default: if unicode.IsLetter(r) { // 00:07:31.945167 +0000 UTC From eabb56b497f00476613f1579f7dde062ae4375dd Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 16:04:58 +1100 Subject: [PATCH 14/27] Text should be lowercase --- parseany.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parseany.go b/parseany.go index c92ceec..c5d0716 100644 --- a/parseany.go +++ b/parseany.go @@ -133,7 +133,7 @@ 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") + ErrAmbiguousMMDD = fmt.Errorf("this date has ambiguous mm/dd vs dd/mm type format") ) func unknownErr(datestr string) error { From c5b562ac1ae744092d1a6ca7a2588526ee3d7c93 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 16:06:01 +1100 Subject: [PATCH 15/27] Added go releaser --- .github/workflows/releaser.yml | 39 ++++++++++++++++++++++++++++++++++ .goreleaser.yml | 38 +++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 .github/workflows/releaser.yml create mode 100644 .goreleaser.yml diff --git a/.github/workflows/releaser.yml b/.github/workflows/releaser.yml new file mode 100644 index 0000000..cc06e22 --- /dev/null +++ b/.github/workflows/releaser.yml @@ -0,0 +1,39 @@ +name: releaser + +on: + push: + tags: + - 'v*.*.*' + +jobs: + goreleaser: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: 1.19 + - name: Cache-Go + uses: actions/cache@v1 + with: + path: | + ~/go/pkg/mod # Module download cache + ~/.cache/go-build # Build cache (Linux) + ~/Library/Caches/go-build # Build cache (Mac) + key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + restore-keys: | + ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} + - name: Test + run: go test ./... + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v2 + with: + distribution: goreleaser + version: latest + args: release --rm-dist + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 0000000..dab3f5c --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,38 @@ +project_name: dateparse +builds: + - + id: "dateparse" + binary: "dateparse" + dir: dateparse + - + id: "example" + binary: "example" + dir: example +archives: + - + format_overrides: + - goos: windows + format: zip +checksum: + name_template: 'checksums.txt' +snapshot: + name_template: "{{ .Tag }}-next" +changelog: + sort: asc + filters: + exclude: + - '^docs:' + - '^test:' +nfpms: + - + vendor: dateparse + homepage: https://github.com/araddon/dateparse + maintainer: n/a + description: NA + formats: + - apk + - deb + - rpm + release: 1 + section: default + priority: extra From 094aad3f21a5f6f2c2c21bbd109fbf0c32800e24 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 16:09:32 +1100 Subject: [PATCH 16/27] Commented code --- parseany.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/parseany.go b/parseany.go index c5d0716..042c2fb 100644 --- a/parseany.go +++ b/parseany.go @@ -468,8 +468,6 @@ iterRunes: switch r { case ':': p.set(p.offseti, "-07:00") - // case ' ': - // return nil, unknownErr(datestr) } case dateYearDashAlphaDash: From 53a8cbdf09066b72c98a5d3b61d478a2aa6337e5 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 16:10:45 +1100 Subject: [PATCH 17/27] Unnecessary bracket --- parseany.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parseany.go b/parseany.go index 042c2fb..73b0585 100644 --- a/parseany.go +++ b/parseany.go @@ -269,7 +269,7 @@ iterRunes: //r := rune(datestr[i]) r, bytesConsumed := utf8.DecodeRuneInString(datestr[i:]) if bytesConsumed > 1 { - i += (bytesConsumed - 1) + i += bytesConsumed - 1 } // gou.Debugf("i=%d r=%s state=%d %s", i, string(r), p.stateDate, datestr) From 544b5426f4e03bcc4bc30e85a876848e6cf8871c Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 16:20:46 +1100 Subject: [PATCH 18/27] Test improvements.. I think --- parseany_test.go | 51 +++++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/parseany_test.go b/parseany_test.go index e4f9de9..7582465 100644 --- a/parseany_test.go +++ b/parseany_test.go @@ -10,7 +10,7 @@ import ( func TestOne(t *testing.T) { time.Local = time.UTC - var ts time.Time = MustParse("2020-07-20+08:00") + var ts = MustParse("2020-07-20+08:00") assert.Equal(t, "2020-07-19 16:00:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) } @@ -435,28 +435,35 @@ func TestParse(t *testing.T) { assert.NotEqual(t, nil, err) for _, th := range testInputs { - if len(th.loc) > 0 { - loc, err := time.LoadLocation(th.loc) - if err != nil { - t.Fatalf("Expected to load location %q but got %v", th.loc, err) + t.Run(th.in, func(t *testing.T) { + defer func() { + if r := recover(); r != nil { + t.Fatalf("error: %s", r) + } + }() + if len(th.loc) > 0 { + loc, err := time.LoadLocation(th.loc) + if err != nil { + t.Fatalf("Expected to load location %q but got %v", th.loc, err) + } + ts, err = ParseIn(th.in, loc) + if err != nil { + t.Fatalf("expected to parse %q but got %v", th.in, err) + } + got := fmt.Sprintf("%v", ts.In(time.UTC)) + assert.Equal(t, th.out, got, "Expected %q but got %q from %q", th.out, got, th.in) + if th.out != got { + t.Fatalf("whoops, got %s, expected %s", got, th.out) + } + } else { + ts = MustParse(th.in) + got := fmt.Sprintf("%v", ts.In(time.UTC)) + assert.Equal(t, th.out, got, "Expected %q but got %q from %q", th.out, got, th.in) + if th.out != got { + t.Fatalf("whoops, got %s, expected %s", got, th.out) + } } - ts, err = ParseIn(th.in, loc) - if err != nil { - t.Fatalf("expected to parse %q but got %v", th.in, err) - } - got := fmt.Sprintf("%v", ts.In(time.UTC)) - assert.Equal(t, th.out, got, "Expected %q but got %q from %q", th.out, got, th.in) - if th.out != got { - panic("whoops") - } - } else { - ts = MustParse(th.in) - got := fmt.Sprintf("%v", ts.In(time.UTC)) - assert.Equal(t, th.out, got, "Expected %q but got %q from %q", th.out, got, th.in) - if th.out != got { - panic("whoops") - } - } + }) } // some errors From c5a1edc7107fb3e49b4174e15c4a68e080e04694 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 16:24:05 +1100 Subject: [PATCH 19/27] My addition last --- parseany_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/parseany_test.go b/parseany_test.go index 7582465..5d86f31 100644 --- a/parseany_test.go +++ b/parseany_test.go @@ -20,7 +20,6 @@ type dateTest struct { } var testInputs = []dateTest{ - {in: "Wed, 8 Feb 2023 19:00:46 +1100 (AEDT)", out: "2023-02-08 19:00:46 +1100 AEDT"}, {in: "oct 7, 1970", out: "1970-10-07 00:00:00 +0000 UTC"}, {in: "oct 7, '70", out: "1970-10-07 00:00:00 +0000 UTC"}, {in: "Oct 7, '70", out: "1970-10-07 00:00:00 +0000 UTC"}, @@ -417,6 +416,8 @@ var testInputs = []dateTest{ {in: "1384216367111", out: "2013-11-12 00:32:47.111 +0000 UTC"}, {in: "1384216367111222", out: "2013-11-12 00:32:47.111222 +0000 UTC"}, {in: "1384216367111222333", out: "2013-11-12 00:32:47.111222333 +0000 UTC"}, + + {in: "Wed, 8 Feb 2023 19:00:46 +1100 (AEDT)", out: "2023-02-08 08:00:46 +0000 UTC"}, } func TestParse(t *testing.T) { From 268a69008173d53ed659b40a278c29c454b850ff Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 16:26:18 +1100 Subject: [PATCH 20/27] So people don't have to check the string they can use the new errors.Is function --- parseany.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/parseany.go b/parseany.go index 73b0585..dd0ea85 100644 --- a/parseany.go +++ b/parseany.go @@ -133,11 +133,12 @@ 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") + ErrAmbiguousMMDD = fmt.Errorf("this date has ambiguous mm/dd vs dd/mm type format") + ErrCouldntFindFormat = fmt.Errorf("could not find format for") ) func unknownErr(datestr string) error { - return fmt.Errorf("Could not find format for %q", datestr) + return fmt.Errorf("%w %q", ErrCouldntFindFormat, datestr) } // ParseAny parse an unknown date format, detect the layout. From bf3a5b3040cd0f3aa6c17112d3f2d7b0a740985b Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 16:27:43 +1100 Subject: [PATCH 21/27] Skip white space - to delete strategically --- parseany.go | 116 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 109 insertions(+), 7 deletions(-) diff --git a/parseany.go b/parseany.go index dd0ea85..915051c 100644 --- a/parseany.go +++ b/parseany.go @@ -383,6 +383,9 @@ iterRunes: } case ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } // 18 January 2018 // 8 January 2018 // 8 jan 2018 @@ -446,6 +449,9 @@ iterRunes: p.stateDate = dateYearDashDashOffset p.setDay() case ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } p.daylen = i - p.dayi p.stateDate = dateYearDashDashWs p.stateTime = timeStart @@ -506,6 +512,9 @@ iterRunes: // 29-Jun-2016 dd-month(alpha)-yyyy switch r { case ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } // we need to find if this was 4 digits, aka year // or 2 digits which makes it ambiguous year/day length := i - (p.moi + p.molen + 1) @@ -538,7 +547,12 @@ iterRunes: // I honestly don't know if this format ever shows up as yyyy/ switch r { - case ' ', ':': + case ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } + fallthrough + case ':': p.stateTime = timeStart if p.daylen == 0 { p.daylen = i - p.dayi @@ -566,7 +580,12 @@ iterRunes: } // We aren't breaking because we are going to re-use this case // to find where the date starts, and possible time begins - case ' ', ':': + case ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } + fallthrough + case ':': p.stateTime = timeStart if p.yearlen == 0 { p.yearlen = i - p.yeari @@ -604,6 +623,9 @@ iterRunes: // Note no break, we are going to pass by and re-enter this dateDigitSlash // and look for ending (space) or not (just date) case ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } p.stateTime = timeStart if p.yearlen == 0 { p.yearlen = i - p.yeari @@ -625,6 +647,9 @@ iterRunes: switch r { case ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } p.stateTime = timeStart if p.yearlen == 0 { p.yearlen = i - p.yeari @@ -662,6 +687,9 @@ iterRunes: // 12 Feb 2006, 19:17:22 switch r { case ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } p.yeari = i + 1 //p.yearlen = 4 p.dayi = 0 @@ -696,6 +724,9 @@ iterRunes: i++ break iterRunes case ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } p.yearlen = i - p.yeari p.setYear() break iterRunes @@ -710,6 +741,9 @@ iterRunes: // weekday %Y年%m月%e日 %A %I:%M %p // 2013年07月18日 星期四 10:27 上午 if r == ' ' { + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } p.stateDate = dateDigitChineseYearWs break } @@ -770,6 +804,9 @@ iterRunes: case r == ' ': // X // April 8, 2009 + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } if i > 3 { // Check to see if the alpha is name of month? or Day? month := strings.ToLower(datestr[0:i]) @@ -877,6 +914,9 @@ iterRunes: p.setDay() p.stateDate = dateAlphaWsDigitMore } else if r == ' ' { + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } p.daylen = i - p.dayi p.setDay() p.yeari = i + 1 @@ -900,6 +940,9 @@ iterRunes: p.yeari = 0 break iterRunes } else if r == ' ' { + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } // must be year format, not 15:04 p.yearlen = i - p.yeari p.setYear() @@ -913,6 +956,9 @@ iterRunes: // oct 1, 1970 // oct 7, '70 if r == ' ' { + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } p.yeari = i + 1 p.stateDate = dateAlphaWsDigitMoreWs } @@ -925,7 +971,12 @@ iterRunes: switch r { case '\'': p.yeari = i + 1 - case ' ', ',': + case ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } + fallthrough + case ',': // x // May 8, 2009 5:57:51 PM // x @@ -941,7 +992,12 @@ iterRunes: // April 8, 2009 // April 8 2009 switch r { - case ' ', ',': + case ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } + fallthrough + case ',': // x // June 8, 2009 // x @@ -973,6 +1029,9 @@ iterRunes: i++ break iterRunes case ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } p.yearlen = i - p.yeari p.setYear() p.stateTime = timeStart @@ -1027,6 +1086,9 @@ iterRunes: } case r == ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } // x // January 02 2006, 15:04:05 p.daylen = i - p.dayi @@ -1050,6 +1112,9 @@ iterRunes: // oct. 7, '70 switch { case r == ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } // continue case unicode.IsDigit(r): p.stateDate = dateAlphaWsDigit @@ -1066,7 +1131,12 @@ iterRunes: p.dayi = i } switch r { - case ' ', '-': + case ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } + fallthrough + case '-': if p.moi == 0 { p.moi = i + 1 p.daylen = i - p.dayi @@ -1088,7 +1158,12 @@ iterRunes: // Tue, 11 Jul 2017 16:28:13 +0200 (CEST) // Mon, 02-Jan-06 15:04:05 MST switch r { - case ' ', '-': + case ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } + fallthrough + case '-': if p.dayi == 0 { p.dayi = i + 1 } else if p.moi == 0 { @@ -1215,7 +1290,10 @@ iterRunes: if p.nextIs(i, ' ') { // x // September 17, 2012 at 5:00pm UTC-05 - i++ // skip ' + i++ // skip ' + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } p.houri = 0 // reset hour } } else { @@ -1240,6 +1318,9 @@ iterRunes: p.set(i, "PM") } case ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } p.coalesceTime(i) p.stateTime = timeWs case ':': @@ -1337,6 +1418,9 @@ iterRunes: p.stateTime = timeWsAlphaZoneOffset p.offseti = i case ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } // 17:57:51 MST 2009 // 17:57:51 MST p.tzlen = i - p.tzi @@ -1361,6 +1445,9 @@ iterRunes: // 15:44:11 UTC+0100 2015 switch r { case ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } p.set(p.offseti, "-0700") if p.yeari == 0 { p.yeari = i + 1 @@ -1423,6 +1510,9 @@ iterRunes: case ':': p.stateTime = timeWsOffsetColon case ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } p.set(p.offseti, "-0700") p.yeari = i + 1 p.stateTime = timeWsOffsetWs @@ -1503,6 +1593,9 @@ iterRunes: // 06:20:00.000 UTC switch r { case ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } p.mslen = i - p.msi p.stateTime = timePeriodWs case '+', '-': @@ -1533,6 +1626,9 @@ iterRunes: // 13:31:51.999 -07:00 MST switch r { case ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } p.set(p.offseti, "-07:00") p.stateTime = timePeriodOffsetColonWs p.tzi = i + 1 @@ -1586,6 +1682,9 @@ iterRunes: case ':': p.stateTime = timePeriodWsOffsetColon case ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } p.set(p.offseti, "-0700") case '+', '-': // This really doesn't seem valid, but for some reason when round-tripping a go date @@ -1615,6 +1714,9 @@ iterRunes: // 13:31:51.999 -07:00 MST switch r { case ' ': + for i+1 < len(datestr) && datestr[i+1] == ' ' { + i++ + } p.set(p.offseti, "-07:00") default: if unicode.IsLetter(r) { From 3a32cbb3d2ddb32f6fcd4d7ea241cfdce3c27d24 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 16:28:56 +1100 Subject: [PATCH 22/27] All of these did nothing --- parseany.go | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/parseany.go b/parseany.go index 915051c..078fc3e 100644 --- a/parseany.go +++ b/parseany.go @@ -383,9 +383,6 @@ iterRunes: } case ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } // 18 January 2018 // 8 January 2018 // 8 jan 2018 @@ -449,9 +446,6 @@ iterRunes: p.stateDate = dateYearDashDashOffset p.setDay() case ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } p.daylen = i - p.dayi p.stateDate = dateYearDashDashWs p.stateTime = timeStart @@ -512,9 +506,6 @@ iterRunes: // 29-Jun-2016 dd-month(alpha)-yyyy switch r { case ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } // we need to find if this was 4 digits, aka year // or 2 digits which makes it ambiguous year/day length := i - (p.moi + p.molen + 1) @@ -548,9 +539,6 @@ iterRunes: switch r { case ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } fallthrough case ':': p.stateTime = timeStart @@ -581,9 +569,6 @@ iterRunes: // We aren't breaking because we are going to re-use this case // to find where the date starts, and possible time begins case ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } fallthrough case ':': p.stateTime = timeStart @@ -623,9 +608,6 @@ iterRunes: // Note no break, we are going to pass by and re-enter this dateDigitSlash // and look for ending (space) or not (just date) case ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } p.stateTime = timeStart if p.yearlen == 0 { p.yearlen = i - p.yeari @@ -647,9 +629,6 @@ iterRunes: switch r { case ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } p.stateTime = timeStart if p.yearlen == 0 { p.yearlen = i - p.yeari @@ -687,9 +666,6 @@ iterRunes: // 12 Feb 2006, 19:17:22 switch r { case ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } p.yeari = i + 1 //p.yearlen = 4 p.dayi = 0 @@ -724,9 +700,6 @@ iterRunes: i++ break iterRunes case ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } p.yearlen = i - p.yeari p.setYear() break iterRunes @@ -741,9 +714,6 @@ iterRunes: // weekday %Y年%m月%e日 %A %I:%M %p // 2013年07月18日 星期四 10:27 上午 if r == ' ' { - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } p.stateDate = dateDigitChineseYearWs break } @@ -804,9 +774,6 @@ iterRunes: case r == ' ': // X // April 8, 2009 - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } if i > 3 { // Check to see if the alpha is name of month? or Day? month := strings.ToLower(datestr[0:i]) From b1fd89e43f72b58e0aa987c45f818a8cf6b24bb6 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 16:31:37 +1100 Subject: [PATCH 23/27] The only required one. --- parseany.go | 56 +---------------------------------------------------- 1 file changed, 1 insertion(+), 55 deletions(-) diff --git a/parseany.go b/parseany.go index 078fc3e..8933b64 100644 --- a/parseany.go +++ b/parseany.go @@ -881,9 +881,6 @@ iterRunes: p.setDay() p.stateDate = dateAlphaWsDigitMore } else if r == ' ' { - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } p.daylen = i - p.dayi p.setDay() p.yeari = i + 1 @@ -907,9 +904,6 @@ iterRunes: p.yeari = 0 break iterRunes } else if r == ' ' { - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } // must be year format, not 15:04 p.yearlen = i - p.yeari p.setYear() @@ -923,9 +917,6 @@ iterRunes: // oct 1, 1970 // oct 7, '70 if r == ' ' { - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } p.yeari = i + 1 p.stateDate = dateAlphaWsDigitMoreWs } @@ -939,9 +930,6 @@ iterRunes: case '\'': p.yeari = i + 1 case ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } fallthrough case ',': // x @@ -960,9 +948,6 @@ iterRunes: // April 8 2009 switch r { case ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } fallthrough case ',': // x @@ -996,9 +981,6 @@ iterRunes: i++ break iterRunes case ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } p.yearlen = i - p.yeari p.setYear() p.stateTime = timeStart @@ -1053,9 +1035,6 @@ iterRunes: } case r == ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } // x // January 02 2006, 15:04:05 p.daylen = i - p.dayi @@ -1079,9 +1058,6 @@ iterRunes: // oct. 7, '70 switch { case r == ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } // continue case unicode.IsDigit(r): p.stateDate = dateAlphaWsDigit @@ -1099,9 +1075,6 @@ iterRunes: } switch r { case ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } fallthrough case '-': if p.moi == 0 { @@ -1257,10 +1230,7 @@ iterRunes: if p.nextIs(i, ' ') { // x // September 17, 2012 at 5:00pm UTC-05 - i++ // skip ' - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } + i++ // skip ' p.houri = 0 // reset hour } } else { @@ -1285,9 +1255,6 @@ iterRunes: p.set(i, "PM") } case ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } p.coalesceTime(i) p.stateTime = timeWs case ':': @@ -1385,9 +1352,6 @@ iterRunes: p.stateTime = timeWsAlphaZoneOffset p.offseti = i case ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } // 17:57:51 MST 2009 // 17:57:51 MST p.tzlen = i - p.tzi @@ -1412,9 +1376,6 @@ iterRunes: // 15:44:11 UTC+0100 2015 switch r { case ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } p.set(p.offseti, "-0700") if p.yeari == 0 { p.yeari = i + 1 @@ -1477,9 +1438,6 @@ iterRunes: case ':': p.stateTime = timeWsOffsetColon case ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } p.set(p.offseti, "-0700") p.yeari = i + 1 p.stateTime = timeWsOffsetWs @@ -1560,9 +1518,6 @@ iterRunes: // 06:20:00.000 UTC switch r { case ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } p.mslen = i - p.msi p.stateTime = timePeriodWs case '+', '-': @@ -1593,9 +1548,6 @@ iterRunes: // 13:31:51.999 -07:00 MST switch r { case ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } p.set(p.offseti, "-07:00") p.stateTime = timePeriodOffsetColonWs p.tzi = i + 1 @@ -1649,9 +1601,6 @@ iterRunes: case ':': p.stateTime = timePeriodWsOffsetColon case ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } p.set(p.offseti, "-0700") case '+', '-': // This really doesn't seem valid, but for some reason when round-tripping a go date @@ -1681,9 +1630,6 @@ iterRunes: // 13:31:51.999 -07:00 MST switch r { case ' ': - for i+1 < len(datestr) && datestr[i+1] == ' ' { - i++ - } p.set(p.offseti, "-07:00") default: if unicode.IsLetter(r) { From 19ef6a25eb4b3a152f7a7610e5292212e142e393 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 17:34:02 +1100 Subject: [PATCH 24/27] New failure - still white space --- parseany_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/parseany_test.go b/parseany_test.go index 5d86f31..b5345a5 100644 --- a/parseany_test.go +++ b/parseany_test.go @@ -418,6 +418,7 @@ var testInputs = []dateTest{ {in: "1384216367111222333", out: "2013-11-12 00:32:47.111222333 +0000 UTC"}, {in: "Wed, 8 Feb 2023 19:00:46 +1100 (AEDT)", out: "2023-02-08 08:00:46 +0000 UTC"}, + {in: "FRI, 16 AUG 2013 9:39:51 +1000", out: "2013-08-15 23:39:51 +0000 UTC"}, } func TestParse(t *testing.T) { From 8b765a53023b55d55b01e751341b0ad02b9defe0 Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 23:37:23 +1100 Subject: [PATCH 25/27] Skip white space --- parseany.go | 6 ++++-- parseany_test.go | 39 +++++++++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/parseany.go b/parseany.go index 8933b64..4f3b72d 100644 --- a/parseany.go +++ b/parseany.go @@ -1097,10 +1097,12 @@ iterRunes: // Thu, 4 Jan 2018 17:53:36 +0000 // Tue, 11 Jul 2017 16:28:13 +0200 (CEST) // Mon, 02-Jan-06 15:04:05 MST + var offset int switch r { case ' ': for i+1 < len(datestr) && datestr[i+1] == ' ' { i++ + offset++ } fallthrough case '-': @@ -1111,11 +1113,11 @@ iterRunes: p.setDay() p.moi = i + 1 } else if p.yeari == 0 { - p.molen = i - p.moi + p.molen = i - p.moi - offset p.set(p.moi, "Jan") p.yeari = i + 1 } else { - p.yearlen = i - p.yeari + p.yearlen = i - p.yeari - offset p.setYear() p.stateTime = timeStart break iterRunes diff --git a/parseany_test.go b/parseany_test.go index b5345a5..aeb201f 100644 --- a/parseany_test.go +++ b/parseany_test.go @@ -427,17 +427,20 @@ func TestParse(t *testing.T) { time.Local = time.UTC zeroTime := time.Time{}.Unix() - ts, err := ParseAny("INVALID") - assert.Equal(t, zeroTime, ts.Unix()) - assert.NotEqual(t, nil, err) + t.Run("Invalid", func(t *testing.T) { + ts, err := ParseAny("INVALID") + assert.Equal(t, zeroTime, ts.Unix()) + assert.NotEqual(t, nil, err) - assert.Equal(t, true, testDidPanic("NOT GONNA HAPPEN")) - // https://github.com/golang/go/issues/5294 - _, err = ParseAny(time.RFC3339) - assert.NotEqual(t, nil, err) + assert.Equal(t, true, testDidPanic("NOT GONNA HAPPEN")) + // https://github.com/golang/go/issues/5294 + _, err = ParseAny(time.RFC3339) + assert.NotEqual(t, nil, err) + }) for _, th := range testInputs { t.Run(th.in, func(t *testing.T) { + var ts time.Time defer func() { if r := recover(); r != nil { t.Fatalf("error: %s", r) @@ -470,16 +473,24 @@ func TestParse(t *testing.T) { // some errors - assert.Equal(t, true, testDidPanic(`{"ts":"now"}`)) + t.Run("", func(t *testing.T) { + assert.Equal(t, true, testDidPanic(`{"ts":"now"}`)) + }) - _, err = ParseAny("138421636711122233311111") // too many digits - assert.NotEqual(t, nil, err) + t.Run("too many digits", func(t *testing.T) { + _, err := ParseAny("138421636711122233311111") // too many digits + assert.NotEqual(t, nil, err) + }) - _, err = ParseAny("-1314") - assert.NotEqual(t, nil, err) + t.Run("negative number", func(t *testing.T) { + _, err := ParseAny("-1314") + assert.NotEqual(t, nil, err) + }) - _, err = ParseAny("2014-13-13 08:20:13,787") // month 13 doesn't exist so error - assert.NotEqual(t, nil, err) + t.Run("month doesn't exist", func(t *testing.T) { + _, err := ParseAny("2014-13-13 08:20:13,787") // month 13 doesn't exist so error + assert.NotEqual(t, nil, err) + }) } func testDidPanic(datestr string) (paniced bool) { From b0b5409675c652d98f67960dfed5ae31c8d9851b Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Wed, 15 Feb 2023 23:37:27 +1100 Subject: [PATCH 26/27] Unused code --- parseany.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/parseany.go b/parseany.go index 4f3b72d..0407b79 100644 --- a/parseany.go +++ b/parseany.go @@ -2156,17 +2156,6 @@ func (p *parser) trimExtra() { } } -// func (p *parser) remove(i, length int) { -// if len(p.format) > i+length { -// //append(a[:i], a[j:]...) -// p.format = append(p.format[0:i], p.format[i+length:]...) -// } -// if len(p.datestr) > i+length { -// //append(a[:i], a[j:]...) -// p.datestr = fmt.Sprintf("%s%s", p.datestr[0:i], p.datestr[i+length:]) -// } -// } - func (p *parser) parse() (time.Time, error) { if p.t != nil { return *p.t, nil From 01b692d1ce4d329cac9290001673b0446acf599d Mon Sep 17 00:00:00 2001 From: Arran Ubels Date: Thu, 16 Feb 2023 09:39:34 +1100 Subject: [PATCH 27/27] Another case. --- parseany.go | 14 +++++++++++--- parseany_test.go | 1 + 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/parseany.go b/parseany.go index 0407b79..b427d68 100644 --- a/parseany.go +++ b/parseany.go @@ -1345,7 +1345,12 @@ iterRunes: // 15:44:11 UTC+0100 2015 switch r { case '+', '-': - p.tzlen = i - p.tzi + if datestr[p.tzi:i] == "GMT" { + p.tzi = 0 + p.tzlen = 0 + } else { + p.tzlen = i - p.tzi + } if p.tzlen == 4 { p.set(p.tzi, " MST") } else if p.tzlen == 3 { @@ -1679,10 +1684,13 @@ iterRunes: p.trimExtra() case timeWsAlphaZoneOffset: // 06:20:00 UTC-05 - if i-p.offseti < 4 { + switch i - p.offseti { + case 2, 3, 4: p.set(p.offseti, "-07") - } else { + case 5: p.set(p.offseti, "-0700") + case 6: + p.set(p.offseti, "-07:00") } case timePeriod: diff --git a/parseany_test.go b/parseany_test.go index aeb201f..0193b52 100644 --- a/parseany_test.go +++ b/parseany_test.go @@ -419,6 +419,7 @@ var testInputs = []dateTest{ {in: "Wed, 8 Feb 2023 19:00:46 +1100 (AEDT)", out: "2023-02-08 08:00:46 +0000 UTC"}, {in: "FRI, 16 AUG 2013 9:39:51 +1000", out: "2013-08-15 23:39:51 +0000 UTC"}, + {in: "Mon, 1 Dec 2008 14:48:22 GMT-07:00", out: "2008-12-01 21:48:22 +0000 UTC"}, } func TestParse(t *testing.T) {