Skip to content

Commit 0529b56

Browse files
committed
types: fix incompatible issue for builtin function str_to_date (pingcap#9693)
1 parent 2129872 commit 0529b56

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
@@ -1251,6 +1251,11 @@ func (s *testEvaluatorSuite) TestStrToDate(c *C) {
12511251
{"2016 11 22 16 50 22", `%Y%m%d%H%i%s`, true, time.Date(2016, 11, 22, 16, 50, 22, 0, time.Local)},
12521252
{"16-50-22 2016 11 22", `%H-%i-%s%Y%m%d`, true, time.Date(2016, 11, 22, 16, 50, 22, 0, time.Local)},
12531253
{"16-50 2016 11 22", `%H-%i-%s%Y%m%d`, false, time.Time{}},
1254+
{"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)},
1255+
{"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)},
1256+
{"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)},
1257+
{"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)},
1258+
{"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)},
12541259
}
12551260

12561261
fc := funcs[ast.StrToDate]

types/time.go

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

22592259
func secondsNumeric(t *MysqlTime, input string, ctx map[string]int) (string, bool) {
2260-
v, succ := parseDigits(input, 2)
2260+
result := oneOrTwoDigitRegex.FindString(input)
2261+
length := len(result)
2262+
2263+
v, succ := parseDigits(input, length)
22612264
if !succ || v >= 60 {
22622265
return input, false
22632266
}
22642267
t.second = uint8(v)
2265-
return input[2:], true
2268+
return input[length:], true
22662269
}
22672270

22682271
func minutesNumeric(t *MysqlTime, input string, ctx map[string]int) (string, bool) {
2269-
v, succ := parseDigits(input, 2)
2272+
result := oneOrTwoDigitRegex.FindString(input)
2273+
length := len(result)
2274+
2275+
v, succ := parseDigits(input, length)
22702276
if !succ || v >= 60 {
22712277
return input, false
22722278
}
22732279
t.minute = uint8(v)
2274-
return input[2:], true
2280+
return input[length:], true
22752281
}
22762282

22772283
const time12HourLen = len("hh:mm:ssAM")
@@ -2368,6 +2374,9 @@ var oneOrTwoDigitRegex = regexp.MustCompile("^[0-9]{1,2}")
23682374
// twoDigitRegex: it was just for two digit number string. Ex: "01" or "12"
23692375
var twoDigitRegex = regexp.MustCompile("^[1-9][0-9]?")
23702376

2377+
// oneToSixDigitRegex: it was just for [0, 999999]
2378+
var oneToSixDigitRegex = regexp.MustCompile("^[0-9]{0,6}")
2379+
23712380
// parseTwoNumeric is used for pattens 0..31 0..24 0..60 and so on.
23722381
// It returns the parsed int, and remain data after parse.
23732382
func parseTwoNumeric(input string) (int, string) {
@@ -2427,15 +2436,23 @@ func hour12Numeric(t *MysqlTime, input string, ctx map[string]int) (string, bool
24272436
}
24282437

24292438
func microSeconds(t *MysqlTime, input string, ctx map[string]int) (string, bool) {
2430-
if len(input) < 6 {
2431-
return input, false
2439+
result := oneToSixDigitRegex.FindString(input)
2440+
length := len(result)
2441+
if length == 0 {
2442+
t.microsecond = 0
2443+
return input, true
24322444
}
2433-
v, err := strconv.ParseUint(input[:6], 10, 64)
2434-
if err != nil {
2445+
2446+
v, ok := parseDigits(input, length)
2447+
2448+
if !ok {
24352449
return input, false
24362450
}
2451+
for v > 0 && v*10 < 1000000 {
2452+
v *= 10
2453+
}
24372454
t.microsecond = uint32(v)
2438-
return input[6:], true
2455+
return input[length:], true
24392456
}
24402457

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

0 commit comments

Comments
 (0)