Skip to content

Commit fe33a56

Browse files
Add prefer-day-first flag and relatedto example program
Support --prefer-day-first and --retry-ambiguous flags for example program. Also provide an example where parsing would fail without it.
1 parent eeb01af commit fe33a56

File tree

4 files changed

+77
-9
lines changed

4 files changed

+77
-9
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
*.pprof
22
*.test
33
dist
4-
vendor
4+
vendor
5+
dateparse/dateparse

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Go Date Parser
66

77
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.
88

9-
⚡ 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! ⚡
9+
⚡ 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/).
1010

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

@@ -75,6 +75,14 @@ cli tool for testing dateformats
7575

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

78+
Running the tests
79+
----------------------------------
80+
81+
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:
82+
83+
```bash
84+
sudo apt install tzdata-legacy
85+
```
7886

7987
Extended example
8088
-------------------

dateparse/README.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,4 +169,44 @@ Your Using time.Local set to location=America/New_York EDT
169169
| ParseAny | time.Local = time.UTC | 2017-03-03 00:00:00 +0000 UTC | 2017-03-03 00:00:00 +0000 UTC day=5 |
170170
+-------------+---------------------------+----------------------------------------------------+----------------------------------------------------+
171171

172+
# Automatically retry date formats that are ambiguous mm/dd vs dd/mm
173+
$ ./dateparse --retry-ambiguous "28.09.2024"
174+
175+
Your Current time.Local zone is MDT
176+
177+
Layout String: dateparse.ParseFormat() => 02.01.2006
178+
179+
+-------------+-----------------------+----------------------------------------------------+----------------------------------------------------+
180+
| method | Zone Source | Parsed | Parsed: t.In(time.UTC) |
181+
+-------------+-----------------------+----------------------------------------------------+----------------------------------------------------+
182+
| ParseIn | time.Local = nil | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC |
183+
| ParseIn | time.Local = time.UTC | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC |
184+
| ParseLocal | time.Local = nil | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC |
185+
| ParseLocal | time.Local = time.UTC | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC |
186+
| 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 |
187+
| 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 |
188+
| ParseAny | time.Local = nil | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC day=6 |
189+
| ParseAny | time.Local = time.UTC | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC day=6 |
190+
+-------------+-----------------------+----------------------------------------------------+----------------------------------------------------+
191+
192+
# Force dates to be interpreted as day-first instead of month-first
193+
$ ./dateparse --prefer-day-first "28.09.2024"
194+
195+
Your Current time.Local zone is MDT
196+
197+
Layout String: dateparse.ParseFormat() => 02.01.2006
198+
199+
+-------------+-----------------------+----------------------------------------------------+----------------------------------------------------+
200+
| method | Zone Source | Parsed | Parsed: t.In(time.UTC) |
201+
+-------------+-----------------------+----------------------------------------------------+----------------------------------------------------+
202+
| ParseAny | time.Local = nil | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC day=6 |
203+
| ParseAny | time.Local = time.UTC | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC day=6 |
204+
| ParseIn | time.Local = nil | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC |
205+
| ParseIn | time.Local = time.UTC | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC |
206+
| ParseLocal | time.Local = nil | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC |
207+
| ParseLocal | time.Local = time.UTC | 2024-09-28 00:00:00 +0000 UTC | 2024-09-28 00:00:00 +0000 UTC |
208+
| 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 |
209+
| 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 |
210+
+-------------+-----------------------+----------------------------------------------------+----------------------------------------------------+
211+
172212
```

dateparse/main.go

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,27 @@ import (
1111
)
1212

1313
var (
14-
timezone = ""
15-
datestr = ""
14+
timezone = ""
15+
datestr = ""
16+
retryAmbiguousDateWithSwap = false
17+
preferDayFirst = false
18+
parserOptions = []dateparse.ParserOption{}
1619
)
1720

21+
func buildParserOptions() {
22+
parserOptions = []dateparse.ParserOption{}
23+
if retryAmbiguousDateWithSwap {
24+
parserOptions = append(parserOptions, dateparse.RetryAmbiguousDateWithSwap(true))
25+
}
26+
if preferDayFirst {
27+
parserOptions = append(parserOptions, dateparse.PreferMonthFirst(false))
28+
}
29+
}
30+
1831
func main() {
1932
flag.StringVar(&timezone, "timezone", "", "Timezone aka `America/Los_Angeles` formatted time-zone")
33+
flag.BoolVar(&retryAmbiguousDateWithSwap, "retry-ambiguous", false, "Retry ambiguous date/time formats (day-first vs month-first)")
34+
flag.BoolVar(&preferDayFirst, "prefer-day-first", false, "Prefer day-first date format")
2035
flag.Parse()
2136

2237
if len(flag.Args()) == 0 {
@@ -25,13 +40,17 @@ func main() {
2540
./dateparse "2009-08-12T22:15:09.99Z"
2641
2742
./dateparse --timezone="America/Denver" "2017-07-19 03:21:51+00:00"
43+
./dateparse --prefer-day-first "28.09.2024"
44+
./dateparse --retry-ambiguous "28.09.2024"
2845
`)
2946
return
3047
}
3148

49+
buildParserOptions()
50+
3251
datestr = flag.Args()[0]
3352

34-
layout, err := dateparse.ParseFormat(datestr)
53+
layout, err := dateparse.ParseFormat(datestr, parserOptions...)
3554
if err != nil {
3655
fatal(err)
3756
}
@@ -82,7 +101,7 @@ type parser func(datestr string, loc *time.Location, utc bool) string
82101

83102
func parseLocal(datestr string, loc *time.Location, utc bool) string {
84103
time.Local = loc
85-
t, err := dateparse.ParseLocal(datestr)
104+
t, err := dateparse.ParseLocal(datestr, parserOptions...)
86105
if err != nil {
87106
return err.Error()
88107
}
@@ -93,7 +112,7 @@ func parseLocal(datestr string, loc *time.Location, utc bool) string {
93112
}
94113

95114
func parseIn(datestr string, loc *time.Location, utc bool) string {
96-
t, err := dateparse.ParseIn(datestr, loc)
115+
t, err := dateparse.ParseIn(datestr, loc, parserOptions...)
97116
if err != nil {
98117
return err.Error()
99118
}
@@ -104,7 +123,7 @@ func parseIn(datestr string, loc *time.Location, utc bool) string {
104123
}
105124

106125
func parseAny(datestr string, loc *time.Location, utc bool) string {
107-
t, err := dateparse.ParseAny(datestr)
126+
t, err := dateparse.ParseAny(datestr, parserOptions...)
108127
if err != nil {
109128
return err.Error()
110129
}
@@ -115,7 +134,7 @@ func parseAny(datestr string, loc *time.Location, utc bool) string {
115134
}
116135

117136
func parseStrict(datestr string, loc *time.Location, utc bool) string {
118-
t, err := dateparse.ParseStrict(datestr)
137+
t, err := dateparse.ParseStrict(datestr, parserOptions...)
119138
if err != nil {
120139
return err.Error()
121140
}

0 commit comments

Comments
 (0)