Create Option type, and system for loading options

Created PreferMonthFirst option, which exposes preferMonthFirst in a backwards compatible manner with optional spread functions that operate on the parser when it's being constructed
This commit is contained in:
troyspencer 2019-08-07 22:12:45 -05:00
parent d530bcec9b
commit e151913243

View File

@ -209,9 +209,9 @@ func ParseStrict(datestr string) (time.Time, error) {
return p.parse() return p.parse()
} }
func parseTime(datestr string, loc *time.Location) (*parser, error) { func parseTime(datestr string, loc *time.Location, opts ...Option) (*parser, error) {
p := newParser(datestr, loc) 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
@ -274,9 +274,9 @@ iterRunes:
p.daylen = i p.daylen = i
p.setDay() p.setDay()
p.moi = i + 1 p.moi = i + 1
}
} }
} }
}
case '.': case '.':
// 3.31.2014 // 3.31.2014
@ -457,9 +457,9 @@ iterRunes:
p.molen = i - p.moi p.molen = i - p.moi
p.setMonth() p.setMonth()
p.yeari = i + 1 p.yeari = i + 1
}
} }
} }
}
case dateDigitWs: case dateDigitWs:
// 18 January 2018 // 18 January 2018
@ -630,7 +630,7 @@ iterRunes:
} else if i == 4 { } else if i == 4 {
// gross // gross
datestr = datestr[0:i-1] + datestr[i:] datestr = datestr[0:i-1] + datestr[i:]
return parseTime(datestr, loc) return parseTime(datestr, loc, opts...)
} else { } else {
return nil, unknownErr(datestr) return nil, unknownErr(datestr)
} }
@ -795,25 +795,25 @@ iterRunes:
case 't', 'T': case 't', 'T':
if p.nextIs(i, 'h') || p.nextIs(i, 'H') { if p.nextIs(i, 'h') || p.nextIs(i, 'H') {
if len(datestr) > i+2 { if len(datestr) > i+2 {
return parseTime(fmt.Sprintf("%s%s", p.datestr[0:i], p.datestr[i+2:]), loc) return parseTime(fmt.Sprintf("%s%s", p.datestr[0:i], p.datestr[i+2:]), loc, opts...)
} }
} }
case 'n', 'N': case 'n', 'N':
if p.nextIs(i, 'd') || p.nextIs(i, 'D') { if p.nextIs(i, 'd') || p.nextIs(i, 'D') {
if len(datestr) > i+2 { if len(datestr) > i+2 {
return parseTime(fmt.Sprintf("%s%s", p.datestr[0:i], p.datestr[i+2:]), loc) return parseTime(fmt.Sprintf("%s%s", p.datestr[0:i], p.datestr[i+2:]), loc, opts...)
} }
} }
case 's', 'S': case 's', 'S':
if p.nextIs(i, 't') || p.nextIs(i, 'T') { if p.nextIs(i, 't') || p.nextIs(i, 'T') {
if len(datestr) > i+2 { if len(datestr) > i+2 {
return parseTime(fmt.Sprintf("%s%s", p.datestr[0:i], p.datestr[i+2:]), loc) return parseTime(fmt.Sprintf("%s%s", p.datestr[0:i], p.datestr[i+2:]), loc, opts...)
} }
} }
case 'r', 'R': case 'r', 'R':
if p.nextIs(i, 'd') || p.nextIs(i, 'D') { if p.nextIs(i, 'd') || p.nextIs(i, 'D') {
if len(datestr) > i+2 { if len(datestr) > i+2 {
return parseTime(fmt.Sprintf("%s%s", p.datestr[0:i], p.datestr[i+2:]), loc) return parseTime(fmt.Sprintf("%s%s", p.datestr[0:i], p.datestr[i+2:]), loc, opts...)
} }
} }
} }
@ -987,7 +987,7 @@ iterRunes:
// 2014-05-11 08:20:13,787 // 2014-05-11 08:20:13,787
ds := []byte(p.datestr) ds := []byte(p.datestr)
ds[i] = '.' ds[i] = '.'
return parseTime(string(ds), loc) return parseTime(string(ds), loc, opts...)
case '-', '+': case '-', '+':
// 03:21:51+00:00 // 03:21:51+00:00
p.stateTime = timeOffset p.stateTime = timeOffset
@ -1711,8 +1711,18 @@ type parser struct {
t *time.Time t *time.Time
} }
func newParser(dateStr string, loc *time.Location) *parser { type Option func(*parser) error
p := parser{
// PreferMonthFirst is an option that allows preferMonthFirst to be changed from its default
func PreferMonthFirst(preferMonthFirst bool) Option {
return func(p *parser) error {
p.preferMonthFirst = preferMonthFirst
return nil
}
}
func newParser(dateStr string, loc *time.Location, opts ...Option) *parser {
p := &parser{
stateDate: dateStart, stateDate: dateStart,
stateTime: timeIgnore, stateTime: timeIgnore,
datestr: dateStr, datestr: dateStr,
@ -1720,7 +1730,12 @@ func newParser(dateStr string, loc *time.Location) *parser {
preferMonthFirst: true, preferMonthFirst: true,
} }
p.format = []byte(dateStr) p.format = []byte(dateStr)
return &p
// allow the options to mutate the parser fields from their defaults
for _, option := range opts {
option(p)
}
return p
} }
func (p *parser) nextIs(i int, b byte) bool { func (p *parser) nextIs(i int, b byte) bool {