Rollback date_diff changes

This commit is contained in:
Jordi Villar 2024-04-11 15:45:11 +02:00
parent 2cc801e74c
commit a4c3153453
7 changed files with 60 additions and 117 deletions

View File

@ -4386,7 +4386,7 @@ Default value: `ignore`.
## first_day_of_week
The first day of the week assumed by functions [`toStartOfInterval`](../../sql-reference/functions/date-time-functions.md#toStartOfInterval) and [`dateDiff`](../../sql-reference/functions/date-time-functions.md#dateDiff) functions when using weeks as unit.
The first day of the week assumed by [`toStartOfInterval`](../../sql-reference/functions/date-time-functions.md#toStartOfInterval) function when using weeks as unit.
Possible values:

View File

@ -1749,7 +1749,7 @@ Result:
Returns the count of the specified `unit` boundaries crossed between the `startdate` and the `enddate`.
The difference is calculated using relative units, e.g. the difference between `2021-12-29` and `2022-01-01` is 3 days for unit `day` (see [toRelativeDayNum](#torelativedaynum)), 1 month for unit `month` (see [toRelativeMonthNum](#torelativemonthnum)) and 1 year for unit `year` (see [toRelativeYearNum](#torelativeyearnum)).
If unit `week` was specified, `date_diff` assumes by default that weeks start on Monday. You can change this behavior with setting [`first_day_of_week`](../../operations/settings/settings.md/#first-day-of-week)
If unit `week` was specified, `date_diff` assumes that weeks start on Monday. Note that this behavior is different from that of function `toWeek()` in which weeks start by default on Sunday.
For an alternative to `date_diff`, see function `age`.

View File

@ -694,11 +694,11 @@ public:
/// (round down to monday and divide DayNum by 7; we made an assumption,
/// that in domain of the function there was no weeks with any other number of days than 7)
template <typename DateOrTime>
Int32 toRelativeWeekNum(DateOrTime v, UInt8 week_mode = 1) const
Int32 toRelativeWeekNum(DateOrTime v) const
{
const LUTIndex i = toLUTIndex(v);
/// We add 8 to avoid underflow at beginning of unix epoch.
return toDayNum(i + (8 - toDayOfWeek(i, week_mode))) / 7;
return toDayNum(i + (8 - toDayOfWeek(i))) / 7;
}
/// Get year that contains most of the current week. Week begins at monday.

View File

@ -1645,25 +1645,25 @@ struct ToRelativeYearNumImpl
{
static constexpr auto name = "toRelativeYearNum";
static auto execute(Int64 t, const DateLUTImpl & time_zone, UInt8 = 0)
static auto execute(Int64 t, const DateLUTImpl & time_zone)
{
if constexpr (precision_ == ResultPrecision::Extended)
return static_cast<Int16>(time_zone.toYear(t));
else
return static_cast<UInt16>(time_zone.toYear(t));
}
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone, UInt8 = 0)
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toYear(static_cast<time_t>(t));
}
static auto execute(Int32 d, const DateLUTImpl & time_zone, UInt8 = 0)
static auto execute(Int32 d, const DateLUTImpl & time_zone)
{
if constexpr (precision_ == ResultPrecision::Extended)
return static_cast<Int16>(time_zone.toYear(ExtendedDayNum(d)));
else
return static_cast<UInt16>(time_zone.toYear(ExtendedDayNum(d)));
}
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone, UInt8 = 0)
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
{
return time_zone.toYear(DayNum(d));
}
@ -1677,25 +1677,25 @@ struct ToRelativeQuarterNumImpl
{
static constexpr auto name = "toRelativeQuarterNum";
static auto execute(Int64 t, const DateLUTImpl & time_zone, UInt8 = 0)
static auto execute(Int64 t, const DateLUTImpl & time_zone)
{
if constexpr (precision_ == ResultPrecision::Extended)
return static_cast<Int32>(time_zone.toRelativeQuarterNum(t));
else
return static_cast<UInt16>(time_zone.toRelativeQuarterNum(t));
}
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone, UInt8 = 0)
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toRelativeQuarterNum(static_cast<time_t>(t));
}
static auto execute(Int32 d, const DateLUTImpl & time_zone, UInt8 = 0)
static auto execute(Int32 d, const DateLUTImpl & time_zone)
{
if constexpr (precision_ == ResultPrecision::Extended)
return static_cast<Int32>(time_zone.toRelativeQuarterNum(ExtendedDayNum(d)));
else
return static_cast<UInt16>(time_zone.toRelativeQuarterNum(ExtendedDayNum(d)));
}
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone, UInt8 = 0)
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
{
return time_zone.toRelativeQuarterNum(DayNum(d));
}
@ -1709,25 +1709,25 @@ struct ToRelativeMonthNumImpl
{
static constexpr auto name = "toRelativeMonthNum";
static auto execute(Int64 t, const DateLUTImpl & time_zone, UInt8 = 0)
static auto execute(Int64 t, const DateLUTImpl & time_zone)
{
if constexpr (precision_ == ResultPrecision::Extended)
return static_cast<Int32>(time_zone.toRelativeMonthNum(t));
else
return static_cast<UInt16>(time_zone.toRelativeMonthNum(t));
}
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone, UInt8 = 0)
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toRelativeMonthNum(static_cast<time_t>(t));
}
static auto execute(Int32 d, const DateLUTImpl & time_zone, UInt8 = 0)
static auto execute(Int32 d, const DateLUTImpl & time_zone)
{
if constexpr (precision_ == ResultPrecision::Extended)
return static_cast<Int32>(time_zone.toRelativeMonthNum(ExtendedDayNum(d)));
else
return static_cast<UInt16>(time_zone.toRelativeMonthNum(ExtendedDayNum(d)));
}
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone, UInt8 = 0)
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
{
return time_zone.toRelativeMonthNum(DayNum(d));
}
@ -1741,27 +1741,27 @@ struct ToRelativeWeekNumImpl
{
static constexpr auto name = "toRelativeWeekNum";
static auto execute(Int64 t, const DateLUTImpl & time_zone, UInt8 week_mode = 0)
static auto execute(Int64 t, const DateLUTImpl & time_zone)
{
if constexpr (precision_ == ResultPrecision::Extended)
return static_cast<Int32>(time_zone.toRelativeWeekNum(t, week_mode));
return static_cast<Int32>(time_zone.toRelativeWeekNum(t));
else
return static_cast<UInt16>(time_zone.toRelativeWeekNum(t, week_mode));
return static_cast<UInt16>(time_zone.toRelativeWeekNum(t));
}
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone, UInt8 week_mode = 0)
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toRelativeWeekNum(static_cast<time_t>(t), week_mode);
return time_zone.toRelativeWeekNum(static_cast<time_t>(t));
}
static auto execute(Int32 d, const DateLUTImpl & time_zone, UInt8 week_mode = 0)
static auto execute(Int32 d, const DateLUTImpl & time_zone)
{
if constexpr (precision_ == ResultPrecision::Extended)
return static_cast<Int32>(time_zone.toRelativeWeekNum(ExtendedDayNum(d), week_mode));
return static_cast<Int32>(time_zone.toRelativeWeekNum(ExtendedDayNum(d)));
else
return static_cast<UInt16>(time_zone.toRelativeWeekNum(ExtendedDayNum(d), week_mode));
return static_cast<UInt16>(time_zone.toRelativeWeekNum(ExtendedDayNum(d)));
}
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone, UInt8 week_mode = 0)
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
{
return time_zone.toRelativeWeekNum(DayNum(d), week_mode);
return time_zone.toRelativeWeekNum(DayNum(d));
}
static constexpr bool hasPreimage() { return false; }
@ -1773,25 +1773,25 @@ struct ToRelativeDayNumImpl
{
static constexpr auto name = "toRelativeDayNum";
static auto execute(Int64 t, const DateLUTImpl & time_zone, UInt8 = 0)
static auto execute(Int64 t, const DateLUTImpl & time_zone)
{
if constexpr (precision_ == ResultPrecision::Extended)
return static_cast<Int64>(time_zone.toDayNum(t));
else
return static_cast<UInt16>(time_zone.toDayNum(t));
}
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone, UInt8 = 0)
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toDayNum(static_cast<time_t>(t));
}
static auto execute(Int32 d, const DateLUTImpl &, UInt8 = 0)
static auto execute(Int32 d, const DateLUTImpl &)
{
if constexpr (precision_ == ResultPrecision::Extended)
return static_cast<Int32>(static_cast<ExtendedDayNum>(d));
else
return static_cast<UInt16>(static_cast<ExtendedDayNum>(d));
}
static UInt16 execute(UInt16 d, const DateLUTImpl &, UInt8 = 0)
static UInt16 execute(UInt16 d, const DateLUTImpl &)
{
return static_cast<DayNum>(d);
}
@ -1805,28 +1805,28 @@ struct ToRelativeHourNumImpl
{
static constexpr auto name = "toRelativeHourNum";
static auto execute(Int64 t, const DateLUTImpl & time_zone, UInt8 = 0)
static auto execute(Int64 t, const DateLUTImpl & time_zone)
{
if constexpr (precision_ == ResultPrecision::Extended)
return static_cast<Int64>(time_zone.toStableRelativeHourNum(t));
else
return static_cast<UInt32>(time_zone.toRelativeHourNum(t));
}
static UInt32 execute(UInt32 t, const DateLUTImpl & time_zone, UInt8 = 0)
static UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
{
if constexpr (precision_ == ResultPrecision::Extended)
return static_cast<UInt32>(time_zone.toStableRelativeHourNum(static_cast<DateLUTImpl::Time>(t)));
else
return static_cast<UInt32>(time_zone.toRelativeHourNum(static_cast<DateLUTImpl::Time>(t)));
}
static auto execute(Int32 d, const DateLUTImpl & time_zone, UInt8 = 0)
static auto execute(Int32 d, const DateLUTImpl & time_zone)
{
if constexpr (precision_ == ResultPrecision::Extended)
return static_cast<Int64>(time_zone.toStableRelativeHourNum(ExtendedDayNum(d)));
else
return static_cast<UInt32>(time_zone.toRelativeHourNum(ExtendedDayNum(d)));
}
static UInt32 execute(UInt16 d, const DateLUTImpl & time_zone, UInt8 = 0)
static UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
{
if constexpr (precision_ == ResultPrecision::Extended)
return static_cast<UInt32>(time_zone.toStableRelativeHourNum(DayNum(d)));
@ -1843,25 +1843,25 @@ struct ToRelativeMinuteNumImpl
{
static constexpr auto name = "toRelativeMinuteNum";
static auto execute(Int64 t, const DateLUTImpl & time_zone, UInt8 = 0)
static auto execute(Int64 t, const DateLUTImpl & time_zone)
{
if constexpr (precision_ == ResultPrecision::Extended)
return static_cast<Int64>(time_zone.toRelativeMinuteNum(t));
else
return static_cast<UInt32>(time_zone.toRelativeMinuteNum(t));
}
static UInt32 execute(UInt32 t, const DateLUTImpl & time_zone, UInt8 = 0)
static UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return static_cast<UInt32>(time_zone.toRelativeMinuteNum(static_cast<DateLUTImpl::Time>(t)));
}
static auto execute(Int32 d, const DateLUTImpl & time_zone, UInt8 = 0)
static auto execute(Int32 d, const DateLUTImpl & time_zone)
{
if constexpr (precision_ == ResultPrecision::Extended)
return static_cast<Int64>(time_zone.toRelativeMinuteNum(ExtendedDayNum(d)));
else
return static_cast<UInt32>(time_zone.toRelativeMinuteNum(ExtendedDayNum(d)));
}
static UInt32 execute(UInt16 d, const DateLUTImpl & time_zone, UInt8 = 0)
static UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
{
return static_cast<UInt32>(time_zone.toRelativeMinuteNum(DayNum(d)));
}
@ -1875,22 +1875,22 @@ struct ToRelativeSecondNumImpl
{
static constexpr auto name = "toRelativeSecondNum";
static Int64 execute(Int64 t, const DateLUTImpl &, UInt8 = 0)
static Int64 execute(Int64 t, const DateLUTImpl &)
{
return t;
}
static UInt32 execute(UInt32 t, const DateLUTImpl &, UInt8 = 0)
static UInt32 execute(UInt32 t, const DateLUTImpl &)
{
return t;
}
static auto execute(Int32 d, const DateLUTImpl & time_zone, UInt8 = 0)
static auto execute(Int32 d, const DateLUTImpl & time_zone)
{
if constexpr (precision_ == ResultPrecision::Extended)
return static_cast<Int64>(time_zone.fromDayNum(ExtendedDayNum(d)));
else
return static_cast<UInt32>(time_zone.fromDayNum(ExtendedDayNum(d)));
}
static UInt32 execute(UInt16 d, const DateLUTImpl & time_zone, UInt8 = 0)
static UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
{
return static_cast<UInt32>(time_zone.fromDayNum(DayNum(d)));
}
@ -1904,7 +1904,7 @@ struct ToRelativeSubsecondNumImpl
{
static constexpr auto name = "toRelativeSubsecondNumImpl";
static Int64 execute(const DateTime64 & t, const DateTime64::NativeType scale, const DateLUTImpl &, UInt8 = 0)
static Int64 execute(const DateTime64 & t, const DateTime64::NativeType scale, const DateLUTImpl &)
{
static_assert(
scale_multiplier == millisecond_multiplier || scale_multiplier == microsecond_multiplier || scale_multiplier == nanosecond_multiplier);
@ -1914,15 +1914,15 @@ struct ToRelativeSubsecondNumImpl
return t.value / (scale / scale_multiplier);
return t.value * (scale_multiplier / scale);
}
static Int64 execute(UInt32 t, const DateLUTImpl &, UInt8 = 0)
static Int64 execute(UInt32 t, const DateLUTImpl &)
{
return t * scale_multiplier;
}
static Int64 execute(Int32 d, const DateLUTImpl & time_zone, UInt8 = 0)
static Int64 execute(Int32 d, const DateLUTImpl & time_zone)
{
return static_cast<Int64>(time_zone.fromDayNum(ExtendedDayNum(d))) * scale_multiplier;
}
static Int64 execute(UInt16 d, const DateLUTImpl & time_zone, UInt8 = 0)
static Int64 execute(UInt16 d, const DateLUTImpl & time_zone)
{
return static_cast<Int64>(time_zone.fromDayNum(DayNum(d)) * scale_multiplier);
}

View File

@ -1,25 +1,20 @@
#include <Columns/ColumnDecimal.h>
#include <Columns/ColumnString.h>
#include <Columns/ColumnsDateTime.h>
#include <Columns/ColumnsNumber.h>
#include <Common/IntervalKind.h>
#include <Core/SettingsEnums.h>
#include <DataTypes/DataTypeDateTime.h>
#include <DataTypes/DataTypeDateTime64.h>
#include <DataTypes/DataTypesNumber.h>
#include <Functions/DateTimeTransforms.h>
#include <Common/IntervalKind.h>
#include <Columns/ColumnString.h>
#include <Columns/ColumnsDateTime.h>
#include <Columns/ColumnsNumber.h>
#include <Columns/ColumnDecimal.h>
#include <Formats/FormatSettings.h>
#include <Functions/IFunction.h>
#include <Functions/FunctionHelpers.h>
#include <Functions/FunctionFactory.h>
#include <Functions/extractTimeZoneFromFunctionArguments.h>
#include <Functions/FunctionFactory.h>
#include <Functions/FunctionHelpers.h>
#include <Functions/IFunction.h>
#include <Functions/DateTimeTransforms.h>
#include <Functions/TransformDateTime64.h>
#include <Functions/extractTimeZoneFromFunctionArguments.h>
#include <IO/WriteHelpers.h>
#include <Interpreters/Context.h>
#include <base/find_symbols.h>
@ -46,10 +41,7 @@ class DateDiffImpl
public:
using ColumnDateTime64 = ColumnDecimal<DateTime64>;
DateDiffImpl(const String & name_, FirstDayOfWeek first_day_of_week_)
: name(name_)
, first_day_of_week(first_day_of_week_)
{}
explicit DateDiffImpl(const String & name_) : name(name_) {}
template <typename Transform>
void dispatchForColumns(
@ -176,12 +168,8 @@ public:
Int64 calculate(const TransformX & transform_x, const TransformY & transform_y, T1 x, T2 y, const DateLUTImpl & timezone_x, const DateLUTImpl & timezone_y) const
{
if constexpr (is_diff)
{
const UInt8 week_mode = (first_day_of_week == FirstDayOfWeek::Monday) ? 0 : 3;
return static_cast<Int64>(transform_y.execute(y, timezone_y, week_mode))
- static_cast<Int64>(transform_x.execute(x, timezone_x, week_mode));
}
return static_cast<Int64>(transform_y.execute(y, timezone_y))
- static_cast<Int64>(transform_x.execute(x, timezone_x));
else
{
auto res = static_cast<Int64>(transform_y.execute(y, timezone_y))
@ -324,7 +312,6 @@ public:
}
private:
String name;
const FirstDayOfWeek first_day_of_week;
};
@ -343,12 +330,7 @@ class FunctionDateDiff : public IFunction
{
public:
static constexpr auto name = is_relative ? "dateDiff" : "age";
static FunctionPtr create(ContextPtr context) { return std::make_shared<FunctionDateDiff>(context); }
explicit FunctionDateDiff(ContextPtr context)
: impl(name, context->getSettingsRef().first_day_of_week)
{
}
static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionDateDiff>(); }
String getName() const override
{
@ -441,7 +423,7 @@ public:
return res;
}
private:
DateDiffImpl<is_relative> impl;
DateDiffImpl<is_relative> impl{name};
};
@ -501,7 +483,7 @@ public:
return res;
}
private:
DateDiffImpl<true> impl{name, FirstDayOfWeek::Monday};
DateDiffImpl<true> impl{name};
};
}

View File

@ -2,7 +2,3 @@
2024-01-02 00:00:00 2024-01-01 2023-12-25
2024-01-02 00:00:00 2024-01-01 2023-12-25
2024-01-02 00:00:00 2023-12-31 2023-12-24
-- date_diff
2023-01-22 00:00:00 2023-01-23 00:00:00 2023-01-24 00:00:00 0 1 0 0 1
2023-01-22 00:00:00 2023-01-23 00:00:00 2023-01-24 00:00:00 0 1 0 0 1
2023-01-22 00:00:00 2023-01-23 00:00:00 2023-01-24 00:00:00 0 0 0 0 1

View File

@ -19,38 +19,3 @@ SELECT
toStartOfInterval(dt, INTERVAL 1 WEEK), -- Sunday, Dec 31
toStartOfInterval(dt, INTERVAL 2 WEEK) -- Sunday, Dec 24
SETTINGS first_day_of_week = 'Sunday';
SELECT '-- date_diff';
-- default behavior
SELECT
toDateTime('2023-01-22 00:00:00', 'UTC') sunday,
toDateTime('2023-01-23 00:00:00', 'UTC') monday,
toDateTime('2023-01-24 00:00:00', 'UTC') tuesday,
dateDiff('week', monday, tuesday),
dateDiff('week', sunday, monday),
age('week', monday, tuesday),
age('week', sunday, monday),
age('week', sunday, monday + toIntervalDay(10));
SELECT
toDateTime('2023-01-22 00:00:00', 'UTC') sunday,
toDateTime('2023-01-23 00:00:00', 'UTC') monday,
toDateTime('2023-01-24 00:00:00', 'UTC') tuesday,
dateDiff('week', monday, tuesday),
dateDiff('week', sunday, monday),
age('week', monday, tuesday),
age('week', sunday, monday),
age('week', sunday, monday + toIntervalDay(10))
SETTINGS first_day_of_week = 'Monday';
SELECT
toDateTime('2023-01-22 00:00:00', 'UTC') sunday,
toDateTime('2023-01-23 00:00:00', 'UTC') monday,
toDateTime('2023-01-24 00:00:00', 'UTC') tuesday,
dateDiff('week', monday, tuesday),
dateDiff('week', sunday, monday),
age('week', monday, tuesday),
age('week', sunday, monday),
age('week', sunday, monday + toIntervalDay(10))
SETTINGS first_day_of_week = 'Sunday';