Add timestampadd/timestampdiff function (#2725)

This commit is contained in:
HangyuanLiu
2020-01-15 21:47:07 +08:00
committed by ZHAO Chun
parent 8ea5907252
commit 0ddca59d36
18 changed files with 793 additions and 64 deletions

View File

@ -351,6 +351,106 @@ DateTimeVal TimestampFunctions::timestamp_time_op(
return new_ts_val;
}
BigIntVal TimestampFunctions::years_diff(
FunctionContext* ctx, const DateTimeVal& ts_val1, const DateTimeVal& ts_val2) {
return timestamp_diff<YEAR>(ctx, ts_val1, ts_val2);
}
BigIntVal TimestampFunctions::months_diff(
FunctionContext* ctx, const DateTimeVal& ts_val1, const DateTimeVal& ts_val2) {
return timestamp_diff<MONTH>(ctx, ts_val1, ts_val2);
}
BigIntVal TimestampFunctions::weeks_diff(
FunctionContext* ctx, const DateTimeVal& ts_val1, const DateTimeVal& ts_val2) {
return timestamp_diff<WEEK>(ctx, ts_val1, ts_val2);
}
BigIntVal TimestampFunctions::days_diff(
FunctionContext* ctx, const DateTimeVal& ts_val1, const DateTimeVal& ts_val2) {
return timestamp_diff<DAY>(ctx, ts_val1, ts_val2);
}
BigIntVal TimestampFunctions::hours_diff(
FunctionContext* ctx, const DateTimeVal& ts_val1, const DateTimeVal& ts_val2) {
return timestamp_diff<HOUR>(ctx, ts_val1, ts_val2);
}
BigIntVal TimestampFunctions::minutes_diff(
FunctionContext* ctx, const DateTimeVal& ts_val1, const DateTimeVal& ts_val2) {
return timestamp_diff<MINUTE>(ctx, ts_val1, ts_val2);
}
BigIntVal TimestampFunctions::seconds_diff(
FunctionContext* ctx, const DateTimeVal& ts_val1, const DateTimeVal& ts_val2) {
return timestamp_diff<SECOND>(ctx, ts_val1, ts_val2);
}
template <TimeUnit unit>
BigIntVal TimestampFunctions::timestamp_diff(FunctionContext* ctx, const DateTimeVal& ts_val2, const DateTimeVal& ts_val1) {
if (ts_val1.is_null || ts_val2.is_null) {
return BigIntVal::null();
}
DateTimeValue ts_value1 = DateTimeValue::from_datetime_val(ts_val1);
DateTimeValue ts_value2 = DateTimeValue::from_datetime_val(ts_val2);
switch (unit) {
case YEAR: {
int year = (ts_value2.year() - ts_value1.year());
if (year >= 0) {
year -= (ts_value2.to_int64() % 10000000000 - ts_value1.to_int64() % 10000000000) < 0;
} else {
year += (ts_value2.to_int64() % 10000000000 - ts_value1.to_int64() % 10000000000) > 0;
}
return year;
}
case MONTH: {
int month = (ts_value2.year() - ts_value1.year()) * 12 + (ts_value2.month() - ts_value1.month());
if (month >= 0) {
month -= (ts_value2.to_int64() % 100000000 - ts_value1.to_int64() % 100000000) < 0;
} else {
month += (ts_value2.to_int64() % 100000000 - ts_value1.to_int64() % 100000000) > 0;
}
return month;
}
case WEEK: {
int day = ts_value2.daynr() - ts_value1.daynr();
if (day >= 0) {
day -= ts_value2.time_part_diff(ts_value1) < 0;
} else {
day += ts_value2.time_part_diff(ts_value1) > 0;
}
return day / 7;
}
case DAY: {
int day = ts_value2.daynr() - ts_value1.daynr();
if (day >= 0) {
day -= ts_value2.time_part_diff(ts_value1) < 0;
} else {
day += ts_value2.time_part_diff(ts_value1) > 0;
}
return day;
}
case HOUR: {
int64_t second = ts_value2.second_diff(ts_value1);
int64_t hour = second / 60 / 60;
return hour;
}
case MINUTE: {
int64_t second = ts_value2.second_diff(ts_value1);
int64_t minute = second / 60;
return minute;
}
case SECOND: {
int64_t second = ts_value2.second_diff(ts_value1);
return second;
}
default:
return BigIntVal::null();
}
}
StringVal TimestampFunctions::date_format(
FunctionContext* ctx, const DateTimeVal& ts_val, const StringVal& format) {
if (ts_val.is_null || format.is_null) {