Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/lint.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ jobs:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Cache-Go
uses: actions/cache@v1
uses: actions/cache@v4
with:
path: |
~/go/pkg/mod # Module download cache
Expand All @@ -23,6 +23,6 @@ jobs:
restore-keys: |
${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
uses: golangci/golangci-lint-action@v7
with:
version: latest
8 changes: 4 additions & 4 deletions .github/workflows/releaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Set up Go
uses: actions/setup-go@v2
uses: actions/setup-go@v5
with:
go-version: 1.20.x
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Cache-Go
uses: actions/cache@v1
uses: actions/cache@v4
with:
path: |
~/go/pkg/mod # Module download cache
Expand All @@ -30,7 +30,7 @@ jobs:
- name: Test
run: go test ./...
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v5
uses: goreleaser/goreleaser-action@v6
with:
distribution: goreleaser
version: latest
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- name: Install Go
uses: actions/setup-go@v2
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Cache-Go
uses: actions/cache@v1
uses: actions/cache@v4
with:
path: |
~/go/pkg/mod # Module download cache
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
*.pprof
*.test
dist
vendor
vendor
dateparse/dateparse
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Go Date Parser

Parse date/time strings without knowing the format in advance. Supports 100+ formats. Validates comprehensively to avoid false positives. Very fast (~single-pass state-machine based approach). See [bench_test.go](https://github.com/itlightning/dateparse/blob/main/bench_test.go) for performance comparison. See the critical note below about timezones.

⚡ Maintained by [IT Lightning](https://itlightning.com/), a cloud-first logging platform that's uniquely powerful, super-easy (schemaless, point-and-shoot ingestion), and affordable. It automatically extracts and classifies structured data out of your unstructured log messages. Enjoy visual pattern-analysis and robust SQL-like search. It's unique architecture means you can log more and pay less. Check it out and give us feedback! ⚡
⚡ Maintained by [SparkLogs](https://sparklogs.com/), a cloud-first logging platform that's uniquely powerful, super-easy (schemaless, point-and-shoot ingestion), and affordable. It automatically extracts and classifies structured data out of your unstructured log messages. Enjoy visual pattern-analysis and robust SQL-like search. It's unique architecture means you can log more and pay less. Check it out and give us feedback! SparkLogs is developed by [IT Lightning](https://itlightning.com/).

🐛💡 Find a bug or have an idea with this package? [Issues](https://github.com/itlightning/dateparse/issues) and pull requests are welcome.

Expand Down Expand Up @@ -75,6 +75,14 @@ cli tool for testing dateformats

[Date Parse CLI](https://github.com/itlightning/dateparse/tree/main/dateparse)

Running the tests
----------------------------------

Make sure for your Linux distribution you've installed the relevant package that includes older timezone name links (e.g., `US/Pacific`). For example, on Ubuntu:

```bash
sudo apt install tzdata-legacy
```

Extended example
-------------------
Expand Down
40 changes: 40 additions & 0 deletions dateparse/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,4 +169,44 @@ Your Using time.Local set to location=America/New_York EDT
| ParseAny | time.Local = time.UTC | 2017-03-03 00:00:00 +0000 UTC | 2017-03-03 00:00:00 +0000 UTC day=5 |
+-------------+---------------------------+----------------------------------------------------+----------------------------------------------------+

# Automatically retry date formats that are ambiguous mm/dd vs dd/mm
$ ./dateparse --retry-ambiguous "28.09.2024"

Your Current time.Local zone is MDT

Layout String: dateparse.ParseFormat() => 02.01.2006

+-------------+-----------------------+----------------------------------------------------+----------------------------------------------------+
| method | Zone Source | Parsed | Parsed: t.In(time.UTC) |
+-------------+-----------------------+----------------------------------------------------+----------------------------------------------------+
| ParseIn | time.Local = nil | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC |
| ParseIn | time.Local = time.UTC | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC |
| ParseLocal | time.Local = nil | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC |
| ParseLocal | time.Local = time.UTC | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC |
| ParseStrict | time.Local = nil | this date has ambiguous mm/dd vs dd/mm type format | this date has ambiguous mm/dd vs dd/mm type format |
| ParseStrict | time.Local = time.UTC | this date has ambiguous mm/dd vs dd/mm type format | this date has ambiguous mm/dd vs dd/mm type format |
| ParseAny | time.Local = nil | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC day=6 |
| ParseAny | time.Local = time.UTC | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC day=6 |
+-------------+-----------------------+----------------------------------------------------+----------------------------------------------------+

# Force dates to be interpreted as day-first instead of month-first
$ ./dateparse --prefer-day-first "28.09.2024"

Your Current time.Local zone is MDT

Layout String: dateparse.ParseFormat() => 02.01.2006

+-------------+-----------------------+----------------------------------------------------+----------------------------------------------------+
| method | Zone Source | Parsed | Parsed: t.In(time.UTC) |
+-------------+-----------------------+----------------------------------------------------+----------------------------------------------------+
| ParseAny | time.Local = nil | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC day=6 |
| ParseAny | time.Local = time.UTC | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC day=6 |
| ParseIn | time.Local = nil | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC |
| ParseIn | time.Local = time.UTC | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC |
| ParseLocal | time.Local = nil | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC |
| ParseLocal | time.Local = time.UTC | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC |
| ParseStrict | time.Local = nil | this date has ambiguous mm/dd vs dd/mm type format | this date has ambiguous mm/dd vs dd/mm type format |
| ParseStrict | time.Local = time.UTC | this date has ambiguous mm/dd vs dd/mm type format | this date has ambiguous mm/dd vs dd/mm type format |
+-------------+-----------------------+----------------------------------------------------+----------------------------------------------------+

```
33 changes: 26 additions & 7 deletions dateparse/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,27 @@ import (
)

var (
timezone = ""
datestr = ""
timezone = ""
datestr = ""
retryAmbiguousDateWithSwap = false
preferDayFirst = false
parserOptions = []dateparse.ParserOption{}
)

func buildParserOptions() {
parserOptions = []dateparse.ParserOption{}
if retryAmbiguousDateWithSwap {
parserOptions = append(parserOptions, dateparse.RetryAmbiguousDateWithSwap(true))
}
if preferDayFirst {
parserOptions = append(parserOptions, dateparse.PreferMonthFirst(false))
}
}

func main() {
flag.StringVar(&timezone, "timezone", "", "Timezone aka `America/Los_Angeles` formatted time-zone")
flag.BoolVar(&retryAmbiguousDateWithSwap, "retry-ambiguous", false, "Retry ambiguous date/time formats (day-first vs month-first)")
flag.BoolVar(&preferDayFirst, "prefer-day-first", false, "Prefer day-first date format")
flag.Parse()

if len(flag.Args()) == 0 {
Expand All @@ -25,13 +40,17 @@ func main() {
./dateparse "2009-08-12T22:15:09.99Z"

./dateparse --timezone="America/Denver" "2017-07-19 03:21:51+00:00"
./dateparse --prefer-day-first "28.09.2024"
./dateparse --retry-ambiguous "28.09.2024"
`)
return
}

buildParserOptions()

datestr = flag.Args()[0]

layout, err := dateparse.ParseFormat(datestr)
layout, err := dateparse.ParseFormat(datestr, parserOptions...)
if err != nil {
fatal(err)
}
Expand Down Expand Up @@ -82,7 +101,7 @@ type parser func(datestr string, loc *time.Location, utc bool) string

func parseLocal(datestr string, loc *time.Location, utc bool) string {
time.Local = loc
t, err := dateparse.ParseLocal(datestr)
t, err := dateparse.ParseLocal(datestr, parserOptions...)
if err != nil {
return err.Error()
}
Expand All @@ -93,7 +112,7 @@ func parseLocal(datestr string, loc *time.Location, utc bool) string {
}

func parseIn(datestr string, loc *time.Location, utc bool) string {
t, err := dateparse.ParseIn(datestr, loc)
t, err := dateparse.ParseIn(datestr, loc, parserOptions...)
if err != nil {
return err.Error()
}
Expand All @@ -104,7 +123,7 @@ func parseIn(datestr string, loc *time.Location, utc bool) string {
}

func parseAny(datestr string, loc *time.Location, utc bool) string {
t, err := dateparse.ParseAny(datestr)
t, err := dateparse.ParseAny(datestr, parserOptions...)
if err != nil {
return err.Error()
}
Expand All @@ -115,7 +134,7 @@ func parseAny(datestr string, loc *time.Location, utc bool) string {
}

func parseStrict(datestr string, loc *time.Location, utc bool) string {
t, err := dateparse.ParseStrict(datestr)
t, err := dateparse.ParseStrict(datestr, parserOptions...)
if err != nil {
return err.Error()
}
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ go 1.20

require (
github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4
github.com/stretchr/testify v1.8.4
github.com/stretchr/testify v1.10.0
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
19 changes: 4 additions & 15 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,28 +1,17 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg=
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
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/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
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/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=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Loading
Loading