mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-25 00:52:02 +00:00
Merge pull request #34394 from holadepo/last_day
Add toLastDayOfMonth function
This commit is contained in:
commit
d9e5ca2119
@ -393,6 +393,13 @@ This is a generalization of other functions named `toStartOf*`. For example,
|
||||
`toStartOfInterval(t, INTERVAL 1 day)` returns the same as `toStartOfDay(t)`,
|
||||
`toStartOfInterval(t, INTERVAL 15 minute)` returns the same as `toStartOfFifteenMinutes(t)` etc.
|
||||
|
||||
## toLastDayOfMonth {#toLastDayOfMonth}
|
||||
|
||||
Rounds up a date or date with time to the last day of the month.
|
||||
Returns the date.
|
||||
|
||||
Alias: `LAST_DAY`.
|
||||
|
||||
## toTime {#totime}
|
||||
|
||||
Converts a date with time to a certain fixed date, while preserving the time.
|
||||
|
@ -360,6 +360,27 @@ public:
|
||||
return toDayNum(LUTIndex(i - (lut[i].day_of_month - 1)));
|
||||
}
|
||||
|
||||
/// Round up to last day of month.
|
||||
template <typename DateOrTime>
|
||||
inline Time toLastDayOfMonth(DateOrTime v) const
|
||||
{
|
||||
const LUTIndex i = toLUTIndex(v);
|
||||
if constexpr (std::is_unsigned_v<DateOrTime> || std::is_same_v<DateOrTime, DayNum>)
|
||||
return lut_saturated[i - lut[i].day_of_month + lut[i].days_in_month].date;
|
||||
else
|
||||
return lut[i - lut[i].day_of_month + lut[i].days_in_month].date;
|
||||
}
|
||||
|
||||
template <typename DateOrTime>
|
||||
inline auto toLastDayNumOfMonth(DateOrTime v) const
|
||||
{
|
||||
const LUTIndex i = toLUTIndex(v);
|
||||
if constexpr (std::is_unsigned_v<DateOrTime> || std::is_same_v<DateOrTime, DayNum>)
|
||||
return toDayNum(LUTIndexWithSaturation(i - lut[i].day_of_month + lut[i].days_in_month));
|
||||
else
|
||||
return toDayNum(LUTIndex(i - lut[i].day_of_month + lut[i].days_in_month));
|
||||
}
|
||||
|
||||
/// Round down to start of quarter.
|
||||
template <typename DateOrTime>
|
||||
inline auto toFirstDayNumOfQuarter(DateOrTime v) const
|
||||
|
@ -146,6 +146,8 @@ TEST(DateLUTTest, TimeValuesInMiddleOfRange)
|
||||
EXPECT_EQ(lut.addYears(time, 10), 1884270011 /*time_t*/);
|
||||
EXPECT_EQ(lut.timeToString(time), "2019-09-16 19:20:11" /*std::string*/);
|
||||
EXPECT_EQ(lut.dateToString(time), "2019-09-16" /*std::string*/);
|
||||
EXPECT_EQ(lut.toLastDayOfMonth(time), 1569790800 /*time_t*/);
|
||||
EXPECT_EQ(lut.toLastDayNumOfMonth(time), DayNum(18169) /*DayNum*/);
|
||||
}
|
||||
|
||||
|
||||
@ -206,6 +208,8 @@ TEST(DateLUTTest, TimeValuesAtLeftBoderOfRange)
|
||||
EXPECT_EQ(lut.addYears(time, 10), 315532800 /*time_t*/);
|
||||
EXPECT_EQ(lut.timeToString(time), "1970-01-01 00:00:00" /*std::string*/);
|
||||
EXPECT_EQ(lut.dateToString(time), "1970-01-01" /*std::string*/);
|
||||
EXPECT_EQ(lut.toLastDayOfMonth(time), 2592000 /*time_t*/);
|
||||
EXPECT_EQ(lut.toLastDayNumOfMonth(time), DayNum(30) /*DayNum*/);
|
||||
}
|
||||
|
||||
TEST(DateLUTTest, TimeValuesAtRightBoderOfRangeOfOldLUT)
|
||||
@ -225,7 +229,7 @@ TEST(DateLUTTest, TimeValuesAtRightBoderOfRangeOfOldLUT)
|
||||
|
||||
EXPECT_EQ(lut.toFirstDayOfWeek(time), 4293820800 /*time_t*/);
|
||||
EXPECT_EQ(lut.toFirstDayNumOfWeek(time), DayNum(49697));
|
||||
EXPECT_EQ(lut.toFirstDayOfMonth(time), 4291747200 /*time_t*/); // 2016-01-01
|
||||
EXPECT_EQ(lut.toFirstDayOfMonth(time), 4291747200 /*time_t*/); // 2106-01-01
|
||||
EXPECT_EQ(lut.toFirstDayNumOfMonth(time), DayNum(49673));
|
||||
EXPECT_EQ(lut.toFirstDayNumOfQuarter(time), DayNum(49673) /*DayNum*/);
|
||||
EXPECT_EQ(lut.toFirstDayOfQuarter(time), 4291747200 /*time_t*/);
|
||||
@ -268,6 +272,8 @@ TEST(DateLUTTest, TimeValuesAtRightBoderOfRangeOfOldLUT)
|
||||
|
||||
EXPECT_EQ(lut.timeToString(time), "2106-01-31 01:17:53" /*std::string*/);
|
||||
EXPECT_EQ(lut.dateToString(time), "2106-01-31" /*std::string*/);
|
||||
EXPECT_EQ(lut.toLastDayOfMonth(time), 4294339200 /*time_t*/); // 2106-01-01
|
||||
EXPECT_EQ(lut.toLastDayNumOfMonth(time), DayNum(49703));
|
||||
}
|
||||
|
||||
|
||||
|
@ -179,6 +179,30 @@ struct ToStartOfMonthImpl
|
||||
using FactorTransform = ZeroTransform;
|
||||
};
|
||||
|
||||
struct ToLastDayOfMonthImpl
|
||||
{
|
||||
static constexpr auto name = "toLastDayOfMonth";
|
||||
|
||||
static inline UInt16 execute(Int64 t, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toLastDayNumOfMonth(time_zone.toDayNum(t));
|
||||
}
|
||||
static inline UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toLastDayNumOfMonth(time_zone.toDayNum(t));
|
||||
}
|
||||
static inline UInt16 execute(Int32 d, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toLastDayNumOfMonth(ExtendedDayNum(d));
|
||||
}
|
||||
static inline UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
|
||||
{
|
||||
return time_zone.toLastDayNumOfMonth(DayNum(d));
|
||||
}
|
||||
|
||||
using FactorTransform = ZeroTransform;
|
||||
};
|
||||
|
||||
struct ToStartOfQuarterImpl
|
||||
{
|
||||
static constexpr auto name = "toStartOfQuarter";
|
||||
|
@ -23,6 +23,7 @@ void registerFunctionToISOYear(FunctionFactory &);
|
||||
void registerFunctionToCustomWeek(FunctionFactory &);
|
||||
void registerFunctionToModifiedJulianDay(FunctionFactory &);
|
||||
void registerFunctionToStartOfMonth(FunctionFactory &);
|
||||
void registerFunctionToLastDayOfMonth(FunctionFactory &);
|
||||
void registerFunctionToStartOfQuarter(FunctionFactory &);
|
||||
void registerFunctionToStartOfYear(FunctionFactory &);
|
||||
void registerFunctionToStartOfMinute(FunctionFactory &);
|
||||
@ -100,6 +101,7 @@ void registerFunctionsDateTime(FunctionFactory & factory)
|
||||
registerFunctionToCustomWeek(factory);
|
||||
registerFunctionToModifiedJulianDay(factory);
|
||||
registerFunctionToStartOfMonth(factory);
|
||||
registerFunctionToLastDayOfMonth(factory);
|
||||
registerFunctionToStartOfQuarter(factory);
|
||||
registerFunctionToStartOfYear(factory);
|
||||
registerFunctionToStartOfNanosecond(factory);
|
||||
|
21
src/Functions/toLastDayOfMonth.cpp
Normal file
21
src/Functions/toLastDayOfMonth.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include <Functions/FunctionFactory.h>
|
||||
#include <Functions/DateTimeTransforms.h>
|
||||
#include <Functions/FunctionDateOrDateTimeToSomething.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
using FunctionToLastDayOfMonth = FunctionDateOrDateTimeToSomething<DataTypeDate, ToLastDayOfMonthImpl>;
|
||||
|
||||
void registerFunctionToLastDayOfMonth(FunctionFactory & factory)
|
||||
{
|
||||
factory.registerFunction<FunctionToLastDayOfMonth>();
|
||||
|
||||
/// MySQL compatibility alias.
|
||||
factory.registerFunction<FunctionToLastDayOfMonth>("LAST_DAY", FunctionFactory::CaseInsensitive);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,7 @@
|
||||
2021-09-30 2021-09-30 2021-09-30
|
||||
2021-03-31 2021-03-31 2021-03-31
|
||||
2021-02-28 2021-02-28 2021-02-28
|
||||
2020-02-29 2020-02-29 2020-02-29
|
||||
2021-12-31 2021-12-31 2021-12-31
|
||||
2020-12-31 2020-12-31 2020-12-31
|
||||
2020-12-31 2020-12-31
|
46
tests/queries/0_stateless/02251_last_day_of_month.sql
Normal file
46
tests/queries/0_stateless/02251_last_day_of_month.sql
Normal file
@ -0,0 +1,46 @@
|
||||
-- month with 30 days
|
||||
WITH
|
||||
toDate('2021-09-12') AS date_value,
|
||||
toDateTime('2021-09-12 11:22:33') AS date_time_value,
|
||||
toDateTime64('2021-09-12 11:22:33', 3) AS date_time_64_value
|
||||
SELECT toLastDayOfMonth(date_value), toLastDayOfMonth(date_time_value), toLastDayOfMonth(date_time_64_value);
|
||||
|
||||
-- month with 31 days
|
||||
WITH
|
||||
toDate('2021-03-12') AS date_value,
|
||||
toDateTime('2021-03-12 11:22:33') AS date_time_value,
|
||||
toDateTime64('2021-03-12 11:22:33', 3) AS date_time_64_value
|
||||
SELECT toLastDayOfMonth(date_value), toLastDayOfMonth(date_time_value), toLastDayOfMonth(date_time_64_value);
|
||||
|
||||
-- non leap year February
|
||||
WITH
|
||||
toDate('2021-02-12') AS date_value,
|
||||
toDateTime('2021-02-12 11:22:33') AS date_time_value,
|
||||
toDateTime64('2021-02-12 11:22:33', 3) AS date_time_64_value
|
||||
SELECT toLastDayOfMonth(date_value), toLastDayOfMonth(date_time_value), toLastDayOfMonth(date_time_64_value);
|
||||
|
||||
-- leap year February
|
||||
WITH
|
||||
toDate('2020-02-12') AS date_value,
|
||||
toDateTime('2020-02-12 11:22:33') AS date_time_value,
|
||||
toDateTime64('2020-02-12 11:22:33', 3) AS date_time_64_value
|
||||
SELECT toLastDayOfMonth(date_value), toLastDayOfMonth(date_time_value), toLastDayOfMonth(date_time_64_value);
|
||||
|
||||
-- December 31 for non-leap year
|
||||
WITH
|
||||
toDate('2021-12-12') AS date_value,
|
||||
toDateTime('2021-12-12 11:22:33') AS date_time_value,
|
||||
toDateTime64('2021-12-12 11:22:33', 3) AS date_time_64_value
|
||||
SELECT toLastDayOfMonth(date_value), toLastDayOfMonth(date_time_value), toLastDayOfMonth(date_time_64_value);
|
||||
|
||||
-- December 31 for leap year
|
||||
WITH
|
||||
toDate('2020-12-12') AS date_value,
|
||||
toDateTime('2020-12-12 11:22:33') AS date_time_value,
|
||||
toDateTime64('2020-12-12 11:22:33', 3) AS date_time_64_value
|
||||
SELECT toLastDayOfMonth(date_value), toLastDayOfMonth(date_time_value), toLastDayOfMonth(date_time_64_value);
|
||||
|
||||
-- aliases
|
||||
WITH
|
||||
toDate('2020-12-12') AS date_value
|
||||
SELECT last_day(date_value), LAST_DAY(date_value);
|
@ -229,7 +229,7 @@ std::map<std::string, FuncRet> func_to_return_type = {
|
||||
{"torelativeweeknum", FuncRet(Type::i, "")}, {"torelativedaynum", FuncRet(Type::i, "")}, {"torelativehournum", FuncRet(Type::i, "")},
|
||||
{"torelativeminutenum", FuncRet(Type::i, "")}, {"torelativesecondsnum", FuncRet(Type::i, "")}, {"datediff", FuncRet(Type::d | Type::dt, "")},
|
||||
{"formatdatetime", FuncRet(Type::s, "")}, {"now", FuncRet(Type::dt | Type::d, "now()")}, {"today", FuncRet(Type::d | Type::dt, "today()")},
|
||||
{"yesterday", FuncRet(Type::d | Type::dt, "yesterday()")}
|
||||
{"yesterday", FuncRet(Type::d | Type::dt, "yesterday()")}, {"tolastdayofmonth", FuncRet(Type::dt | Type::d, "")}
|
||||
};
|
||||
|
||||
std::set<std::string> func_args_same_types = {
|
||||
@ -253,7 +253,7 @@ std::map<std::string, ColumnType> func_to_param_type = {
|
||||
{"tostartofinterval", Type::d | Type::dt}, {"totime", Type::d | Type::dt}, {"torelativehonthnum", Type::d | Type::dt},
|
||||
{"torelativeweeknum", Type::d | Type::dt}, {"torelativedaynum", Type::d | Type::dt}, {"torelativehournum", Type::d | Type::dt},
|
||||
{"torelativeminutenum", Type::d | Type::dt}, {"torelativesecondnum", Type::d | Type::dt}, {"datediff", Type::d | Type::dt},
|
||||
{"formatdatetime", Type::dt}
|
||||
{"formatdatetime", Type::dt}, {"tolastdayofmonth", Type::d | Type::dt}
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user