exposes monthfirst

This commit is contained in:
Kamal Galrani 2019-07-09 19:25:50 +05:30
parent 0fb0a474d1
commit 23d378dd18
3 changed files with 115 additions and 56 deletions

View File

@ -37,7 +37,7 @@ func BenchmarkParseAny(b *testing.B) {
b.ReportAllocs() b.ReportAllocs()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
for _, dateStr := range testDates { for _, dateStr := range testDates {
ParseAny(dateStr) ParseAny(dateStr, true)
} }
} }
} }

View File

@ -120,12 +120,24 @@ func unknownErr(datestr string) error {
// ParseAny parse an unknown date format, detect the layout. // ParseAny parse an unknown date format, detect the layout.
// Normal parse. Equivalent Timezone rules as time.Parse(). // Normal parse. Equivalent Timezone rules as time.Parse().
// NOTE: please see readme on mmdd vs ddmm ambiguous dates. // NOTE: please see readme on mmdd vs ddmm ambiguous dates.
func ParseAny(datestr string) (time.Time, error) { func ParseAny(datestr string, preferMonthFirst bool) (time.Time, error) {
p, err := parseTime(datestr, nil) p, err := parseTime(datestr, nil, preferMonthFirst)
if err != nil { if err != nil {
return time.Time{}, err return time.Time{}, err
} }
return p.parse()
t, err := p.parse()
if err != nil && strings.Contains(err.Error(), "month out of range") {
p, err = parseTime(datestr, nil, !preferMonthFirst)
if err != nil {
return time.Time{}, err
}
t, err = p.parse()
}
return t, err
} }
// ParseIn with Location, equivalent to time.ParseInLocation() timezone/offset // ParseIn with Location, equivalent to time.ParseInLocation() timezone/offset
@ -133,12 +145,24 @@ func ParseAny(datestr string) (time.Time, error) {
// datestring, it uses the given location rules for any zone interpretation. // datestring, it uses the given location rules for any zone interpretation.
// That is, MST means one thing when using America/Denver and something else // That is, MST means one thing when using America/Denver and something else
// in other locations. // in other locations.
func ParseIn(datestr string, loc *time.Location) (time.Time, error) { func ParseIn(datestr string, loc *time.Location, preferMonthFirst bool) (time.Time, error) {
p, err := parseTime(datestr, loc) p, err := parseTime(datestr, loc, preferMonthFirst)
if err != nil { if err != nil {
return time.Time{}, err return time.Time{}, err
} }
return p.parse()
t, err := p.parse()
if err != nil && strings.Contains(err.Error(), "month out of range") {
p, err = parseTime(datestr, loc, !preferMonthFirst)
if err != nil {
return time.Time{}, err
}
t, err = p.parse()
}
return t, err
} }
// ParseLocal Given an unknown date format, detect the layout, // ParseLocal Given an unknown date format, detect the layout,
@ -156,20 +180,31 @@ func ParseIn(datestr string, loc *time.Location) (time.Time, error) {
// //
// t, err := dateparse.ParseIn("3/1/2014", denverLoc) // t, err := dateparse.ParseIn("3/1/2014", denverLoc)
// //
func ParseLocal(datestr string) (time.Time, error) { func ParseLocal(datestr string, preferMonthFirst bool) (time.Time, error) {
p, err := parseTime(datestr, time.Local) p, err := parseTime(datestr, time.Local, preferMonthFirst)
if err != nil { if err != nil {
return time.Time{}, err return time.Time{}, err
} }
return p.parse()
t, err := p.parse()
if err != nil && strings.Contains(err.Error(), "month out of range") {
p, err = parseTime(datestr, time.Local, !preferMonthFirst)
if err != nil {
return time.Time{}, err
}
t, err = p.parse()
}
return t, err
} }
// MustParse parse a date, and panic if it can't be parsed. Used for testing. // MustParse parse a date, and panic if it can't be parsed. Used for testing.
// Not recommended for most use-cases. // Not recommended for most use-cases.
func MustParse(datestr string) time.Time { func MustParse(datestr string, preferMonthFirst bool) time.Time {
p, err := parseTime(datestr, nil) p, err := parseTime(datestr, nil, preferMonthFirst)
if err != nil { if err != nil {
panic(err.Error())
} }
t, err := p.parse() t, err := p.parse()
if err != nil { if err != nil {
@ -184,8 +219,15 @@ func MustParse(datestr string) time.Time {
// layout, err := dateparse.ParseFormat("2013-02-01 00:00:00") // layout, err := dateparse.ParseFormat("2013-02-01 00:00:00")
// // layout = "2006-01-02 15:04:05" // // layout = "2006-01-02 15:04:05"
// //
func ParseFormat(datestr string) (string, error) { func ParseFormat(datestr string, preferMonthFirst bool) (string, error) {
p, err := parseTime(datestr, nil) p, err := parseTime(datestr, nil, preferMonthFirst)
if err != nil {
return "", err
}
_, err = p.parse()
if err != nil {
if strings.Contains(err.Error(), "month out of range") {
p, err := parseTime(datestr, nil, !preferMonthFirst)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -194,12 +236,17 @@ func ParseFormat(datestr string) (string, error) {
return "", err return "", err
} }
return string(p.format), nil return string(p.format), nil
} else {
return "", err
}
}
return string(p.format), nil
} }
// ParseStrict parse an unknown date format. IF the date is ambigous // ParseStrict parse an unknown date format. IF the date is ambigous
// mm/dd vs dd/mm then return an error. These return errors: 3.3.2014 , 8/8/71 etc // mm/dd vs dd/mm then return an error. These return errors: 3.3.2014 , 8/8/71 etc
func ParseStrict(datestr string) (time.Time, error) { func ParseStrict(datestr string, preferMonthFirst bool) (time.Time, error) {
p, err := parseTime(datestr, nil) p, err := parseTime(datestr, nil, preferMonthFirst)
if err != nil { if err != nil {
return time.Time{}, err return time.Time{}, err
} }
@ -209,9 +256,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, preferMonthFirst bool) (*parser, error) {
p := newParser(datestr, loc) p := newParser(datestr, loc, preferMonthFirst)
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
@ -269,6 +316,12 @@ iterRunes:
p.setMonth() p.setMonth()
p.dayi = i + 1 p.dayi = i + 1
} }
} else {
if p.daylen == 0 {
p.daylen = i
p.setDay()
p.moi = i + 1
}
} }
} }
@ -446,6 +499,12 @@ iterRunes:
p.setDay() p.setDay()
p.yeari = i + 1 p.yeari = i + 1
} }
} else {
if p.molen == 0 {
p.molen = i - p.moi
p.setMonth()
p.yeari = i + 1
}
} }
} }
@ -618,7 +677,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, preferMonthFirst)
} else { } else {
return nil, unknownErr(datestr) return nil, unknownErr(datestr)
} }
@ -783,25 +842,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, preferMonthFirst)
} }
} }
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, preferMonthFirst)
} }
} }
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, preferMonthFirst)
} }
} }
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, preferMonthFirst)
} }
} }
} }
@ -975,7 +1034,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, preferMonthFirst)
case '-', '+': case '-', '+':
// 03:21:51+00:00 // 03:21:51+00:00
p.stateTime = timeOffset p.stateTime = timeOffset
@ -1699,13 +1758,13 @@ type parser struct {
t *time.Time t *time.Time
} }
func newParser(dateStr string, loc *time.Location) *parser { func newParser(dateStr string, loc *time.Location, preferMonthFirst bool) *parser {
p := parser{ p := parser{
stateDate: dateStart, stateDate: dateStart,
stateTime: timeIgnore, stateTime: timeIgnore,
datestr: dateStr, datestr: dateStr,
loc: loc, loc: loc,
preferMonthFirst: true, preferMonthFirst: preferMonthFirst,
} }
p.format = []byte(dateStr) p.format = []byte(dateStr)
return &p return &p

View File

@ -11,7 +11,7 @@ import (
func TestOne(t *testing.T) { func TestOne(t *testing.T) {
time.Local = time.UTC time.Local = time.UTC
var ts time.Time var ts time.Time
ts = MustParse("2018.09.30") ts = MustParse("2018.09.30", true)
assert.Equal(t, "2018-09-30 00:00:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) assert.Equal(t, "2018-09-30 00:00:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
} }
@ -386,13 +386,13 @@ func TestParse(t *testing.T) {
time.Local = time.UTC time.Local = time.UTC
zeroTime := time.Time{}.Unix() zeroTime := time.Time{}.Unix()
ts, err := ParseAny("INVALID") ts, err := ParseAny("INVALID", true)
assert.Equal(t, zeroTime, ts.Unix()) assert.Equal(t, zeroTime, ts.Unix())
assert.NotEqual(t, nil, err) assert.NotEqual(t, nil, err)
assert.Equal(t, true, testDidPanic("NOT GONNA HAPPEN")) assert.Equal(t, true, testDidPanic("NOT GONNA HAPPEN"))
// https://github.com/golang/go/issues/5294 // https://github.com/golang/go/issues/5294
_, err = ParseAny(time.RFC3339) _, err = ParseAny(time.RFC3339, true)
assert.NotEqual(t, nil, err) assert.NotEqual(t, nil, err)
for _, th := range testInputs { for _, th := range testInputs {
@ -401,7 +401,7 @@ func TestParse(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Expected to load location %q but got %v", th.loc, err) 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, true)
if err != nil { if err != nil {
t.Fatalf("expected to parse %q but got %v", th.in, err) t.Fatalf("expected to parse %q but got %v", th.in, err)
} }
@ -411,7 +411,7 @@ func TestParse(t *testing.T) {
panic("whoops") panic("whoops")
} }
} else { } else {
ts = MustParse(th.in) ts = MustParse(th.in, true)
got := fmt.Sprintf("%v", ts.In(time.UTC)) 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) assert.Equal(t, th.out, got, "Expected %q but got %q from %q", th.out, got, th.in)
if th.out != got { if th.out != got {
@ -424,13 +424,13 @@ func TestParse(t *testing.T) {
assert.Equal(t, true, testDidPanic(`{"ts":"now"}`)) assert.Equal(t, true, testDidPanic(`{"ts":"now"}`))
_, err = ParseAny("138421636711122233311111") // too many digits _, err = ParseAny("138421636711122233311111", true) // too many digits
assert.NotEqual(t, nil, err) assert.NotEqual(t, nil, err)
_, err = ParseAny("-1314") _, err = ParseAny("-1314", true)
assert.NotEqual(t, nil, err) assert.NotEqual(t, nil, err)
_, err = ParseAny("2014-13-13 08:20:13,787") // month 13 doesn't exist so error _, err = ParseAny("2014-13-13 08:20:13,787", true) // month 13 doesn't exist so error
assert.NotEqual(t, nil, err) assert.NotEqual(t, nil, err)
} }
@ -440,7 +440,7 @@ func testDidPanic(datestr string) (paniced bool) {
paniced = true paniced = true
} }
}() }()
MustParse(datestr) MustParse(datestr, true)
return false return false
} }
@ -449,7 +449,7 @@ func TestPStruct(t *testing.T) {
denverLoc, err := time.LoadLocation("America/Denver") denverLoc, err := time.LoadLocation("America/Denver")
assert.Equal(t, nil, err) assert.Equal(t, nil, err)
p := newParser("08.21.71", denverLoc) p := newParser("08.21.71", denverLoc, true)
p.setMonth() p.setMonth()
assert.Equal(t, 0, p.moi) assert.Equal(t, 0, p.moi)
@ -479,7 +479,7 @@ var testParseErrors = []dateTest{
func TestParseErrors(t *testing.T) { func TestParseErrors(t *testing.T) {
for _, th := range testParseErrors { for _, th := range testParseErrors {
v, err := ParseAny(th.in) v, err := ParseAny(th.in, true)
assert.NotEqual(t, nil, err, "%v for %v", v, th.in) assert.NotEqual(t, nil, err, "%v for %v", v, th.in)
} }
} }
@ -514,7 +514,7 @@ var testParseFormat = []dateTest{
func TestParseLayout(t *testing.T) { func TestParseLayout(t *testing.T) {
for _, th := range testParseFormat { for _, th := range testParseFormat {
l, err := ParseFormat(th.in) l, err := ParseFormat(th.in, true)
if th.err { if th.err {
assert.NotEqual(t, nil, err) assert.NotEqual(t, nil, err)
} else { } else {
@ -544,14 +544,14 @@ var testParseStrict = []dateTest{
func TestParseStrict(t *testing.T) { func TestParseStrict(t *testing.T) {
for _, th := range testParseStrict { for _, th := range testParseStrict {
_, err := ParseStrict(th.in) _, err := ParseStrict(th.in, true)
assert.NotEqual(t, nil, err) assert.NotEqual(t, nil, err)
} }
_, err := ParseStrict(`{"hello"}`) _, err := ParseStrict(`{"hello"}`, true)
assert.NotEqual(t, nil, err) assert.NotEqual(t, nil, err)
_, err = ParseStrict("2009-08-12T22:15Z") _, err = ParseStrict("2009-08-12T22:15Z", true)
assert.Equal(t, nil, err) assert.Equal(t, nil, err)
} }
@ -570,7 +570,7 @@ func TestInLocation(t *testing.T) {
time.Local = time.UTC time.Local = time.UTC
// Just normal parse to test out zone/offset // Just normal parse to test out zone/offset
ts := MustParse("2013-02-01 00:00:00") ts := MustParse("2013-02-01 00:00:00", true)
zone, offset := ts.Zone() zone, offset := ts.Zone()
assert.Equal(t, 0, offset, "Should have found offset = 0 %v", offset) assert.Equal(t, 0, offset, "Should have found offset = 0 %v", offset)
assert.Equal(t, "UTC", zone, "Should have found zone = UTC %v", zone) assert.Equal(t, "UTC", zone, "Should have found zone = UTC %v", zone)
@ -579,26 +579,26 @@ func TestInLocation(t *testing.T) {
// Now lets set to denver (MST/MDT) and re-parse the same time string // Now lets set to denver (MST/MDT) and re-parse the same time string
// and since no timezone info in string, we expect same result // and since no timezone info in string, we expect same result
time.Local = denverLoc time.Local = denverLoc
ts = MustParse("2013-02-01 00:00:00") ts = MustParse("2013-02-01 00:00:00", true)
zone, offset = ts.Zone() zone, offset = ts.Zone()
assert.Equal(t, 0, offset, "Should have found offset = 0 %v", offset) assert.Equal(t, 0, offset, "Should have found offset = 0 %v", offset)
assert.Equal(t, "UTC", zone, "Should have found zone = UTC %v", zone) assert.Equal(t, "UTC", zone, "Should have found zone = UTC %v", zone)
assert.Equal(t, "2013-02-01 00:00:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) assert.Equal(t, "2013-02-01 00:00:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
ts = MustParse("Tue, 5 Jul 2017 16:28:13 -0700 (MST)") ts = MustParse("Tue, 5 Jul 2017 16:28:13 -0700 (MST)", true)
assert.Equal(t, "2017-07-05 23:28:13 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) assert.Equal(t, "2017-07-05 23:28:13 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
// Now we are going to use ParseIn() and see that it gives different answer // Now we are going to use ParseIn() and see that it gives different answer
// with different zone, offset // with different zone, offset
time.Local = nil time.Local = nil
ts, err = ParseIn("2013-02-01 00:00:00", denverLoc) ts, err = ParseIn("2013-02-01 00:00:00", denverLoc, true)
assert.Equal(t, nil, err) assert.Equal(t, nil, err)
zone, offset = ts.Zone() zone, offset = ts.Zone()
assert.Equal(t, -25200, offset, "Should have found offset = -25200 %v %v", offset, denverLoc) assert.Equal(t, -25200, offset, "Should have found offset = -25200 %v %v", offset, denverLoc)
assert.Equal(t, "MST", zone, "Should have found zone = MST %v", zone) assert.Equal(t, "MST", zone, "Should have found zone = MST %v", zone)
assert.Equal(t, "2013-02-01 07:00:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) assert.Equal(t, "2013-02-01 07:00:00 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
ts, err = ParseIn("18 January 2018", denverLoc) ts, err = ParseIn("18 January 2018", denverLoc, true)
assert.Equal(t, nil, err) assert.Equal(t, nil, err)
zone, offset = ts.Zone() zone, offset = ts.Zone()
assert.Equal(t, -25200, offset, "Should have found offset = 0 %v", offset) assert.Equal(t, -25200, offset, "Should have found offset = 0 %v", offset)
@ -608,7 +608,7 @@ func TestInLocation(t *testing.T) {
// Now we are going to use ParseLocal() and see that it gives same // Now we are going to use ParseLocal() and see that it gives same
// answer as ParseIn when we have time.Local set to a location // answer as ParseIn when we have time.Local set to a location
time.Local = denverLoc time.Local = denverLoc
ts, err = ParseLocal("2013-02-01 00:00:00") ts, err = ParseLocal("2013-02-01 00:00:00", true)
assert.Equal(t, nil, err) assert.Equal(t, nil, err)
zone, offset = ts.Zone() zone, offset = ts.Zone()
assert.Equal(t, -25200, offset, "Should have found offset = -25200 %v %v", offset, denverLoc) assert.Equal(t, -25200, offset, "Should have found offset = -25200 %v %v", offset, denverLoc)
@ -617,7 +617,7 @@ func TestInLocation(t *testing.T) {
// Lets advance past daylight savings time start // Lets advance past daylight savings time start
// use parseIn and see offset/zone has changed to Daylight Savings Equivalents // use parseIn and see offset/zone has changed to Daylight Savings Equivalents
ts, err = ParseIn("2013-04-01 00:00:00", denverLoc) ts, err = ParseIn("2013-04-01 00:00:00", denverLoc, true)
assert.Equal(t, nil, err) assert.Equal(t, nil, err)
zone, offset = ts.Zone() zone, offset = ts.Zone()
assert.Equal(t, -21600, offset, "Should have found offset = -21600 %v %v", offset, denverLoc) assert.Equal(t, -21600, offset, "Should have found offset = -21600 %v %v", offset, denverLoc)
@ -628,7 +628,7 @@ func TestInLocation(t *testing.T) {
time.Local = time.UTC time.Local = time.UTC
// UnixDate = "Mon Jan _2 15:04:05 MST 2006" // UnixDate = "Mon Jan _2 15:04:05 MST 2006"
ts = MustParse("Mon Jan 2 15:04:05 MST 2006") ts = MustParse("Mon Jan 2 15:04:05 MST 2006", true)
_, offset = ts.Zone() _, offset = ts.Zone()
assert.Equal(t, 0, offset, "Should have found offset = 0 %v", offset) assert.Equal(t, 0, offset, "Should have found offset = 0 %v", offset)
@ -636,7 +636,7 @@ func TestInLocation(t *testing.T) {
// Now lets set to denver(mst/mdt) // Now lets set to denver(mst/mdt)
time.Local = denverLoc time.Local = denverLoc
ts = MustParse("Mon Jan 2 15:04:05 MST 2006") ts = MustParse("Mon Jan 2 15:04:05 MST 2006", true)
// this time is different from one above parsed with time.Local set to UTC // this time is different from one above parsed with time.Local set to UTC
_, offset = ts.Zone() _, offset = ts.Zone()
@ -647,25 +647,25 @@ func TestInLocation(t *testing.T) {
time.Local = time.UTC time.Local = time.UTC
// RFC850 = "Monday, 02-Jan-06 15:04:05 MST" // RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
ts = MustParse("Monday, 02-Jan-06 15:04:05 MST") ts = MustParse("Monday, 02-Jan-06 15:04:05 MST", true)
_, offset = ts.Zone() _, offset = ts.Zone()
assert.Equal(t, 0, offset, "Should have found offset = 0 %v", offset) assert.Equal(t, 0, offset, "Should have found offset = 0 %v", offset)
assert.Equal(t, "2006-01-02 15:04:05 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) assert.Equal(t, "2006-01-02 15:04:05 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
// Now lets set to denver // Now lets set to denver
time.Local = denverLoc time.Local = denverLoc
ts = MustParse("Monday, 02-Jan-06 15:04:05 MST") ts = MustParse("Monday, 02-Jan-06 15:04:05 MST", true)
_, offset = ts.Zone() _, offset = ts.Zone()
assert.NotEqual(t, 0, offset, "Should have found offset %v", offset) assert.NotEqual(t, 0, offset, "Should have found offset %v", offset)
assert.Equal(t, "2006-01-02 22:04:05 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC))) assert.Equal(t, "2006-01-02 22:04:05 +0000 UTC", fmt.Sprintf("%v", ts.In(time.UTC)))
// Now some errors // Now some errors
zeroTime := time.Time{}.Unix() zeroTime := time.Time{}.Unix()
ts, err = ParseIn("INVALID", denverLoc) ts, err = ParseIn("INVALID", denverLoc, true)
assert.Equal(t, zeroTime, ts.Unix()) assert.Equal(t, zeroTime, ts.Unix())
assert.NotEqual(t, nil, err) assert.NotEqual(t, nil, err)
ts, err = ParseLocal("INVALID") ts, err = ParseLocal("INVALID", true)
assert.Equal(t, zeroTime, ts.Unix()) assert.Equal(t, zeroTime, ts.Unix())
assert.NotEqual(t, nil, err) assert.NotEqual(t, nil, err)
} }