From 3ebc8bc635b94e4fae022e27b7e349b70cf8a659 Mon Sep 17 00:00:00 2001 From: Klondike Dragon Date: Mon, 11 Dec 2023 23:46:44 -0700 Subject: [PATCH] Incorporate fix for dd.mm.yyyy format Incorporates PR https://github.com/araddon/dateparse/pull/133 from https://github.com/mehanizm to fix https://github.com/araddon/dateparse/issues/129 Adds test cases to verify the following are already fixed: * https://github.com/araddon/dateparse/issues/105 --- parseany.go | 50 +++++++++++++++++++++++++++++++++--------------- parseany_test.go | 33 ++++++++++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 17 deletions(-) diff --git a/parseany.go b/parseany.go index 700ffdf..52f5e1a 100644 --- a/parseany.go +++ b/parseany.go @@ -396,12 +396,24 @@ iterRunes: } } else { p.ambiguousMD = true - p.moi = 0 - p.molen = i - if !p.setMonth() { - return p, unknownErr(datestr) + if p.preferMonthFirst { + if p.molen == 0 { + // 03.31.2005 + p.molen = i + if !p.setMonth() { + return p, unknownErr(datestr) + } + p.dayi = i + 1 + } + } else { + if p.daylen == 0 { + p.daylen = i + if !p.setDay() { + return p, unknownErr(datestr) + } + p.moi = i + 1 + } } - p.dayi = i + 1 } case ' ': @@ -799,9 +811,17 @@ iterRunes: return p, unknownErr(datestr) } p.stateDate = dateDigitDotDot + } else if p.dayi == 0 && p.yearlen == 0 { + // 23.07.2002 + p.molen = i - p.moi + p.yeari = i + 1 + if !p.setMonth() { + return p, unknownErr(datestr) + } + p.stateDate = dateDigitDotDot } else { // 2018.09.30 - //p.molen = 2 + // p.molen = 2 p.molen = i - p.moi p.dayi = i + 1 if !p.setMonth() { @@ -2267,20 +2287,20 @@ func (p *parser) coalesceTime(end int) { } } func (p *parser) setFullMonth(month string) { - oldLen := len(p.format) - const fullMonth = "January" + oldLen := len(p.format) + const fullMonth = "January" p.format = []byte(fmt.Sprintf("%s%s%s", p.format[0:p.moi], fullMonth, p.format[p.moi+len(month):])) - newLen := len(p.format) + newLen := len(p.format) if newLen > oldLen && p.formatSetLen >= p.moi { - p.formatSetLen += newLen - oldLen + p.formatSetLen += newLen - oldLen } else if newLen < oldLen && p.formatSetLen >= p.moi { p.formatSetLen -= oldLen - newLen - } + } - if p.formatSetLen > len(p.format) { - p.formatSetLen = len(p.format) - } else if p.formatSetLen < len(fullMonth) { - p.formatSetLen = len(fullMonth) + if p.formatSetLen > len(p.format) { + p.formatSetLen = len(p.format) + } else if p.formatSetLen < len(fullMonth) { + p.formatSetLen = len(fullMonth) } else if p.formatSetLen < 0 { p.formatSetLen = 0 } diff --git a/parseany_test.go b/parseany_test.go index 4989161..c45a5ee 100644 --- a/parseany_test.go +++ b/parseany_test.go @@ -17,6 +17,8 @@ func TestOne(t *testing.T) { type dateTest struct { in, out, loc, zname string err bool + preferDayFirst bool + retryAmbiguous bool } var testInputs = []dateTest{ @@ -525,6 +527,32 @@ var testInputs = []dateTest{ {in: "03.31.2014", out: "2014-03-31 00:00:00 +0000 UTC"}, // mm.dd.yy {in: "08.21.71", out: "1971-08-21 00:00:00 +0000 UTC"}, + // dd.mm.yyyy (see https://github.com/araddon/dateparse/issues/129 and https://github.com/araddon/dateparse/issues/28 and https://github.com/araddon/dateparse/pull/133) + {in: "23.07.1938", out: "1938-07-23 00:00:00 +0000 UTC", retryAmbiguous: true}, + {in: "23.07.1938", out: "1938-07-23 00:00:00 +0000 UTC", preferDayFirst: true}, + {in: "23/07/1938", out: "1938-07-23 00:00:00 +0000 UTC", retryAmbiguous: true}, + {in: "23/07/1938", out: "1938-07-23 00:00:00 +0000 UTC", preferDayFirst: true}, + {in: "31/3/2014", out: "2014-03-31 00:00:00 +0000 UTC", retryAmbiguous: true}, + {in: "31/3/2014", out: "2014-03-31 00:00:00 +0000 UTC", preferDayFirst: true}, + {in: "31/03/2014", out: "2014-03-31 00:00:00 +0000 UTC", retryAmbiguous: true}, + {in: "31/03/2014", out: "2014-03-31 00:00:00 +0000 UTC", preferDayFirst: true}, + {in: "21/08/71", out: "1971-08-21 00:00:00 +0000 UTC", retryAmbiguous: true}, + {in: "21/08/71", out: "1971-08-21 00:00:00 +0000 UTC", preferDayFirst: true}, + {in: "1/8/71", out: "1971-01-08 00:00:00 +0000 UTC", preferDayFirst: false}, + {in: "1/8/71", out: "1971-08-01 00:00:00 +0000 UTC", preferDayFirst: true}, + {in: "8/4/2014 22:05", out: "2014-08-04 22:05:00 +0000 UTC", preferDayFirst: false}, + {in: "8/4/2014 22:05", out: "2014-04-08 22:05:00 +0000 UTC", preferDayFirst: true}, + {in: "08/04/2014 22:05", out: "2014-08-04 22:05:00 +0000 UTC", preferDayFirst: false}, + {in: "08/04/2014 22:05", out: "2014-04-08 22:05:00 +0000 UTC", preferDayFirst: true}, + {in: "2/04/2014 03:00:51", out: "2014-02-04 03:00:51 +0000 UTC", preferDayFirst: false}, + {in: "2/04/2014 03:00:51", out: "2014-04-02 03:00:51 +0000 UTC", preferDayFirst: true}, + {in: "19/03/2012 10:11:59", out: "2012-03-19 10:11:59 +0000 UTC", retryAmbiguous: true}, + {in: "19/03/2012 10:11:59", out: "2012-03-19 10:11:59 +0000 UTC", preferDayFirst: true}, + {in: "19/03/2012 10:11:59.3186369", out: "2012-03-19 10:11:59.3186369 +0000 UTC", retryAmbiguous: true}, + {in: "19/03/2012 10:11:59.3186369", out: "2012-03-19 10:11:59.3186369 +0000 UTC", preferDayFirst: true}, + // https://github.com/araddon/dateparse/issues/105 + {in: "20/5/2006 19:51:45", out: "2006-05-20 19:51:45 +0000 UTC", retryAmbiguous: true}, + {in: "20/5/2006 19:51:45", out: "2006-05-20 19:51:45 +0000 UTC", preferDayFirst: true}, // yyyymmdd and similar {in: "2014", out: "2014-01-01 00:00:00 +0000 UTC"}, {in: "20140601", out: "2014-06-01 00:00:00 +0000 UTC"}, @@ -573,12 +601,13 @@ func TestParse(t *testing.T) { t.Fatalf("error: %s", r) } }() + parserOptions := []ParserOption{PreferMonthFirst(!th.preferDayFirst), RetryAmbiguousDateWithSwap(th.retryAmbiguous)} 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) + ts, err = ParseIn(th.in, loc, parserOptions...) if err != nil { t.Fatalf("expected to parse %q but got %v", th.in, err) } @@ -592,7 +621,7 @@ func TestParse(t *testing.T) { assert.Equal(t, th.zname, gotZone, "Expected zname %q but got %q from %q", th.zname, gotZone, th.in) } } else { - ts = MustParse(th.in) + ts = MustParse(th.in, parserOptions...) 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 {