Added option retryAmbiguousDateWithSwap

Original retry logic by KamalGalrani
Adapted into a deferred function at the source enabled by an option, by me
This commit is contained in:
troyspencer 2019-08-07 22:47:05 -05:00
parent ae62f1889d
commit 1bdd6d3fc9

View File

@ -209,9 +209,25 @@ func ParseStrict(datestr string, opts ...ParserOption) (time.Time, error) {
return p.parse() return p.parse()
} }
func parseTime(datestr string, loc *time.Location, opts ...ParserOption) (*parser, error) { func parseTime(datestr string, loc *time.Location, opts ...ParserOption) (p *parser, err error) {
p = newParser(datestr, loc, opts...)
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
// by retrying in this case, we can fix a common situation with no assumptions
defer func() {
if err != nil && strings.Contains(err.Error(), "month out of range") {
// create the option to reverse the preference
preferMonthFirst := PreferMonthFirst(!p.preferMonthFirst)
// turn off the retry to avoid endless recursion
retryAmbiguousDateWithSwap := RetryAmbiguousDateWithSwap(false)
modifiedOpts := append(opts, preferMonthFirst, retryAmbiguousDateWithSwap)
p, err = parseTime(datestr, time.Local, modifiedOpts...)
}
}()
}
p := newParser(datestr, loc, opts...)
i := 0 i := 0
// General strategy is to read rune by rune through the date looking for // General strategy is to read rune by rune through the date looking for
@ -1681,6 +1697,7 @@ iterRunes:
type parser struct { type parser struct {
loc *time.Location loc *time.Location
preferMonthFirst bool preferMonthFirst bool
retryAmbiguousDateWithSwap bool
ambiguousMD bool ambiguousMD bool
stateDate dateState stateDate dateState
stateTime timeState stateTime timeState
@ -1721,6 +1738,14 @@ func PreferMonthFirst(preferMonthFirst bool) ParserOption {
} }
} }
// RetryAmbiguousDateWithSwap is an option that allows retryAmbiguousDateWithSwap to be changed from its default
func RetryAmbiguousDateWithSwap(retryAmbiguousDateWithSwap bool) ParserOption {
return func(p *parser) error {
p.retryAmbiguousDateWithSwap = retryAmbiguousDateWithSwap
return nil
}
}
func newParser(dateStr string, loc *time.Location, opts ...ParserOption) *parser { func newParser(dateStr string, loc *time.Location, opts ...ParserOption) *parser {
p := &parser{ p := &parser{
stateDate: dateStart, stateDate: dateStart,
@ -1728,6 +1753,7 @@ func newParser(dateStr string, loc *time.Location, opts ...ParserOption) *parser
datestr: dateStr, datestr: dateStr,
loc: loc, loc: loc,
preferMonthFirst: true, preferMonthFirst: true,
retryAmbiguousDateWithSwap: false,
} }
p.format = []byte(dateStr) p.format = []byte(dateStr)