Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 94 additions & 24 deletions parseany.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ const (
dateDigitWs // 15
dateDigitWsMoYear
dateDigitWsMolong
dateDigitWsOffset
dateAlpha
dateAlphaWs
dateAlphaWsDigit // 20
dateAlphaWsDigit
dateAlphaWsDigitMore
dateAlphaWsDigitMoreWs
dateAlphaWsDigitMoreWsYear
Expand Down Expand Up @@ -89,16 +90,17 @@ const (
timeWsOffsetColonAlpha
timeWsOffsetColon
timeWsYear // 15
timeWsYearOffset
timeOffset
timeOffsetColon
timeAlpha
timePeriod
timePeriodOffset // 20
timePeriodOffset
timePeriodOffsetColon
timePeriodOffsetColonWs
timePeriodWs
timePeriodWsAlpha
timePeriodWsOffset // 25
timePeriodWsOffset
timePeriodWsOffsetWs
timePeriodWsOffsetWsAlpha
timePeriodWsOffsetColon
Expand Down Expand Up @@ -297,9 +299,15 @@ iterRunes:
// 02 Jan 2018 23:59:34
// 12 Feb 2006, 19:17
// 12 Feb 2006, 19:17:22
p.stateDate = dateDigitWs
p.dayi = 0
p.daylen = i
// 1112911993 -0700
if i <= 2 {
p.stateDate = dateDigitWs
p.dayi = 0
p.daylen = i
} else {
// Timestamp with offset, such as: 1112911993 -0700
p.stateDate = dateDigitWsOffset
}
case '年':
// Chinese Year
p.stateDate = dateDigitChineseYear
Expand Down Expand Up @@ -540,6 +548,7 @@ iterRunes:
// Mon Jan _2 15:04:05 2006
// Mon Jan _2 15:04:05 MST 2006
// Mon Jan 02 15:04:05 -0700 2006
// Mon Jan 02 15:04:05 2006 -0700
// Mon Aug 10 15:44:11 UTC+0100 2015
// Fri Jul 03 2015 18:04:07 GMT+0100 (GMT Daylight Time)
// dateAlphaWSDigit
Expand Down Expand Up @@ -629,6 +638,7 @@ iterRunes:
// Mon Jan _2 15:04:05 2006
// Mon Jan _2 15:04:05 MST 2006
// Mon Jan 02 15:04:05 -0700 2006
// Mon Jan 02 15:04:05 2006 -0700
// Fri Jul 03 2015 18:04:07 GMT+0100 (GMT Daylight Time)
// Mon Aug 10 15:44:11 UTC+0100 2015
// dateAlphaWsDigit
Expand Down Expand Up @@ -701,6 +711,7 @@ iterRunes:
case dateAlphaWsAlpha:
// Mon Jan _2 15:04:05 2006
// Mon Jan 02 15:04:05 -0700 2006
// Mon Jan 02 15:04:05 2006 -0700
// Mon Jan _2 15:04:05 MST 2006
// Mon Aug 10 15:44:11 UTC+0100 2015
// Fri Jul 03 2015 18:04:07 GMT+0100 (GMT Daylight Time)
Expand Down Expand Up @@ -1068,6 +1079,8 @@ iterRunes:
// 00:12:00 +00:00 UTC
// timeWsYear
// 00:12:00 2008
// timeWsYearOffset
// 00:12:00 2008 +0800
// timeZ
// 15:04:05.99Z
switch r {
Expand All @@ -1093,6 +1106,17 @@ iterRunes:
p.yeari = i
}
}
case timeWsYear:
// timeWsYearOffset
// 00:12:00 2008 +0800
switch r {
case ' ':
p.yearlen = i - p.yeari
p.setYear()
case '+', '-':
p.offseti = i
p.stateTime = timeWsYearOffset
}
case timeWsAlpha:
// 06:20:00 UTC
// 06:20:00 UTC-05
Expand Down Expand Up @@ -1441,6 +1465,8 @@ iterRunes:
p.set(p.offseti, "-0700")
case timeWsOffset:
p.set(p.offseti, "-0700")
case timeWsYearOffset:
p.set(p.offseti, "-0700")
case timeWsOffsetWs:
// 17:57:51 -0700 2009
// 00:12:00 +0000 UTC
Expand Down Expand Up @@ -1470,7 +1496,7 @@ iterRunes:
}

switch p.stateDate {
case dateDigit:
case dateDigit, dateDigitWsOffset:
// unixy timestamps ish
// example ct type
// 1499979655583057426 19 nanoseconds
Expand All @@ -1480,44 +1506,88 @@ iterRunes:
// 1332151919 10 seconds
// 20140601 8 yyyymmdd
// 2014 4 yyyy
// 1112911993 +0000
t := time.Time{}
if len(datestr) == len("1499979655583057426") { // 19
dateItems := strings.Split(datestr, " ")
if len(dateItems[0]) == len("1499979655583057426") { // 19
// nano-seconds
if nanoSecs, err := strconv.ParseInt(datestr, 10, 64); err == nil {
if nanoSecs, err := strconv.ParseInt(dateItems[0], 10, 64); err == nil {
t = time.Unix(0, nanoSecs)
}
} else if len(datestr) == len("1499979795437000") { // 16
} else if len(dateItems[0]) == len("1499979795437000") { // 16
// micro-seconds
if microSecs, err := strconv.ParseInt(datestr, 10, 64); err == nil {
if microSecs, err := strconv.ParseInt(dateItems[0], 10, 64); err == nil {
t = time.Unix(0, microSecs*1000)
}
} else if len(datestr) == len("yyyyMMddhhmmss") { // 14
} else if len(dateItems[0]) == len("yyyyMMddhhmmss") { // 14
// yyyyMMddhhmmss
p.format = []byte("20060102150405")
return p, nil
} else if len(datestr) == len("1332151919000") { // 13
if miliSecs, err := strconv.ParseInt(datestr, 10, 64); err == nil {
} else if len(dateItems[0]) == len("1332151919000") { // 13
if miliSecs, err := strconv.ParseInt(dateItems[0], 10, 64); err == nil {
t = time.Unix(0, miliSecs*1000*1000)
}
} else if len(datestr) == len("1332151919") { //10
if secs, err := strconv.ParseInt(datestr, 10, 64); err == nil {
} else if len(dateItems[0]) == len("1332151919") { //10
if secs, err := strconv.ParseInt(dateItems[0], 10, 64); err == nil {
t = time.Unix(secs, 0)
}
} else if len(datestr) == len("20140601") {
} else if len(dateItems[0]) == len("20140601") {
p.format = []byte("20060102")
return p, nil
} else if len(datestr) == len("2014") {
} else if len(dateItems[0]) == len("2014") {
p.format = []byte("2006")
return p, nil
} else if len(datestr) < 4 {
return nil, fmt.Errorf("unrecognized format, too short %v", datestr)
} else if len(dateItems[0]) < 4 {
return nil, fmt.Errorf("unrecognized format, too short %v", dateItems[0])
}
if !t.IsZero() {
if loc == nil {
p.t = &t
return p, nil
if loc == nil &&
len(dateItems) == 2 &&
len(dateItems[1]) > 0 &&
(dateItems[1][0] == '-' || dateItems[1][0] == '+') {
var (
h, m int64
err error
tzName string
)
tzName = "UTC" + string(dateItems[1][0])
switch len(dateItems[1]) - 1 {
case 2:
h, err = strconv.ParseInt(dateItems[1][1:3], 10, 64)
case 4:
if h, err = strconv.ParseInt(dateItems[1][1:3], 10, 64); err == nil {
m, err = strconv.ParseInt(dateItems[1][3:5], 10, 64)
}
case 5:
if dateItems[1][3] == ':' {
if h, err = strconv.ParseInt(dateItems[1][1:3], 10, 64); err == nil {
m, err = strconv.ParseInt(dateItems[1][4:6], 10, 64)
}
}
default:
err = fmt.Errorf("bad digit number")
}
if err != nil {
return nil, fmt.Errorf("bad time zone offset %s: %s", dateItems[1], err)
}
if h == 0 && m == 0 {
tzName = "UTC"
} else {
tzName = "UTC" + string(dateItems[1][0])
tzName += strconv.FormatInt(h, 10)
if m != 0 {
tzName += fmt.Sprintf(":%02d", m)
}
}
sec := int(h*3600 + m*60)
if dateItems[1][0] == '-' {
sec = -1 * sec
}
loc = time.FixedZone(tzName, sec)
}
if loc != nil {
t = t.In(loc)
}
t = t.In(loc)
p.t = &t
return p, nil
}
Expand Down
10 changes: 10 additions & 0 deletions parseany_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,16 @@ var testInputs = []dateTest{
{in: "1384216367111", out: "2013-11-12 00:32:47.111 +0000 UTC"},
{in: "1384216367111222", out: "2013-11-12 00:32:47.111222 +0000 UTC"},
{in: "1384216367111222333", out: "2013-11-12 00:32:47.111222333 +0000 UTC"},

// all digits (unix secs, ms etc) with offset
{in: "1112911993 -0700", out: "2005-04-07 22:13:13 +0000 UTC"},
{in: "1112911993 +0800", out: "2005-04-07 22:13:13 +0000 UTC"},
{in: "1384216367111 +0000", out: "2013-11-12 00:32:47.111 +0000 UTC"},
{in: "1384216367111222 -0000", out: "2013-11-12 00:32:47.111222 +0000 UTC"},
{in: "1384216367111222333 +0130", out: "2013-11-12 00:32:47.111222333 +0000 UTC"},

// git log default date format
{in: "Thu Apr 7 15:13:13 2005 -0700", out: "2005-04-07 22:13:13 +0000 UTC"},
}

func TestParse(t *testing.T) {
Expand Down