mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-12-19 04:42:37 +00:00
Implementation of missing formats
This commit is contained in:
parent
3646fef2fc
commit
408f8a228e
@ -1569,7 +1569,7 @@ public:
|
|||||||
|
|
||||||
String pattern = pattern_column->getValue<String>();
|
String pattern = pattern_column->getValue<String>();
|
||||||
|
|
||||||
std::vector<std::function<void (String &, UInt32, DateLUTImpl)>> instructions = {};
|
std::vector<std::function<void (String &, UInt32, const DateLUTImpl &)>> instructions = {};
|
||||||
parsePattern(pattern, instructions);
|
parsePattern(pattern, instructions);
|
||||||
|
|
||||||
const DateLUTImpl * time_zone_tmp = nullptr;
|
const DateLUTImpl * time_zone_tmp = nullptr;
|
||||||
@ -1584,12 +1584,12 @@ public:
|
|||||||
const ColumnUInt32::Container & vec = times->getData();
|
const ColumnUInt32::Container & vec = times->getData();
|
||||||
res_column->reserve(vec.size());
|
res_column->reserve(vec.size());
|
||||||
|
|
||||||
|
String formatted_string = "";
|
||||||
for (size_t i = 0; i < input_rows_count; ++i)
|
for (size_t i = 0; i < input_rows_count; ++i)
|
||||||
{
|
{
|
||||||
|
formatted_string.clear();
|
||||||
UInt32 date_time_value = vec[i];
|
UInt32 date_time_value = vec[i];
|
||||||
|
|
||||||
String formatted_string = "";
|
|
||||||
|
|
||||||
for(auto & instruction : instructions) {
|
for(auto & instruction : instructions) {
|
||||||
instruction(formatted_string, date_time_value, time_zone);
|
instruction(formatted_string, date_time_value, time_zone);
|
||||||
}
|
}
|
||||||
@ -1601,59 +1601,105 @@ public:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void parsePattern(String & pattern, std::vector<std::function<void (String &, UInt32, DateLUTImpl)>> & instructions)
|
void parsePattern(String & pattern, std::vector<std::function<void (String &, UInt32, const DateLUTImpl &)>> & instructions)
|
||||||
{
|
{
|
||||||
unsigned long last_pos = 0;
|
size_t last_pos = 0;
|
||||||
for (unsigned long s = 0; s < pattern.length(); s++) {
|
for (size_t s = 0; s < pattern.length(); s++) {
|
||||||
if(pattern[s] == '%')
|
if(pattern[s] == '%')
|
||||||
{
|
{
|
||||||
if (last_pos > 0)
|
if (last_pos > 0)
|
||||||
{
|
{
|
||||||
instructions.push_back(
|
instructions.push_back(
|
||||||
[last_pos, s, &pattern](auto & receiver, auto , DateLUTImpl ) {
|
[last_pos, s, &pattern](auto & receiver, auto ,const auto &) {
|
||||||
receiver.append(pattern, last_pos - 1, 1 + s - last_pos);
|
receiver.append(pattern, last_pos - 1, 1 + s - last_pos);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
last_pos = 0;
|
last_pos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (++s == pattern.length()) {
|
if (++s == pattern.length())
|
||||||
throw Exception("Sign '%' is last in pattern, if you need it, use '%%'");
|
throw Exception("Sign '%' is last in pattern, if you need it, use '%%'");
|
||||||
}
|
|
||||||
|
|
||||||
switch(pattern[s])
|
switch(pattern[s])
|
||||||
{
|
{
|
||||||
|
// Year, divided by 100, zero-padded
|
||||||
|
case 'C':
|
||||||
|
instructions.push_back(
|
||||||
|
[](auto & receiver, auto date_or_ts, const auto & time_zone) {
|
||||||
|
auto year = ToYearImpl::execute(date_or_ts, time_zone);
|
||||||
|
|
||||||
|
int s = static_cast<int>(floor(year/100));
|
||||||
|
if(s < 10)
|
||||||
|
receiver.append("0");
|
||||||
|
|
||||||
|
receiver.append(toString(s));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
// Day of the month, zero-padded (01-31)
|
// Day of the month, zero-padded (01-31)
|
||||||
case 'd':
|
case 'd':
|
||||||
instructions.push_back(
|
instructions.push_back(
|
||||||
[](auto & receiver, auto date_or_ts, DateLUTImpl time_zone) {
|
[](auto & receiver, auto date_or_ts, const auto & time_zone) {
|
||||||
auto day = ToDayOfMonthImpl::execute(date_or_ts, time_zone);
|
auto day = ToDayOfMonthImpl::execute(date_or_ts, time_zone);
|
||||||
|
|
||||||
if (day < 10) {
|
if (day < 10)
|
||||||
receiver.append("0");
|
receiver.append("0");
|
||||||
}
|
|
||||||
|
|
||||||
receiver.append(toString(day));
|
receiver.append(toString(day));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Four digits year
|
// Short MM/DD/YY date, equivalent to %m/%d/%y
|
||||||
case 'G':
|
case 'D':
|
||||||
instructions.push_back(
|
instructions.push_back(
|
||||||
[](auto & receiver, auto date_or_ts, DateLUTImpl time_zone) {
|
[](auto & receiver, auto date_or_ts, const auto & time_zone) {
|
||||||
receiver.append(toString(ToYearImpl::execute(date_or_ts, time_zone)));
|
auto month = ToMonthImpl::execute(date_or_ts, time_zone);
|
||||||
|
auto day = ToDayOfMonthImpl::execute(date_or_ts, time_zone);
|
||||||
|
auto year = ToYearImpl::execute(date_or_ts, time_zone) % 1000;
|
||||||
|
|
||||||
|
char buf[20];
|
||||||
|
auto written = sprintf(buf, "%02d/%02d/%02d", month, day, year);
|
||||||
|
receiver.append(buf, written);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Day of the month, space-padded ( 1-31) 23
|
||||||
|
case 'e':
|
||||||
|
instructions.push_back(
|
||||||
|
[](auto & receiver, auto date_or_ts, const auto & time_zone) {
|
||||||
|
auto day = ToDayOfMonthImpl::execute(date_or_ts, time_zone);
|
||||||
|
|
||||||
|
if(day < 10)
|
||||||
|
receiver.append(" ");
|
||||||
|
receiver.append(toString(day));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Short YYYY-MM-DD date, equivalent to %Y-%m-%d 2001-08-23
|
||||||
|
case 'F':
|
||||||
|
instructions.push_back(
|
||||||
|
[](auto & receiver, auto date_or_ts, const auto & time_zone) {
|
||||||
|
auto year = ToYearImpl::execute(date_or_ts, time_zone);
|
||||||
|
auto month = ToMonthImpl::execute(date_or_ts, time_zone);
|
||||||
|
auto day = ToDayOfMonthImpl::execute(date_or_ts, time_zone);
|
||||||
|
|
||||||
|
char buf[20];
|
||||||
|
auto written = sprintf(buf, "%04d-%02d-%02d", year, month, day);
|
||||||
|
receiver.append(buf, written);
|
||||||
|
}
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Hour in 24h format (00-23)
|
// Hour in 24h format (00-23)
|
||||||
case 'H':
|
case 'H':
|
||||||
instructions.push_back(
|
instructions.push_back(
|
||||||
[](auto & receiver, auto date_or_ts, DateLUTImpl time_zone) {
|
[](auto & receiver, auto date_or_ts, const auto & time_zone) {
|
||||||
|
|
||||||
UInt8 x = ToHourImpl::execute(date_or_ts, time_zone);
|
auto x = ToHourImpl::execute(date_or_ts, time_zone);
|
||||||
if (x < 10) {
|
if (x < 10) {
|
||||||
receiver.append("0");
|
receiver.append("0");
|
||||||
}
|
}
|
||||||
@ -1662,16 +1708,44 @@ public:
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Hour in 12h format (01-12)
|
||||||
|
case 'I':
|
||||||
|
instructions.push_back(
|
||||||
|
[](auto & receiver, auto date_or_ts, const auto & time_zone) {
|
||||||
|
|
||||||
|
auto x = (ToHourImpl::execute(date_or_ts, time_zone) % 12) + 1;
|
||||||
|
if (x < 10)
|
||||||
|
receiver.append("0");
|
||||||
|
|
||||||
|
receiver.append(toString(x));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Day of the year (001-366) 235
|
||||||
|
case 'j':
|
||||||
|
instructions.push_back(
|
||||||
|
[](auto & receiver, auto date_or_ts, const auto & time_zone) {
|
||||||
|
|
||||||
|
auto x = (ToHourImpl::execute(date_or_ts, time_zone) % 12) + 1;
|
||||||
|
if (x < 10)
|
||||||
|
receiver.append("0");
|
||||||
|
|
||||||
|
receiver.append(toString(x));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
// Month as a decimal number (01-12)
|
// Month as a decimal number (01-12)
|
||||||
case 'm':
|
case 'm':
|
||||||
|
|
||||||
instructions.push_back(
|
instructions.push_back(
|
||||||
[](auto & receiver, auto date_or_ts, DateLUTImpl time_zone) {
|
[](auto & receiver, auto date_or_ts, const auto & time_zone) {
|
||||||
|
|
||||||
UInt8 x = ToMonthImpl::execute(date_or_ts, time_zone);
|
UInt8 x = ToMonthImpl::execute(date_or_ts, time_zone);
|
||||||
if (x < 10) {
|
if (x < 10)
|
||||||
receiver.append("0");
|
receiver.append("0");
|
||||||
}
|
|
||||||
receiver.append(toString(x));
|
receiver.append(toString(x));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -1681,35 +1755,129 @@ public:
|
|||||||
case 'M':
|
case 'M':
|
||||||
|
|
||||||
instructions.push_back(
|
instructions.push_back(
|
||||||
[](auto & receiver, auto date_or_ts, DateLUTImpl time_zone) {
|
[](auto & receiver, auto date_or_ts, const auto & time_zone) {
|
||||||
|
|
||||||
UInt8 x = ToMinuteImpl::execute(date_or_ts, time_zone);
|
UInt8 x = ToMinuteImpl::execute(date_or_ts, time_zone);
|
||||||
if (x < 10) {
|
if (x < 10)
|
||||||
receiver.append("0");
|
receiver.append("0");
|
||||||
}
|
|
||||||
receiver.append(toString(x));
|
receiver.append(toString(x));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// New line character "\n"
|
||||||
|
case 'n':
|
||||||
|
|
||||||
|
instructions.push_back(
|
||||||
|
[](auto & receiver, auto , const auto &) {
|
||||||
|
receiver.append("\n");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// AM or PM
|
||||||
|
case 'p':
|
||||||
|
|
||||||
|
instructions.push_back(
|
||||||
|
[](auto & receiver, auto date_or_ts, const auto & time_zone) {
|
||||||
|
receiver.append(ToHourImpl::execute(date_or_ts, time_zone) < 12 ? "AM" : "PM");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// 24-hour HH:MM time, equivalent to %H:%M 14:55
|
||||||
|
case 'R':
|
||||||
|
|
||||||
|
instructions.push_back(
|
||||||
|
[](auto & receiver, auto date_or_ts, const auto & time_zone) {
|
||||||
|
|
||||||
|
auto hour = ToHourImpl::execute(date_or_ts, time_zone);
|
||||||
|
auto minute = ToMinuteImpl::execute(date_or_ts, time_zone);
|
||||||
|
|
||||||
|
char buf[10];
|
||||||
|
|
||||||
|
auto written = sprintf(buf, "%02d:%02d", hour, minute);
|
||||||
|
|
||||||
|
receiver.append(buf, written);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
// Seconds
|
// Seconds
|
||||||
case 'S':
|
case 'S':
|
||||||
instructions.push_back(
|
instructions.push_back(
|
||||||
[](auto & receiver, auto date_or_ts, DateLUTImpl time_zone) {
|
[](auto & receiver, auto date_or_ts, const auto & time_zone) {
|
||||||
|
|
||||||
UInt8 x = ToSecondImpl::execute(date_or_ts, time_zone);
|
UInt8 x = ToSecondImpl::execute(date_or_ts, time_zone);
|
||||||
if (x < 10) {
|
if (x < 10)
|
||||||
receiver.append("0");
|
receiver.append("0");
|
||||||
}
|
|
||||||
receiver.append(toString(x));
|
receiver.append(toString(x));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Horizontal-tab character ('\t')
|
||||||
|
case 't':
|
||||||
|
instructions.push_back(
|
||||||
|
[](auto & receiver, auto , const auto & ) {
|
||||||
|
receiver.append("\t");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S 14:55:02
|
||||||
|
case 'T':
|
||||||
|
instructions.push_back(
|
||||||
|
[](auto & receiver, auto date_or_ts, const auto & time_zone) {
|
||||||
|
|
||||||
|
auto hour = ToHourImpl::execute(date_or_ts, time_zone);
|
||||||
|
auto minute = ToMinuteImpl::execute(date_or_ts, time_zone);
|
||||||
|
auto second = ToSecondImpl::execute(date_or_ts, time_zone);
|
||||||
|
|
||||||
|
char buffer[20];
|
||||||
|
auto written = sprintf(buffer, "%02d:%02d:%02d", hour, minute, second);
|
||||||
|
receiver.append(buffer, written);
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
// ISO 8601 weekday as number with Monday as 1 (1-7)
|
||||||
|
case 'u':
|
||||||
|
instructions.push_back(
|
||||||
|
[](auto & receiver, auto date_or_ts, const auto & time_zone) {
|
||||||
|
receiver.append(toString(ToDayOfWeekImpl::execute(date_or_ts, time_zone)));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Weekday as a decimal number with Sunday as 0 (0-6) 4
|
||||||
|
case 'w':
|
||||||
|
instructions.push_back(
|
||||||
|
[](auto & receiver, auto date_or_ts, const auto & time_zone) {
|
||||||
|
auto day = ToDayOfWeekImpl::execute(date_or_ts, time_zone);
|
||||||
|
receiver.append(toString(day == 7 ? 0 : day));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Four digits year
|
||||||
|
case 'Y':
|
||||||
|
instructions.push_back(
|
||||||
|
[](auto & receiver, auto date_or_ts, const auto & time_zone) {
|
||||||
|
receiver.append(toString(ToYearImpl::execute(date_or_ts, time_zone)));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case '%':
|
case '%':
|
||||||
instructions.push_back(
|
instructions.push_back(
|
||||||
[](auto & receiver, auto , DateLUTImpl ) {
|
[](auto & receiver, auto , const auto &) {
|
||||||
receiver.append("%");
|
receiver.append("%");
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -1731,7 +1899,7 @@ public:
|
|||||||
{
|
{
|
||||||
auto s = pattern.length();
|
auto s = pattern.length();
|
||||||
instructions.push_back(
|
instructions.push_back(
|
||||||
[last_pos, s, &pattern](auto & receiver, auto , DateLUTImpl ) {
|
[last_pos, s, &pattern](auto & receiver, auto , const auto &) {
|
||||||
receiver.append(pattern, last_pos - 1, 1 + s - last_pos);
|
receiver.append(pattern, last_pos - 1, 1 + s - last_pos);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user