diff --git a/src/Functions/toStartOfInterval.cpp b/src/Functions/toStartOfInterval.cpp
index fd472d453b5..c4f60d6d6db 100644
--- a/src/Functions/toStartOfInterval.cpp
+++ b/src/Functions/toStartOfInterval.cpp
@@ -1,6 +1,8 @@
#include
+#include "Common/IntervalKind.h"
#include
#include
+#include "base/types.h"
#include
#include
#include
@@ -220,7 +222,7 @@ private:
if (isDateTime64(time_column_type))
{
- if (!isDateTime64(origin_column.type.get()) && origin_column.column != nullptr)
+ if (origin_column.column != nullptr && !isDateTime64(origin_column.type.get()))
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Datetime argument and origin argument for function {} must have the same type", getName());
const auto * time_column_vec = checkAndGetColumn(time_column_col);
@@ -231,9 +233,8 @@ private:
}
else if (isDateTime(time_column_type))
{
- if (origin_column.column != nullptr)
- if (!isDateTime(origin_column.type.get()))
- throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Datetime argument and origin argument for function {} must have the same type", getName());
+ if (origin_column.column != nullptr && !isDateTime(origin_column.type.get()))
+ throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Datetime argument and origin argument for function {} must have the same type", getName());
const auto * time_column_vec = checkAndGetColumn(time_column_col);
if (time_column_vec)
@@ -241,9 +242,8 @@ private:
}
else if (isDate(time_column_type))
{
- if (origin_column.column != nullptr)
- if (!isDate(origin_column.type.get()))
- throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Datetime argument and origin argument for function {} must have the same type", getName());
+ if (origin_column.column != nullptr && !isDate(origin_column.type.get()))
+ throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Datetime argument and origin argument for function {} must have the same type", getName());
const auto * time_column_vec = checkAndGetColumn(time_column_col);
if (time_column_vec)
@@ -330,19 +330,23 @@ private:
else
{
UInt64 origin = origin_column.column->get64(0);
- std::cerr << "origin: " << origin << std::endl;
- std::cerr << "scale_multiplier: " << scale_multiplier << std::endl;
for (size_t i = 0; i != size; ++i)
{
auto td = time_data[i];
+ result_data[i] = 0;
if (origin > size_t(td))
throw Exception(ErrorCodes::BAD_ARGUMENTS, "The origin must be before the end date/datetime");
+
td -= origin;
- result_data[i] = static_cast(ToStartOfInterval::execute(td, num_units, time_zone, scale_multiplier));
+ auto res = static_cast(ToStartOfInterval::execute(td, num_units, time_zone, scale_multiplier));
+
if (!(unit == IntervalKind::Millisecond || unit == IntervalKind::Microsecond || unit == IntervalKind::Nanosecond) && scale_multiplier != 10)
origin = origin / scale_multiplier;
- result_data[i] += origin;
+ if (unit == IntervalKind::Week || unit == IntervalKind::Month || unit == IntervalKind::Quarter || unit == IntervalKind::Year)
+ result_data[i] = UInt16(origin/86400 + res);
+ else
+ result_data[i] += origin + res;
}
}
diff --git a/tests/queries/0_stateless/02916_to_start_of_interva_with_origin.reference b/tests/queries/0_stateless/02916_to_start_of_interva_with_origin.reference
index 7213925fb64..78e3b117cb8 100644
--- a/tests/queries/0_stateless/02916_to_start_of_interva_with_origin.reference
+++ b/tests/queries/0_stateless/02916_to_start_of_interva_with_origin.reference
@@ -1,15 +1,34 @@
+2023-01-02 14:45:50.917120700
+2023-01-02 14:45:50.910600
+2023-01-02 14:45:50.901
+2023-01-02 14:45:50
+2023-01-02 14:45:30
+2023-01-02 14:44:30
+2023-01-02 14:44:30
+2023-01-06
+2023-03-02
+2023-07-02
+2022-01-02
+2023-01-02 15:45:50.917120700
+2023-01-02 15:45:50.910600
+2023-01-02 15:45:50.901
+2023-01-02 15:45:50
+2023-01-02 15:45:30
+2023-01-02 15:44:30
+2023-01-03 14:44:30
+2023-01-06
+2023-03-02
+2023-07-02
+2022-01-02
2023-03-01 16:55:00
-2023-02-01 16:55:00
-2023-03-01 16:55:00
-2023-02-01 16:55:00
-2023-03-01 16:55:00
+2023-02-01 16:54:33
+2023-03-01 16:54:38
+2023-02-01 16:54:52
+2023-03-01 16:54:16
2023-03-01 16:55:00
2023-02-01 16:55:00
2023-03-01 16:55:00
2023-02-01 16:55:00
2023-03-01 16:55:00
2023-01-02 15:44:30
-2023-01-02 15:44:30
-2023-01-02 14:45:30
-2023-01-02 14:45:30
-2023-01-02
+2023-02-01 16:44:30
diff --git a/tests/queries/0_stateless/02916_to_start_of_interval_with_origin.sql b/tests/queries/0_stateless/02916_to_start_of_interval_with_origin.sql
index 5f5f941047a..390b36a4cf1 100644
--- a/tests/queries/0_stateless/02916_to_start_of_interval_with_origin.sql
+++ b/tests/queries/0_stateless/02916_to_start_of_interval_with_origin.sql
@@ -7,10 +7,10 @@ SELECT toStartOfInterval(toDateTime('2023-01-02 14:45:50'), toIntervalSecond(2),
SELECT toStartOfInterval(toDateTime('2023-01-02 14:45:50'), toIntervalMinute(1), toDateTime('2023-01-02 14:44:30'));
SELECT toStartOfInterval(toDateTime64('2023-01-02 14:45:50', 2), toIntervalHour(1), toDateTime64('2023-01-02 14:44:30', 2));
SELECT toStartOfInterval(toDateTime('2023-01-02 14:45:50'), toIntervalDay(1), toDateTime('2023-01-02 14:44:30'));
-SELECT toStartOfInterval(toDateTime('2023-01-02 14:45:50'), toIntervalWeek(1), toDateTime('2023-01-02 14:44:30'));
-SELECT toStartOfInterval(toDateTime('2023-01-02 14:45:50'), toIntervalMonth(1), toDateTime('2022-01-02 14:44:30'));
-SELECT toStartOfInterval(toDateTime('2023-01-02 14:45:50'), toIntervalQuarter(1), toDateTime('2022-01-02 14:44:30'));
-SELECT toStartOfInterval(toDateTime('2023-01-02 14:45:50'), toIntervalYear(1), toDateTime('2020-01-02 14:44:30'));
+SELECT toStartOfInterval(toDateTime('2023-01-08 14:45:50'), toIntervalWeek(1), toDateTime('2023-01-02 14:44:30'));
+SELECT toStartOfInterval(toDateTime('2023-03-03 14:45:50'), toIntervalMonth(1), toDateTime('2022-01-02 14:44:30'));
+SELECT toStartOfInterval(toDateTime('2023-08-02 14:45:50'), toIntervalQuarter(1), toDateTime('2022-01-02 14:44:30'));
+SELECT toStartOfInterval(toDateTime('2023-01-02 14:45:50'), toIntervalYear(1), toDateTime('2020-01-03 14:44:30'));
SELECT toStartOfInterval(toDateTime64('2023-01-02 14:45:50.917122341', 9), toIntervalNanosecond(10000), toDateTime64('2023-01-02 14:44:30.500600700', 9), 'Europe/Amsterdam');
SELECT toStartOfInterval(toDateTime64('2023-01-02 14:45:50.917122', 6), toIntervalMicrosecond(10000), toDateTime64('2023-01-02 14:44:30.500600', 6), 'Europe/Amsterdam');
@@ -19,15 +19,15 @@ SELECT toStartOfInterval(toDateTime('2023-01-02 14:45:50'), toIntervalSecond(2),
SELECT toStartOfInterval(toDateTime('2023-01-02 14:45:50'), toIntervalMinute(1), toDateTime('2023-01-02 14:44:30'), 'Europe/Amsterdam');
SELECT toStartOfInterval(toDateTime64('2023-01-02 14:45:50', 2), toIntervalHour(1), toDateTime64('2023-01-02 14:44:30', 2), 'Europe/Amsterdam');
SELECT toStartOfInterval(toDateTime('2023-01-02 14:45:50'), toIntervalDay(1), toDateTime('2023-01-02 14:44:30'), 'Europe/Amsterdam');
-SELECT toStartOfInterval(toDateTime('2023-01-02 14:45:50'), toIntervalWeek(1), toDateTime('2023-01-02 14:44:30'), 'Europe/Amsterdam');
-SELECT toStartOfInterval(toDateTime('2023-01-02 14:45:50'), toIntervalMonth(1), toDateTime('2022-01-02 14:44:30'), 'Europe/Amsterdam');
-SELECT toStartOfInterval(toDateTime('2023-01-02 14:45:50'), toIntervalQuarter(1), toDateTime('2022-01-02 14:44:30'), 'Europe/Amsterdam');
-SELECT toStartOfInterval(toDateTime('2023-01-02 14:45:50'), toIntervalYear(1), toDateTime('2020-01-02 14:44:30'), 'Europe/Amsterdam');
+SELECT toStartOfInterval(toDateTime('2023-01-08 14:45:50'), toIntervalWeek(1), toDateTime('2023-01-02 14:44:30'), 'Europe/Amsterdam');
+SELECT toStartOfInterval(toDateTime('2023-03-03 14:45:50'), toIntervalMonth(1), toDateTime('2022-01-02 14:44:30'), 'Europe/Amsterdam');
+SELECT toStartOfInterval(toDateTime('2023-08-02 14:45:50'), toIntervalQuarter(1), toDateTime('2022-01-02 14:44:30'), 'Europe/Amsterdam');
+SELECT toStartOfInterval(toDateTime('2023-01-02 14:45:50'), toIntervalYear(1), toDateTime('2020-01-03 14:44:30'), 'Europe/Amsterdam');
SELECT toStartOfInterval(number % 2 == 0 ? toDateTime64('2023-03-01 15:55:00', 2) : toDateTime64('2023-02-01 15:55:00', 2), toIntervalMinute(1), toDateTime64('2023-01-01 13:55:00', 2), 'Europe/Amsterdam') from numbers(5);
SELECT toStartOfInterval(number % 2 == 0 ? toDateTime('2023-03-01 15:55:00') : toDateTime('2023-02-01 15:55:00'), toIntervalHour(1), toDateTime('2023-01-01 13:55:00'), 'Europe/Amsterdam') from numbers(5);
SELECT toStartOfInterval(materialize(toDateTime('2023-01-02 14:45:50')), toIntervalHour(1), toDateTime('2023-01-02 14:44:30'), 'Europe/Amsterdam');
-SELECT toStartOfInterval(materialize(toDateTime64('2023-02-01 15:45:50', 2)), toIntervalHour(1), toDateTime('2023-01-02 14:44:30'), 'Europe/Amsterdam');
+SELECT toStartOfInterval(materialize(toDateTime64('2023-02-01 15:45:50', 2)), toIntervalHour(1), toDateTime64('2023-01-02 14:44:30', 2), 'Europe/Amsterdam');
SELECT toStartOfInterval(toDate('2023-01-02 14:45:50'), toIntervalSecond(5), toDate32('2023-01-02 14:44:30')); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
SELECT toStartOfInterval(toDate('2023-01-02 14:45:50'), toIntervalMillisecond(12), toDateTime('2023-01-02 14:44:30')); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }