Replace mySQL date formatter M behavior from minutes to month name

This commit is contained in:
Robert Schulze 2023-03-23 22:16:10 +00:00
parent 22da93e239
commit 3db38dbb5a
No known key found for this signature in database
GPG Key ID: 26703B55FB13728A
11 changed files with 493 additions and 159 deletions

View File

@ -1276,16 +1276,16 @@ Using replacement fields, you can define a pattern for the resulting string. “
| %k | hour in 24h format (00-23) | 22 |
| %l | hour in 12h format (01-12) | 09 |
| %m | month as an integer number (01-12) | 01 |
| %M | minute (00-59) | 33 |
| %M | full month name (January-December) | January |
| %n | new-line character () | |
| %p | AM or PM designation | PM |
| %Q | Quarter (1-4) | 1 |
| %r | 12-hour HH:MM AM/PM time, equivalent to %H:%M %p | 10:30 PM |
| %R | 24-hour HH:MM time, equivalent to %H:%M | 22:33 |
| %r | 12-hour HH:MM AM/PM time, equivalent to %H:%i %p | 10:30 PM |
| %R | 24-hour HH:MM time, equivalent to %H:%i | 22:33 |
| %s | second (00-59) | 44 |
| %S | second (00-59) | 44 |
| %t | horizontal-tab character () | |
| %T | ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S | 22:33:44 |
| %T | ISO 8601 time format (HH:MM:SS), equivalent to %H:%i:%S | 22:33:44 |
| %u | ISO 8601 weekday as number with Monday as 1 (1-7) | 2 |
| %V | ISO 8601 week number (01-53) | 01 |
| %w | weekday as a integer number with Sunday as 0 (0-6) | 2 |

File diff suppressed because it is too large Load Diff

View File

@ -48,7 +48,7 @@ namespace
const std::unordered_map<String, std::pair<String, Int32>> monthMap{
{"jan", {"uary", 1}},
{"feb", {"ruary", 2}},
{"mar", {"rch", 3}},
{"mar", {"ch", 3}},
{"apr", {"il", 4}},
{"may", {"", 5}},
{"jun", {"e", 6}},
@ -724,6 +724,38 @@ namespace
return cur;
}
static Pos mysqlMonthOfYearTextLong(Pos cur, Pos end, const String & fragment, DateTime & date)
{
checkSpace(cur, end, 3, "mysqlMonthOfYearTextLong requires size >= 3", fragment);
String text1(cur, 3);
boost::to_lower(text1);
auto it = monthMap.find(text1);
if (it == monthMap.end())
throw Exception(
ErrorCodes::CANNOT_PARSE_DATETIME,
"Unable to parse first part of fragment {} from {} because of unknown month of year text: {}",
fragment,
std::string_view(cur, end - cur),
text1);
cur += 3;
size_t expected_remaining_size = it->second.first.size();
checkSpace(cur, end, expected_remaining_size, "mysqlMonthOfYearTextLong requires the second parg size >= " + std::to_string(expected_remaining_size), fragment);
String text2(cur, expected_remaining_size);
boost::to_lower(text2);
if (text2 != it->second.first)
throw Exception(
ErrorCodes::CANNOT_PARSE_DATETIME,
"Unable to parse second part of fragment {} from {} because of unknown month of year text: {}",
fragment,
std::string_view(cur, end - cur),
text1 + text2);
cur += expected_remaining_size;
date.setMonth(it->second.second);
return cur;
}
static Pos mysqlMonth(Pos cur, Pos end, const String & fragment, DateTime & date)
{
Int32 month;
@ -856,7 +888,7 @@ namespace
static Pos mysqlDayOfWeekTextLong(Pos cur, Pos end, const String & fragment, DateTime & date)
{
checkSpace(cur, end, 6, "jodaDayOfWeekText requires size >= 6", fragment);
checkSpace(cur, end, 6, "mysqlDayOfWeekTextLong requires size >= 6", fragment);
String text1(cur, 3);
boost::to_lower(text1);
auto it = dayOfWeekMap.find(text1);
@ -870,7 +902,7 @@ namespace
cur += 3;
size_t expected_remaining_size = it->second.first.size();
checkSpace(cur, end, expected_remaining_size, "jodaDayOfWeekText requires the second parg size >= " + std::to_string(expected_remaining_size), fragment);
checkSpace(cur, end, expected_remaining_size, "mysqlDayOfWeekTextLong requires the second parg size >= " + std::to_string(expected_remaining_size), fragment);
String text2(cur, expected_remaining_size);
boost::to_lower(text2);
if (text2 != it->second.first)
@ -1470,7 +1502,7 @@ namespace
// Minute (00-59)
case 'M':
instructions.emplace_back(ACTION_ARGS(Instruction::mysqlMinute));
instructions.emplace_back(ACTION_ARGS(Instruction::mysqlMonthOfYearTextLong));
break;
// AM or PM

View File

@ -17,7 +17,7 @@ Jan Jan
366 366
00 00
01 01
33 00
January January
\n \n
AM AM
AM
@ -50,3 +50,5 @@ no formatting pattern no formatting pattern
2022-12-08 18:11:29.0
2022-12-08 00:00:00.0
2022-12-08 00:00:00.0
16\t\n%MayMonday16
00\t\n%MayMonday00

View File

@ -74,3 +74,6 @@ select formatDateTime(toDateTime64('2022-12-08 18:11:29.1234', 0, 'UTC'), '%F %T
select formatDateTime(toDateTime('2022-12-08 18:11:29', 'UTC'), '%F %T.%f');
select formatDateTime(toDate32('2022-12-08 18:11:29', 'UTC'), '%F %T.%f');
select formatDateTime(toDate('2022-12-08 18:11:29', 'UTC'), '%F %T.%f');
select formatDateTime(toDateTime('2018-05-07 15:16:17', 'UTC'), '%i%t%n%%%M%W%i');
select formatDateTime(toDate32('2018-05-07', 'UTC'), '%i%t%n%%%M%W%i');

View File

@ -83,7 +83,7 @@ CAST(N as DateTime64(9, 'Europe/Minsk'))
# CAST(N as DateTime64(12, 'Asia/Istanbul'))
# DateTime64(18) will always fail due to zero precision, but it is Ok to test here:
# CAST(N as DateTime64(18, 'Asia/Istanbul'))
formatDateTime(N, '%C %d %D %e %F %H %I %j %m %M %p %R %S %T %u %V %w %y %Y %%', 'Asia/Istanbul')
formatDateTime(N, '%C %d %D %e %F %H %I %j %m %i %p %R %S %T %u %V %w %y %Y %%', 'Asia/Istanbul')
""".splitlines()
# Expanded later to cartesian product of all arguments, using format string.

View File

@ -353,7 +353,7 @@ SELECT CAST(N as DateTime64(9, \'Europe/Minsk\'))
"DateTime64(9, 'Europe/Minsk')","2019-09-16 19:20:11.000000000"
"DateTime64(9, 'Europe/Minsk')","2019-09-16 19:20:11.234000000"
------------------------------------------
SELECT formatDateTime(N, \'%C %d %D %e %F %H %I %j %m %M %p %R %S %T %u %V %w %y %Y %%\', \'Asia/Istanbul\')
SELECT formatDateTime(N, \'%C %d %D %e %F %H %I %j %m %i %p %R %S %T %u %V %w %y %Y %%\', \'Asia/Istanbul\')
"String","20 16 09/16/19 16 2019-09-16 00 12 259 09 00 AM 00:00 00 00:00:00 1 38 1 19 2019 %"
"String","20 16 09/16/19 16 2019-09-16 19 07 259 09 20 PM 19:20 11 19:20:11 1 38 1 19 2019 %"
"String","20 16 09/16/19 16 2019-09-16 19 07 259 09 20 PM 19:20 11 19:20:11 1 38 1 19 2019 %"

View File

@ -24,7 +24,7 @@ Jan Jan
366 366
00 00
01 01
33 00
January January
\n \n
AM AM
AM

View File

@ -17,7 +17,7 @@ Jan Jan
366 366
00 00
01 01
33 00
January January
\n \n
AM AM
AM

View File

@ -26,6 +26,13 @@ select parseDateTime('jun', '%b', 'UTC') = toDateTime('2000-06-01', 'UTC');
select parseDateTime('JUN', '%b', 'UTC') = toDateTime('2000-06-01', 'UTC');
1
select parseDateTime('abc', '%b'); -- { serverError CANNOT_PARSE_DATETIME }
select parseDateTime('may', '%M', 'UTC') = toDateTime('2000-05-01', 'UTC');
1
select parseDateTime('MAY', '%M', 'UTC') = toDateTime('2000-05-01', 'UTC');
1
select parseDateTime('september', '%M', 'UTC') = toDateTime('2000-09-01', 'UTC');
1
select parseDateTime('summer', '%M'); -- { serverError CANNOT_PARSE_DATETIME }
-- day of month
select parseDateTime('07', '%d', 'UTC') = toDateTime('2000-01-07', 'UTC');
1

View File

@ -18,6 +18,10 @@ select parseDateTime('12345', '%c'); -- { serverError CANNOT_PARSE_DATETIME }
select parseDateTime('jun', '%b', 'UTC') = toDateTime('2000-06-01', 'UTC');
select parseDateTime('JUN', '%b', 'UTC') = toDateTime('2000-06-01', 'UTC');
select parseDateTime('abc', '%b'); -- { serverError CANNOT_PARSE_DATETIME }
select parseDateTime('may', '%M', 'UTC') = toDateTime('2000-05-01', 'UTC');
select parseDateTime('MAY', '%M', 'UTC') = toDateTime('2000-05-01', 'UTC');
select parseDateTime('september', '%M', 'UTC') = toDateTime('2000-09-01', 'UTC');
select parseDateTime('summer', '%M'); -- { serverError CANNOT_PARSE_DATETIME }
-- day of month
select parseDateTime('07', '%d', 'UTC') = toDateTime('2000-01-07', 'UTC');
@ -132,4 +136,4 @@ select parseDateTime('2021-01-04+23:00:00', '%Y-%m-%d+%H:%i:%s', 'UTC') = toDate
select parseDateTime('2019-07-03 11:04:10', '%Y-%m-%d %H:%i:%s', 'UTC') = toDateTime('2019-07-03 11:04:10', 'UTC');
select parseDateTime('10:04:11 03-07-2019', '%s:%i:%H %d-%m-%Y', 'UTC') = toDateTime('2019-07-03 11:04:10', 'UTC');
-- { echoOff }
-- { echoOff }