Skip to content

Commit b76b2da

Browse files
qw4990zz-jason
authored andcommitted
types: fix incompatible issue for builtin function str_to_date (#9693)
1 parent ec7514f commit b76b2da

File tree

2 files changed

+33
-11
lines changed

2 files changed

+33
-11
lines changed

expression/builtin_time_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,6 +1264,11 @@ func (s *testEvaluatorSuite) TestStrToDate(c *C) {
12641264
{"2016 11 22 16 50 22", `%Y%m%d%H%i%s`, true, time.Date(2016, 11, 22, 16, 50, 22, 0, time.Local)},
12651265
{"16-50-22 2016 11 22", `%H-%i-%s%Y%m%d`, true, time.Date(2016, 11, 22, 16, 50, 22, 0, time.Local)},
12661266
{"16-50 2016 11 22", `%H-%i-%s%Y%m%d`, false, time.Time{}},
1267+
{"15-01-2001 1:59:58.999", "%d-%m-%Y %I:%i:%s.%f", true, time.Date(2001, 1, 15, 1, 59, 58, 999000000, time.Local)},
1268+
{"15-01-2001 1:59:58.1", "%d-%m-%Y %H:%i:%s.%f", true, time.Date(2001, 1, 15, 1, 59, 58, 100000000, time.Local)},
1269+
{"15-01-2001 1:59:58.", "%d-%m-%Y %H:%i:%s.%f", true, time.Date(2001, 1, 15, 1, 59, 58, 000000000, time.Local)},
1270+
{"15-01-2001 1:9:8.999", "%d-%m-%Y %H:%i:%s.%f", true, time.Date(2001, 1, 15, 1, 9, 8, 999000000, time.Local)},
1271+
{"15-01-2001 1:9:8.999", "%d-%m-%Y %H:%i:%S.%f", true, time.Date(2001, 1, 15, 1, 9, 8, 999000000, time.Local)},
12671272
}
12681273

12691274
fc := funcs[ast.StrToDate]

types/time.go

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2157,8 +2157,8 @@ var dateFormatParserTable = map[string]dateFormatParser{
21572157
"%e": dayOfMonthNumeric, // Day of the month, numeric (0..31)
21582158
"%f": microSeconds, // Microseconds (000000..999999)
21592159
"%h": hour24TwoDigits, // Hour (01..12)
2160-
"%H": hour24TwoDigits, // Hour (01..12)
2161-
"%I": hour24TwoDigits, // Hour (01..12)
2160+
"%H": hour24Numeric, // Hour (00..23)
2161+
"%I": hour12Numeric, // Hour (01..12)
21622162
"%i": minutesNumeric, // Minutes, numeric (00..59)
21632163
"%j": dayOfYearThreeDigits, // Day of year (001..366)
21642164
"%k": hour24Numeric, // Hour (0..23)
@@ -2267,21 +2267,27 @@ func hour24TwoDigits(t *MysqlTime, input string, ctx map[string]int) (string, bo
22672267
}
22682268

22692269
func secondsNumeric(t *MysqlTime, input string, ctx map[string]int) (string, bool) {
2270-
v, succ := parseDigits(input, 2)
2270+
result := oneOrTwoDigitRegex.FindString(input)
2271+
length := len(result)
2272+
2273+
v, succ := parseDigits(input, length)
22712274
if !succ || v >= 60 {
22722275
return input, false
22732276
}
22742277
t.second = uint8(v)
2275-
return input[2:], true
2278+
return input[length:], true
22762279
}
22772280

22782281
func minutesNumeric(t *MysqlTime, input string, ctx map[string]int) (string, bool) {
2279-
v, succ := parseDigits(input, 2)
2282+
result := oneOrTwoDigitRegex.FindString(input)
2283+
length := len(result)
2284+
2285+
v, succ := parseDigits(input, length)
22802286
if !succ || v >= 60 {
22812287
return input, false
22822288
}
22832289
t.minute = uint8(v)
2284-
return input[2:], true
2290+
return input[length:], true
22852291
}
22862292

22872293
const time12HourLen = len("hh:mm:ssAM")
@@ -2378,6 +2384,9 @@ var oneOrTwoDigitRegex = regexp.MustCompile("^[0-9]{1,2}")
23782384
// twoDigitRegex: it was just for two digit number string. Ex: "01" or "12"
23792385
var twoDigitRegex = regexp.MustCompile("^[1-9][0-9]?")
23802386

2387+
// oneToSixDigitRegex: it was just for [0, 999999]
2388+
var oneToSixDigitRegex = regexp.MustCompile("^[0-9]{0,6}")
2389+
23812390
// parseTwoNumeric is used for pattens 0..31 0..24 0..60 and so on.
23822391
// It returns the parsed int, and remain data after parse.
23832392
func parseTwoNumeric(input string) (int, string) {
@@ -2437,15 +2446,23 @@ func hour12Numeric(t *MysqlTime, input string, ctx map[string]int) (string, bool
24372446
}
24382447

24392448
func microSeconds(t *MysqlTime, input string, ctx map[string]int) (string, bool) {
2440-
if len(input) < 6 {
2441-
return input, false
2449+
result := oneToSixDigitRegex.FindString(input)
2450+
length := len(result)
2451+
if length == 0 {
2452+
t.microsecond = 0
2453+
return input, true
24422454
}
2443-
v, err := strconv.ParseUint(input[:6], 10, 64)
2444-
if err != nil {
2455+
2456+
v, ok := parseDigits(input, length)
2457+
2458+
if !ok {
24452459
return input, false
24462460
}
2461+
for v > 0 && v*10 < 1000000 {
2462+
v *= 10
2463+
}
24472464
t.microsecond = uint32(v)
2448-
return input[6:], true
2465+
return input[length:], true
24492466
}
24502467

24512468
func yearNumericFourDigits(t *MysqlTime, input string, ctx map[string]int) (string, bool) {

0 commit comments

Comments
 (0)