Skip to content

Commit cebc7ff

Browse files
b41shzz-jason
authored andcommitted
types: refine the parsing logic of INTERVAL to correct DATE_ADD/DATE_SUB (#9874)
1 parent ffc97a7 commit cebc7ff

File tree

3 files changed

+119
-225
lines changed

3 files changed

+119
-225
lines changed

expression/integration_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1828,11 +1828,11 @@ func (s *testIntegrationSuite) TestTimeBuiltin(c *C) {
18281828

18291829
{"\"2011-11-11\"", "\"abc1000\"", "MICROSECOND", "<nil>", "<nil>"},
18301830
{"\"20111111 10:10:10\"", "\"1\"", "DAY", "<nil>", "<nil>"},
1831-
{"\"2011-11-11\"", "\"10\"", "SECOND_MICROSECOND", "<nil>", "<nil>"},
1832-
{"\"2011-11-11\"", "\"10.0000\"", "MINUTE_MICROSECOND", "<nil>", "<nil>"},
1833-
{"\"2011-11-11\"", "\"10:10:10\"", "MINUTE_MICROSECOND", "<nil>", "<nil>"},
1831+
{"\"2011-11-11\"", "\"10\"", "SECOND_MICROSECOND", "2011-11-11 00:00:00.100000", "2011-11-10 23:59:59.900000"},
1832+
{"\"2011-11-11\"", "\"10.0000\"", "MINUTE_MICROSECOND", "2011-11-11 00:00:10", "2011-11-10 23:59:50"},
1833+
{"\"2011-11-11\"", "\"10:10:10\"", "MINUTE_MICROSECOND", "2011-11-11 00:10:10.100000", "2011-11-10 23:49:49.900000"},
18341834

1835-
{"cast(\"2011-11-11\" as datetime)", "\"10:10:10\"", "MINUTE_MICROSECOND", "<nil>", "<nil>"},
1835+
{"cast(\"2011-11-11\" as datetime)", "\"10:10:10\"", "MINUTE_MICROSECOND", "2011-11-11 00:10:10.100000", "2011-11-10 23:49:49.900000"},
18361836
{"cast(\"2011-11-11 00:00:00\" as datetime)", "1", "DAY", "2011-11-12 00:00:00", "2011-11-10 00:00:00"},
18371837
{"cast(\"2011-11-11 00:00:00\" as datetime)", "10", "HOUR", "2011-11-11 10:00:00", "2011-11-10 14:00:00"},
18381838
{"cast(\"2011-11-11 00:00:00\" as datetime)", "10", "MINUTE", "2011-11-11 00:10:00", "2011-11-10 23:50:00"},
@@ -1843,7 +1843,7 @@ func (s *testIntegrationSuite) TestTimeBuiltin(c *C) {
18431843
{"cast(\"2011-11-11 00:00:00\" as datetime)", "\"10\"", "MINUTE", "2011-11-11 00:10:00", "2011-11-10 23:50:00"},
18441844
{"cast(\"2011-11-11 00:00:00\" as datetime)", "\"10\"", "SECOND", "2011-11-11 00:00:10", "2011-11-10 23:59:50"},
18451845

1846-
{"cast(\"2011-11-11\" as date)", "\"10:10:10\"", "MINUTE_MICROSECOND", "<nil>", "<nil>"},
1846+
{"cast(\"2011-11-11\" as date)", "\"10:10:10\"", "MINUTE_MICROSECOND", "2011-11-11 00:10:10.100000", "2011-11-10 23:49:49.900000"},
18471847
{"cast(\"2011-11-11 00:00:00\" as date)", "1", "DAY", "2011-11-12", "2011-11-10"},
18481848
{"cast(\"2011-11-11 00:00:00\" as date)", "10", "HOUR", "2011-11-11 10:00:00", "2011-11-10 14:00:00"},
18491849
{"cast(\"2011-11-11 00:00:00\" as date)", "10", "MINUTE", "2011-11-11 00:10:00", "2011-11-10 23:50:00"},

types/time.go

Lines changed: 98 additions & 218 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,50 @@ const (
7979
TimeMaxValueSeconds = TimeMaxHour*3600 + TimeMaxMinute*60 + TimeMaxSecond
8080
)
8181

82+
const (
83+
// YearIndex is index of 'YEARS-MONTHS DAYS HOURS:MINUTES:SECONDS.MICROSECONDS' expr Format
84+
YearIndex = 0 + iota
85+
// MonthIndex is index of 'YEARS-MONTHS DAYS HOURS:MINUTES:SECONDS.MICROSECONDS' expr Format
86+
MonthIndex
87+
// DayIndex is index of 'YEARS-MONTHS DAYS HOURS:MINUTES:SECONDS.MICROSECONDS' expr Format
88+
DayIndex
89+
// HourIndex is index of 'YEARS-MONTHS DAYS HOURS:MINUTES:SECONDS.MICROSECONDS' expr Format
90+
HourIndex
91+
// MinuteIndex is index of 'YEARS-MONTHS DAYS HOURS:MINUTES:SECONDS.MICROSECONDS' expr Format
92+
MinuteIndex
93+
// SecondIndex is index of 'YEARS-MONTHS DAYS HOURS:MINUTES:SECONDS.MICROSECONDS' expr Format
94+
SecondIndex
95+
// MicrosecondIndex is index of 'YEARS-MONTHS DAYS HOURS:MINUTES:SECONDS.MICROSECONDS' expr Format
96+
MicrosecondIndex
97+
)
98+
99+
const (
100+
// YearMonthMaxCnt is max parameters count 'YEARS-MONTHS' expr Format allowed
101+
YearMonthMaxCnt = 2
102+
// DayHourMaxCnt is max parameters count 'DAYS HOURS' expr Format allowed
103+
DayHourMaxCnt = 2
104+
// DayMinuteMaxCnt is max parameters count 'DAYS HOURS:MINUTES' expr Format allowed
105+
DayMinuteMaxCnt = 3
106+
// DaySecondMaxCnt is max parameters count 'DAYS HOURS:MINUTES:SECONDS' expr Format allowed
107+
DaySecondMaxCnt = 4
108+
// DayMicrosecondMaxCnt is max parameters count 'DAYS HOURS:MINUTES:SECONDS.MICROSECONDS' expr Format allowed
109+
DayMicrosecondMaxCnt = 5
110+
// HourMinuteMaxCnt is max parameters count 'HOURS:MINUTES' expr Format allowed
111+
HourMinuteMaxCnt = 2
112+
// HourSecondMaxCnt is max parameters count 'HOURS:MINUTES:SECONDS' expr Format allowed
113+
HourSecondMaxCnt = 3
114+
// HourMicrosecondMaxCnt is max parameters count 'HOURS:MINUTES:SECONDS.MICROSECONDS' expr Format allowed
115+
HourMicrosecondMaxCnt = 4
116+
// MinuteSecondMaxCnt is max parameters count 'MINUTES:SECONDS' expr Format allowed
117+
MinuteSecondMaxCnt = 2
118+
// MinuteMicrosecondMaxCnt is max parameters count 'MINUTES:SECONDS.MICROSECONDS' expr Format allowed
119+
MinuteMicrosecondMaxCnt = 3
120+
// SecondMicrosecondMaxCnt is max parameters count 'SECONDS.MICROSECONDS' expr Format allowed
121+
SecondMicrosecondMaxCnt = 2
122+
// TimeValueCnt is parameters count 'YEARS-MONTHS DAYS HOURS:MINUTES:SECONDS.MICROSECONDS' expr Format
123+
TimeValueCnt = 7
124+
)
125+
82126
// Zero values for different types.
83127
var (
84128
// ZeroDuration is the zero value for Duration type.
@@ -1574,234 +1618,67 @@ func extractSingleTimeValue(unit string, format string) (int64, int64, int64, fl
15741618
return 0, 0, 0, 0, errors.Errorf("invalid singel timeunit - %s", unit)
15751619
}
15761620

1577-
// extractSecondMicrosecond extracts second and microsecond from a string and its format is `SS.FFFFFF`.
1578-
func extractSecondMicrosecond(format string) (int64, int64, int64, float64, error) {
1579-
fields := strings.Split(format, ".")
1580-
if len(fields) != 2 {
1581-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1582-
}
1583-
1584-
seconds, err := strconv.ParseFloat(fields[0], 64)
1585-
if err != nil {
1586-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1587-
}
1588-
1589-
microseconds, err := strconv.ParseFloat(alignFrac(fields[1], MaxFsp), 64)
1590-
if err != nil {
1591-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1592-
}
1593-
1594-
return 0, 0, 0, seconds*float64(gotime.Second) + microseconds*float64(gotime.Microsecond), nil
1595-
}
1596-
1597-
// extractMinuteMicrosecond extracts minutes and microsecond from a string and its format is `MM:SS.FFFFFF`.
1598-
func extractMinuteMicrosecond(format string) (int64, int64, int64, float64, error) {
1599-
fields := strings.Split(format, ":")
1600-
if len(fields) != 2 {
1601-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1602-
}
1603-
1604-
minutes, err := strconv.ParseFloat(fields[0], 64)
1605-
if err != nil {
1606-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1607-
}
1608-
1609-
_, _, _, value, err := extractSecondMicrosecond(fields[1])
1610-
if err != nil {
1611-
return 0, 0, 0, 0, errors.Trace(err)
1612-
}
1613-
1614-
return 0, 0, 0, minutes*float64(gotime.Minute) + value, nil
1615-
}
1616-
1617-
// extractMinuteSecond extracts minutes and second from a string and its format is `MM:SS`.
1618-
func extractMinuteSecond(format string) (int64, int64, int64, float64, error) {
1619-
fields := strings.Split(format, ":")
1620-
if len(fields) != 2 {
1621-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1622-
}
1623-
1624-
minutes, err := strconv.ParseFloat(fields[0], 64)
1625-
if err != nil {
1626-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1627-
}
1628-
1629-
seconds, err := strconv.ParseFloat(fields[1], 64)
1630-
if err != nil {
1631-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1632-
}
1633-
1634-
return 0, 0, 0, minutes*float64(gotime.Minute) + seconds*float64(gotime.Second), nil
1635-
}
1636-
1637-
// extractHourMicrosecond extracts hour and microsecond from a string and its format is `HH:MM:SS.FFFFFF`.
1638-
func extractHourMicrosecond(format string) (int64, int64, int64, float64, error) {
1639-
fields := strings.Split(format, ":")
1640-
if len(fields) != 3 {
1641-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1642-
}
1643-
1644-
hours, err := strconv.ParseFloat(fields[0], 64)
1645-
if err != nil {
1646-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1647-
}
1648-
1649-
minutes, err := strconv.ParseFloat(fields[1], 64)
1650-
if err != nil {
1651-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1652-
}
1653-
1654-
_, _, _, value, err := extractSecondMicrosecond(fields[2])
1655-
if err != nil {
1656-
return 0, 0, 0, 0, errors.Trace(err)
1657-
}
1658-
1659-
return 0, 0, 0, hours*float64(gotime.Hour) + minutes*float64(gotime.Minute) + value, nil
1660-
}
1661-
1662-
// extractHourSecond extracts hour and second from a string and its format is `HH:MM:SS`.
1663-
func extractHourSecond(format string) (int64, int64, int64, float64, error) {
1664-
fields := strings.Split(format, ":")
1665-
if len(fields) != 3 {
1666-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1667-
}
1668-
1669-
hours, err := strconv.ParseFloat(fields[0], 64)
1670-
if err != nil {
1671-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1672-
}
1673-
1674-
minutes, err := strconv.ParseFloat(fields[1], 64)
1675-
if err != nil {
1676-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1677-
}
1678-
1679-
seconds, err := strconv.ParseFloat(fields[2], 64)
1680-
if err != nil {
1681-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1682-
}
1683-
1684-
return 0, 0, 0, hours*float64(gotime.Hour) + minutes*float64(gotime.Minute) + seconds*float64(gotime.Second), nil
1685-
}
1686-
1687-
// extractHourMinute extracts hour and minute from a string and its format is `HH:MM`.
1688-
func extractHourMinute(format string) (int64, int64, int64, float64, error) {
1689-
fields := strings.Split(format, ":")
1690-
if len(fields) != 2 {
1691-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1692-
}
1693-
1694-
hours, err := strconv.ParseFloat(fields[0], 64)
1695-
if err != nil {
1696-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1697-
}
1698-
1699-
minutes, err := strconv.ParseFloat(fields[1], 64)
1700-
if err != nil {
1701-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1702-
}
1703-
1704-
return 0, 0, 0, hours*float64(gotime.Hour) + minutes*float64(gotime.Minute), nil
1705-
}
1706-
1707-
// extractDayMicrosecond extracts day and microsecond from a string and its format is `DD HH:MM:SS.FFFFFF`.
1708-
func extractDayMicrosecond(format string) (int64, int64, int64, float64, error) {
1709-
fields := strings.Split(format, " ")
1710-
if len(fields) != 2 {
1711-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1712-
}
1713-
1714-
days, err := strconv.ParseInt(fields[0], 10, 64)
1715-
if err != nil {
1716-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1621+
// extractTimeValue extracts years, months, days, microseconds from a string
1622+
// MySQL permits any punctuation delimiter in the expr format.
1623+
// See https://dev.mysql.com/doc/refman/8.0/en/expressions.html#temporal-intervals
1624+
func extractTimeValue(format string, index, cnt int) (int64, int64, int64, float64, error) {
1625+
neg := false
1626+
originalFmt := format
1627+
format = strings.TrimSpace(format)
1628+
if len(format) > 0 && format[0] == '-' {
1629+
neg = true
1630+
format = format[1:]
17171631
}
1718-
1719-
_, _, _, value, err := extractHourMicrosecond(fields[1])
1720-
if err != nil {
1721-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1632+
fields := make([]string, TimeValueCnt)
1633+
for i := range fields {
1634+
fields[i] = "0"
17221635
}
1723-
1724-
return 0, 0, days, value, nil
1725-
}
1726-
1727-
// extractDaySecond extracts day and hour from a string and its format is `DD HH:MM:SS`.
1728-
func extractDaySecond(format string) (int64, int64, int64, float64, error) {
1729-
fields := strings.Split(format, " ")
1730-
if len(fields) != 2 {
1731-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1636+
matches := numericRegex.FindAllString(format, -1)
1637+
if len(matches) > cnt {
1638+
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(originalFmt)
17321639
}
1733-
1734-
days, err := strconv.ParseInt(fields[0], 10, 64)
1735-
if err != nil {
1736-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1640+
for i := range matches {
1641+
if neg {
1642+
fields[index] = "-" + matches[len(matches)-1-i]
1643+
} else {
1644+
fields[index] = matches[len(matches)-1-i]
1645+
}
1646+
index--
17371647
}
17381648

1739-
_, _, _, value, err := extractHourSecond(fields[1])
1649+
years, err := strconv.ParseInt(fields[YearIndex], 10, 64)
17401650
if err != nil {
1741-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1651+
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(originalFmt)
17421652
}
1743-
1744-
return 0, 0, days, value, nil
1745-
}
1746-
1747-
// extractDayMinute extracts day and minute from a string and its format is `DD HH:MM`.
1748-
func extractDayMinute(format string) (int64, int64, int64, float64, error) {
1749-
fields := strings.Split(format, " ")
1750-
if len(fields) != 2 {
1751-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1752-
}
1753-
1754-
days, err := strconv.ParseInt(fields[0], 10, 64)
1653+
months, err := strconv.ParseInt(fields[MonthIndex], 10, 64)
17551654
if err != nil {
1756-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1655+
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(originalFmt)
17571656
}
1758-
1759-
_, _, _, value, err := extractHourMinute(fields[1])
1657+
days, err := strconv.ParseInt(fields[DayIndex], 10, 64)
17601658
if err != nil {
1761-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1762-
}
1763-
1764-
return 0, 0, days, value, nil
1765-
}
1766-
1767-
// extractDayHour extracts day and hour from a string and its format is `DD HH`.
1768-
func extractDayHour(format string) (int64, int64, int64, float64, error) {
1769-
fields := strings.Split(format, " ")
1770-
if len(fields) != 2 {
1771-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1659+
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(originalFmt)
17721660
}
17731661

1774-
days, err := strconv.ParseInt(fields[0], 10, 64)
1662+
hours, err := strconv.ParseFloat(fields[HourIndex], 64)
17751663
if err != nil {
1776-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1664+
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(originalFmt)
17771665
}
1778-
1779-
hours, err := strconv.ParseFloat(fields[1], 64)
1666+
minutes, err := strconv.ParseFloat(fields[MinuteIndex], 64)
17801667
if err != nil {
1781-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1668+
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(originalFmt)
17821669
}
1783-
1784-
return 0, 0, days, hours * float64(gotime.Hour), nil
1785-
}
1786-
1787-
// extractYearMonth extracts year and month from a string and its format is `YYYY-MM`.
1788-
func extractYearMonth(format string) (int64, int64, int64, float64, error) {
1789-
fields := strings.Split(format, "-")
1790-
if len(fields) != 2 {
1791-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1792-
}
1793-
1794-
years, err := strconv.ParseInt(fields[0], 10, 64)
1670+
seconds, err := strconv.ParseFloat(fields[SecondIndex], 64)
17951671
if err != nil {
1796-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1672+
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(originalFmt)
17971673
}
1798-
1799-
months, err := strconv.ParseInt(fields[1], 10, 64)
1674+
microseconds, err := strconv.ParseFloat(alignFrac(fields[MicrosecondIndex], MaxFsp), 64)
18001675
if err != nil {
1801-
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(format)
1676+
return 0, 0, 0, 0, ErrIncorrectDatetimeValue.GenWithStackByArgs(originalFmt)
18021677
}
1678+
durations := hours*float64(gotime.Hour) + minutes*float64(gotime.Minute) +
1679+
seconds*float64(gotime.Second) + microseconds*float64(gotime.Microsecond)
18031680

1804-
return years, months, 0, 0, nil
1681+
return years, months, days, durations, nil
18051682
}
18061683

18071684
// ExtractTimeValue extracts time value from time unit and format.
@@ -1810,27 +1687,27 @@ func ExtractTimeValue(unit string, format string) (int64, int64, int64, float64,
18101687
case "MICROSECOND", "SECOND", "MINUTE", "HOUR", "DAY", "WEEK", "MONTH", "QUARTER", "YEAR":
18111688
return extractSingleTimeValue(unit, format)
18121689
case "SECOND_MICROSECOND":
1813-
return extractSecondMicrosecond(format)
1690+
return extractTimeValue(format, MicrosecondIndex, SecondMicrosecondMaxCnt)
18141691
case "MINUTE_MICROSECOND":
1815-
return extractMinuteMicrosecond(format)
1692+
return extractTimeValue(format, MicrosecondIndex, MinuteMicrosecondMaxCnt)
18161693
case "MINUTE_SECOND":
1817-
return extractMinuteSecond(format)
1694+
return extractTimeValue(format, SecondIndex, MinuteSecondMaxCnt)
18181695
case "HOUR_MICROSECOND":
1819-
return extractHourMicrosecond(format)
1696+
return extractTimeValue(format, MicrosecondIndex, HourMicrosecondMaxCnt)
18201697
case "HOUR_SECOND":
1821-
return extractHourSecond(format)
1698+
return extractTimeValue(format, SecondIndex, HourSecondMaxCnt)
18221699
case "HOUR_MINUTE":
1823-
return extractHourMinute(format)
1700+
return extractTimeValue(format, MinuteIndex, HourMinuteMaxCnt)
18241701
case "DAY_MICROSECOND":
1825-
return extractDayMicrosecond(format)
1702+
return extractTimeValue(format, MicrosecondIndex, DayMicrosecondMaxCnt)
18261703
case "DAY_SECOND":
1827-
return extractDaySecond(format)
1704+
return extractTimeValue(format, SecondIndex, DaySecondMaxCnt)
18281705
case "DAY_MINUTE":
1829-
return extractDayMinute(format)
1706+
return extractTimeValue(format, MinuteIndex, DayMinuteMaxCnt)
18301707
case "DAY_HOUR":
1831-
return extractDayHour(format)
1708+
return extractTimeValue(format, HourIndex, DayHourMaxCnt)
18321709
case "YEAR_MONTH":
1833-
return extractYearMonth(format)
1710+
return extractTimeValue(format, MonthIndex, YearMonthMaxCnt)
18341711
default:
18351712
return 0, 0, 0, 0, errors.Errorf("invalid singel timeunit - %s", unit)
18361713
}
@@ -2391,6 +2268,9 @@ var twoDigitRegex = regexp.MustCompile("^[1-9][0-9]?")
23912268
// oneToSixDigitRegex: it was just for [0, 999999]
23922269
var oneToSixDigitRegex = regexp.MustCompile("^[0-9]{0,6}")
23932270

2271+
// numericRegex: it was for any numeric characters
2272+
var numericRegex = regexp.MustCompile("[0-9]+")
2273+
23942274
// parseTwoNumeric is used for pattens 0..31 0..24 0..60 and so on.
23952275
// It returns the parsed int, and remain data after parse.
23962276
func parseTwoNumeric(input string) (int, string) {

0 commit comments

Comments
 (0)