ClickHouse/src/Functions/DateTimeTransforms.h

1992 lines
65 KiB
C++
Raw Normal View History

#pragma once
2021-05-06 23:17:39 +00:00
2021-10-02 07:13:14 +00:00
#include <base/types.h>
2019-09-26 15:12:40 +00:00
#include <Core/DecimalFunctions.h>
#include <Common/Exception.h>
#include <Common/DateLUTImpl.h>
#include <Common/DateLUT.h>
2023-09-29 16:52:48 +00:00
#include <Common/IntervalKind.h>
#include <Columns/ColumnNullable.h>
#include <Columns/ColumnsNumber.h>
#include <Columns/ColumnVector.h>
2019-09-26 15:12:40 +00:00
#include <Columns/ColumnDecimal.h>
#include <Functions/FunctionHelpers.h>
2021-05-17 07:30:42 +00:00
#include <Functions/IFunction.h>
#include <Functions/extractTimeZoneFromFunctionArguments.h>
#include <DataTypes/DataTypeDateTime.h>
#include <DataTypes/DataTypeDateTime64.h>
2021-05-06 23:17:39 +00:00
namespace DB
{
static constexpr auto microsecond_multiplier = 1000000;
static constexpr auto millisecond_multiplier = 1000;
namespace ErrorCodes
{
extern const int CANNOT_CONVERT_TYPE;
2023-10-08 10:46:28 +00:00
extern const int DECIMAL_OVERFLOW;
extern const int ILLEGAL_COLUMN;
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
}
/** Transformations.
* Represents two functions - from datetime (UInt32) and from date (UInt16).
*
* Also, the "factor transformation" F is defined for the T transformation.
* This is a transformation of F such that its value identifies the region of monotonicity for T
* (for a fixed value of F, the transformation T is monotonic).
*
* Or, figuratively, if T is similar to taking the remainder of division, then F is similar to division.
*
* Example: for transformation T "get the day number in the month" (2015-02-03 -> 3),
* factor-transformation F is "round to the nearest month" (2015-02-03 -> 2015-02-01).
*/
[[noreturn]] void throwDateIsNotSupported(const char * name);
[[noreturn]] void throwDateTimeIsNotSupported(const char * name);
[[noreturn]] void throwDate32IsNotSupported(const char * name);
2022-09-22 07:15:03 +00:00
/// This factor transformation will say that the function is monotone everywhere.
struct ZeroTransform
{
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int64, const DateLUTImpl &) { return 0; }
static UInt16 execute(UInt32, const DateLUTImpl &) { return 0; }
static UInt16 execute(Int32, const DateLUTImpl &) { return 0; }
static UInt16 execute(UInt16, const DateLUTImpl &) { return 0; }
};
struct ToDateImpl
{
static constexpr auto name = "toDate";
2023-09-09 16:48:17 +00:00
static UInt16 execute(const DecimalUtils::DecimalComponents<DateTime64> & t, const DateLUTImpl & time_zone)
2023-03-13 10:10:05 +00:00
{
return static_cast<UInt16>(time_zone.toDayNum(t.whole));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int64 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return UInt16(time_zone.toDayNum(t));
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return UInt16(time_zone.toDayNum(t));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int32, const DateLUTImpl &)
{
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt16 d, const DateLUTImpl &)
{
return d;
}
2023-09-09 16:48:17 +00:00
static DecimalUtils::DecimalComponents<DateTime64> executeExtendedResult(const DecimalUtils::DecimalComponents<DateTime64> & t, const DateLUTImpl & time_zone)
2023-03-13 10:10:05 +00:00
{
return {time_zone.toDayNum(t.whole), 0};
}
2021-07-15 11:40:45 +00:00
using FactorTransform = ZeroTransform;
};
struct ToDate32Impl
{
static constexpr auto name = "toDate32";
2023-09-09 16:48:17 +00:00
static Int32 execute(Int64 t, const DateLUTImpl & time_zone)
2021-07-15 11:40:45 +00:00
{
return Int32(time_zone.toDayNum(t));
}
2023-09-09 16:48:17 +00:00
static Int32 execute(UInt32 t, const DateLUTImpl & time_zone)
2021-07-15 11:40:45 +00:00
{
2021-11-08 07:19:31 +00:00
/// Don't saturate.
return Int32(time_zone.toDayNum<Int64>(t));
2021-07-15 11:40:45 +00:00
}
2023-09-09 16:48:17 +00:00
static Int32 execute(Int32 d, const DateLUTImpl &)
2021-07-15 11:40:45 +00:00
{
return d;
}
2023-09-09 16:48:17 +00:00
static Int32 execute(UInt16 d, const DateLUTImpl &)
2021-07-15 11:40:45 +00:00
{
return d;
}
using FactorTransform = ZeroTransform;
};
struct ToStartOfDayImpl
{
static constexpr auto name = "toStartOfDay";
2023-09-09 16:48:17 +00:00
static UInt32 execute(const DecimalUtils::DecimalComponents<DateTime64> & t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return static_cast<UInt32>(time_zone.toDate(static_cast<time_t>(t.whole)));
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return static_cast<UInt32>(time_zone.toDate(t));
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(Int32 d, const DateLUTImpl & time_zone)
{
return static_cast<UInt32>(time_zone.toDate(ExtendedDayNum(d)));
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
{
return static_cast<UInt32>(time_zone.toDate(DayNum(d)));
}
2023-09-09 16:48:17 +00:00
static DecimalUtils::DecimalComponents<DateTime64> executeExtendedResult(const DecimalUtils::DecimalComponents<DateTime64> & t, const DateLUTImpl & time_zone)
2022-09-22 09:19:22 +00:00
{
return {time_zone.toDate(t.whole), 0};
}
2023-09-09 16:48:17 +00:00
static Int64 executeExtendedResult(Int32 d, const DateLUTImpl & time_zone)
2022-09-22 09:19:22 +00:00
{
return time_zone.fromDayNum(ExtendedDayNum(d)) * DecimalUtils::scaleMultiplier<DateTime64>(DataTypeDateTime64::default_scale);
2022-09-22 09:19:22 +00:00
}
using FactorTransform = ZeroTransform;
};
struct ToMondayImpl
{
static constexpr auto name = "toMonday";
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int64 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
//return time_zone.toFirstDayNumOfWeek(time_zone.toDayNum(t));
return time_zone.toFirstDayNumOfWeek(t);
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
{
//return time_zone.toFirstDayNumOfWeek(time_zone.toDayNum(t));
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
return time_zone.toFirstDayNumOfWeek(t);
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int32 d, const DateLUTImpl & time_zone)
{
return time_zone.toFirstDayNumOfWeek(ExtendedDayNum(d));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
{
2021-11-08 07:19:31 +00:00
return time_zone.toFirstDayNumOfWeek(DayNum(d));
}
2023-09-09 16:48:17 +00:00
static Int64 executeExtendedResult(Int64 t, const DateLUTImpl & time_zone)
{
return time_zone.toFirstDayNumOfWeek(time_zone.toDayNum(t));
}
2023-09-09 16:48:17 +00:00
static Int32 executeExtendedResult(Int32 d, const DateLUTImpl & time_zone)
{
return time_zone.toFirstDayNumOfWeek(ExtendedDayNum(d));
}
using FactorTransform = ZeroTransform;
};
struct ToStartOfMonthImpl
{
static constexpr auto name = "toStartOfMonth";
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int64 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return time_zone.toFirstDayNumOfMonth(time_zone.toDayNum(t));
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toFirstDayNumOfMonth(time_zone.toDayNum(t));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int32 d, const DateLUTImpl & time_zone)
{
return time_zone.toFirstDayNumOfMonth(ExtendedDayNum(d));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
{
2021-11-08 07:19:31 +00:00
return time_zone.toFirstDayNumOfMonth(DayNum(d));
}
2023-09-09 16:48:17 +00:00
static Int64 executeExtendedResult(Int64 t, const DateLUTImpl & time_zone)
{
return time_zone.toFirstDayNumOfMonth(time_zone.toDayNum(t));
}
2023-09-09 16:48:17 +00:00
static Int32 executeExtendedResult(Int32 d, const DateLUTImpl & time_zone)
{
return time_zone.toFirstDayNumOfMonth(ExtendedDayNum(d));
}
using FactorTransform = ZeroTransform;
};
2022-02-07 20:38:36 +00:00
struct ToLastDayOfMonthImpl
{
static constexpr auto name = "toLastDayOfMonth";
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int64 t, const DateLUTImpl & time_zone)
2022-02-07 20:38:36 +00:00
{
return time_zone.toLastDayNumOfMonth(time_zone.toDayNum(t));
2022-02-07 20:38:36 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
2022-02-07 20:38:36 +00:00
{
return time_zone.toLastDayNumOfMonth(time_zone.toDayNum(t));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int32 d, const DateLUTImpl & time_zone)
2022-02-07 20:38:36 +00:00
{
return time_zone.toLastDayNumOfMonth(ExtendedDayNum(d));
2022-02-07 20:38:36 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
2022-02-07 20:38:36 +00:00
{
return time_zone.toLastDayNumOfMonth(DayNum(d));
2022-02-07 20:38:36 +00:00
}
2023-09-09 16:48:17 +00:00
static Int64 executeExtendedResult(Int64 t, const DateLUTImpl & time_zone)
{
return time_zone.toLastDayNumOfMonth(time_zone.toDayNum(t));
}
2023-09-09 16:48:17 +00:00
static Int32 executeExtendedResult(Int32 d, const DateLUTImpl & time_zone)
{
return time_zone.toLastDayNumOfMonth(ExtendedDayNum(d));
}
2022-02-07 20:38:36 +00:00
using FactorTransform = ZeroTransform;
};
struct ToStartOfQuarterImpl
{
static constexpr auto name = "toStartOfQuarter";
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int64 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return time_zone.toFirstDayNumOfQuarter(time_zone.toDayNum(t));
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toFirstDayNumOfQuarter(time_zone.toDayNum(t));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int32 d, const DateLUTImpl & time_zone)
{
return time_zone.toFirstDayNumOfQuarter(ExtendedDayNum(d));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
{
2021-11-08 07:19:31 +00:00
return time_zone.toFirstDayNumOfQuarter(DayNum(d));
}
2023-09-09 16:48:17 +00:00
static Int64 executeExtendedResult(Int64 t, const DateLUTImpl & time_zone)
{
return time_zone.toFirstDayNumOfQuarter(time_zone.toDayNum(t));
}
2023-09-09 16:48:17 +00:00
static Int32 executeExtendedResult(Int32 d, const DateLUTImpl & time_zone)
{
return time_zone.toFirstDayNumOfQuarter(ExtendedDayNum(d));
}
using FactorTransform = ZeroTransform;
};
struct ToStartOfYearImpl
{
static constexpr auto name = "toStartOfYear";
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int64 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return time_zone.toFirstDayNumOfYear(time_zone.toDayNum(t));
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toFirstDayNumOfYear(time_zone.toDayNum(t));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int32 d, const DateLUTImpl & time_zone)
{
return time_zone.toFirstDayNumOfYear(ExtendedDayNum(d));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
{
2021-11-08 07:19:31 +00:00
return time_zone.toFirstDayNumOfYear(DayNum(d));
}
2023-09-09 16:48:17 +00:00
static Int64 executeExtendedResult(Int64 t, const DateLUTImpl & time_zone)
{
return time_zone.toFirstDayNumOfYear(time_zone.toDayNum(t));
}
2023-09-09 16:48:17 +00:00
static Int32 executeExtendedResult(Int32 d, const DateLUTImpl & time_zone)
{
return time_zone.toFirstDayNumOfYear(ExtendedDayNum(d));
}
using FactorTransform = ZeroTransform;
};
2023-09-29 16:52:48 +00:00
template <IntervalKind::Kind unit>
struct ToStartOfInterval;
static constexpr auto TO_START_OF_INTERVAL_NAME = "toStartOfInterval";
template <>
struct ToStartOfInterval<IntervalKind::Nanosecond>
{
2023-10-08 14:26:31 +00:00
static UInt32 execute(UInt16, Int64, const DateLUTImpl &, Int64)
2023-09-29 16:52:48 +00:00
{
throwDateIsNotSupported(TO_START_OF_INTERVAL_NAME);
}
2023-10-08 14:26:31 +00:00
static UInt32 execute(Int32, Int64, const DateLUTImpl &, Int64)
2023-09-29 16:52:48 +00:00
{
throwDateIsNotSupported(TO_START_OF_INTERVAL_NAME);
}
2023-10-08 14:26:31 +00:00
static UInt32 execute(UInt32, Int64, const DateLUTImpl &, Int64)
2023-09-29 16:52:48 +00:00
{
throwDateTimeIsNotSupported(TO_START_OF_INTERVAL_NAME);
}
2023-10-08 14:26:31 +00:00
static Int64 execute(Int64 t, Int64 nanoseconds, const DateLUTImpl &, Int64 scale_multiplier)
2023-09-29 16:52:48 +00:00
{
if (scale_multiplier < 1000000000)
{
Int64 t_nanoseconds = 0;
if (common::mulOverflow(t, (static_cast<Int64>(1000000000) / scale_multiplier), t_nanoseconds))
throw DB::Exception(ErrorCodes::DECIMAL_OVERFLOW, "Numeric overflow");
if (t >= 0) [[likely]]
return t_nanoseconds / nanoseconds * nanoseconds;
else
return ((t_nanoseconds + 1) / nanoseconds - 1) * nanoseconds;
}
else
if (t >= 0) [[likely]]
return t / nanoseconds * nanoseconds;
else
return ((t + 1) / nanoseconds - 1) * nanoseconds;
}
};
template <>
struct ToStartOfInterval<IntervalKind::Microsecond>
{
2023-10-08 14:26:31 +00:00
static UInt32 execute(UInt16, Int64, const DateLUTImpl &, Int64)
2023-09-29 16:52:48 +00:00
{
throwDateIsNotSupported(TO_START_OF_INTERVAL_NAME);
}
2023-10-08 14:26:31 +00:00
static UInt32 execute(Int32, Int64, const DateLUTImpl &, Int64)
2023-09-29 16:52:48 +00:00
{
throwDateIsNotSupported(TO_START_OF_INTERVAL_NAME);
}
2023-10-08 14:26:31 +00:00
static UInt32 execute(UInt32, Int64, const DateLUTImpl &, Int64)
2023-09-29 16:52:48 +00:00
{
throwDateTimeIsNotSupported(TO_START_OF_INTERVAL_NAME);
}
2023-10-08 14:26:31 +00:00
static Int64 execute(Int64 t, Int64 microseconds, const DateLUTImpl &, Int64 scale_multiplier)
2023-09-29 16:52:48 +00:00
{
if (scale_multiplier < 1000000)
{
Int64 t_microseconds = 0;
if (common::mulOverflow(t, static_cast<Int64>(1000000) / scale_multiplier, t_microseconds))
throw DB::Exception(ErrorCodes::DECIMAL_OVERFLOW, "Numeric overflow");
if (t >= 0) [[likely]]
return t_microseconds / microseconds * microseconds;
else
return ((t_microseconds + 1) / microseconds - 1) * microseconds;
}
else if (scale_multiplier > 1000000)
{
Int64 scale_diff = scale_multiplier / static_cast<Int64>(1000000);
if (t >= 0) [[likely]]
return t / microseconds / scale_diff * microseconds;
else
return ((t + 1) / microseconds / scale_diff - 1) * microseconds;
}
else
if (t >= 0) [[likely]]
return t / microseconds * microseconds;
else
return ((t + 1) / microseconds - 1) * microseconds;
}
};
template <>
struct ToStartOfInterval<IntervalKind::Millisecond>
{
2023-10-08 14:26:31 +00:00
static UInt32 execute(UInt16, Int64, const DateLUTImpl &, Int64)
2023-09-29 16:52:48 +00:00
{
throwDateIsNotSupported(TO_START_OF_INTERVAL_NAME);
}
2023-10-08 14:26:31 +00:00
static UInt32 execute(Int32, Int64, const DateLUTImpl &, Int64)
2023-09-29 16:52:48 +00:00
{
throwDateIsNotSupported(TO_START_OF_INTERVAL_NAME);
}
2023-10-08 14:26:31 +00:00
static UInt32 execute(UInt32, Int64, const DateLUTImpl &, Int64)
2023-09-29 16:52:48 +00:00
{
throwDateTimeIsNotSupported(TO_START_OF_INTERVAL_NAME);
}
2023-10-08 14:26:31 +00:00
static Int64 execute(Int64 t, Int64 milliseconds, const DateLUTImpl &, Int64 scale_multiplier)
2023-09-29 16:52:48 +00:00
{
if (scale_multiplier < 1000)
{
Int64 t_milliseconds = 0;
if (common::mulOverflow(t, static_cast<Int64>(1000) / scale_multiplier, t_milliseconds))
throw DB::Exception(ErrorCodes::DECIMAL_OVERFLOW, "Numeric overflow");
if (t >= 0) [[likely]]
return t_milliseconds / milliseconds * milliseconds;
else
return ((t_milliseconds + 1) / milliseconds - 1) * milliseconds;
}
else if (scale_multiplier > 1000)
{
Int64 scale_diff = scale_multiplier / static_cast<Int64>(1000);
if (t >= 0) [[likely]]
return t / milliseconds / scale_diff * milliseconds;
else
return ((t + 1) / milliseconds / scale_diff - 1) * milliseconds;
}
else
if (t >= 0) [[likely]]
return t / milliseconds * milliseconds;
else
return ((t + 1) / milliseconds - 1) * milliseconds;
}
};
template <>
struct ToStartOfInterval<IntervalKind::Second>
{
2023-10-08 14:26:31 +00:00
static UInt32 execute(UInt16, Int64, const DateLUTImpl &, Int64)
2023-09-29 16:52:48 +00:00
{
throwDateIsNotSupported(TO_START_OF_INTERVAL_NAME);
}
2023-10-08 14:26:31 +00:00
static UInt32 execute(Int32, Int64, const DateLUTImpl &, Int64)
2023-09-29 16:52:48 +00:00
{
throwDateIsNotSupported(TO_START_OF_INTERVAL_NAME);
}
2023-10-08 14:26:31 +00:00
static UInt32 execute(UInt32 t, Int64 seconds, const DateLUTImpl & time_zone, Int64)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfSecondInterval(t, seconds);
}
2023-10-08 14:26:31 +00:00
static Int64 execute(Int64 t, Int64 seconds, const DateLUTImpl & time_zone, Int64 scale_multiplier)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfSecondInterval(t / scale_multiplier, seconds);
}
};
template <>
struct ToStartOfInterval<IntervalKind::Minute>
{
2023-10-08 14:26:31 +00:00
static UInt32 execute(UInt16, Int64, const DateLUTImpl &, Int64)
2023-09-29 16:52:48 +00:00
{
throwDateIsNotSupported(TO_START_OF_INTERVAL_NAME);
}
2023-10-08 14:26:31 +00:00
static UInt32 execute(Int32, Int64, const DateLUTImpl &, Int64)
2023-09-29 16:52:48 +00:00
{
throwDateIsNotSupported(TO_START_OF_INTERVAL_NAME);
}
2023-10-08 14:26:31 +00:00
static UInt32 execute(UInt32 t, Int64 minutes, const DateLUTImpl & time_zone, Int64)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfMinuteInterval(t, minutes);
}
2023-10-08 14:26:31 +00:00
static Int64 execute(Int64 t, Int64 minutes, const DateLUTImpl & time_zone, Int64 scale_multiplier)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfMinuteInterval(t / scale_multiplier, minutes);
}
};
template <>
struct ToStartOfInterval<IntervalKind::Hour>
{
2023-10-08 14:26:31 +00:00
static UInt32 execute(UInt16, Int64, const DateLUTImpl &, Int64)
2023-09-29 16:52:48 +00:00
{
throwDateIsNotSupported(TO_START_OF_INTERVAL_NAME);
}
2023-10-08 14:26:31 +00:00
static UInt32 execute(Int32, Int64, const DateLUTImpl &, Int64)
2023-09-29 16:52:48 +00:00
{
throwDateIsNotSupported(TO_START_OF_INTERVAL_NAME);
}
2023-10-08 14:26:31 +00:00
static UInt32 execute(UInt32 t, Int64 hours, const DateLUTImpl & time_zone, Int64)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfHourInterval(t, hours);
}
2023-10-08 14:26:31 +00:00
static Int64 execute(Int64 t, Int64 hours, const DateLUTImpl & time_zone, Int64 scale_multiplier)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfHourInterval(t / scale_multiplier, hours);
}
};
template <>
struct ToStartOfInterval<IntervalKind::Day>
{
2023-10-08 14:26:31 +00:00
static UInt32 execute(UInt16 d, Int64 days, const DateLUTImpl & time_zone, Int64)
2023-09-29 16:52:48 +00:00
{
return static_cast<UInt32>(time_zone.toStartOfDayInterval(ExtendedDayNum(d), days));
}
2023-10-08 14:26:31 +00:00
static UInt32 execute(Int32 d, Int64 days, const DateLUTImpl & time_zone, Int64)
2023-09-29 16:52:48 +00:00
{
return static_cast<UInt32>(time_zone.toStartOfDayInterval(ExtendedDayNum(d), days));
}
2023-10-08 14:26:31 +00:00
static UInt32 execute(UInt32 t, Int64 days, const DateLUTImpl & time_zone, Int64)
2023-09-29 16:52:48 +00:00
{
return static_cast<UInt32>(time_zone.toStartOfDayInterval(time_zone.toDayNum(t), days));
}
2023-10-08 14:26:31 +00:00
static Int64 execute(Int64 t, Int64 days, const DateLUTImpl & time_zone, Int64 scale_multiplier)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfDayInterval(time_zone.toDayNum(t / scale_multiplier), days);
}
};
template <>
struct ToStartOfInterval<IntervalKind::Week>
{
2023-10-08 14:26:31 +00:00
static UInt16 execute(UInt16 d, Int64 weeks, const DateLUTImpl & time_zone, Int64)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfWeekInterval(DayNum(d), weeks);
}
2023-10-08 14:26:31 +00:00
static UInt16 execute(Int32 d, Int64 weeks, const DateLUTImpl & time_zone, Int64)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfWeekInterval(ExtendedDayNum(d), weeks);
}
2023-10-08 14:26:31 +00:00
static UInt16 execute(UInt32 t, Int64 weeks, const DateLUTImpl & time_zone, Int64)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfWeekInterval(time_zone.toDayNum(t), weeks);
}
2023-10-08 14:26:31 +00:00
static UInt16 execute(Int64 t, Int64 weeks, const DateLUTImpl & time_zone, Int64 scale_multiplier)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfWeekInterval(time_zone.toDayNum(t / scale_multiplier), weeks);
}
};
template <>
struct ToStartOfInterval<IntervalKind::Month>
{
2023-10-08 14:26:31 +00:00
static UInt16 execute(UInt16 d, Int64 months, const DateLUTImpl & time_zone, Int64)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfMonthInterval(DayNum(d), months);
}
2023-10-08 14:26:31 +00:00
static UInt16 execute(Int32 d, Int64 months, const DateLUTImpl & time_zone, Int64)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfMonthInterval(ExtendedDayNum(d), months);
}
2023-10-08 14:26:31 +00:00
static UInt16 execute(UInt32 t, Int64 months, const DateLUTImpl & time_zone, Int64)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfMonthInterval(time_zone.toDayNum(t), months);
}
2023-10-08 14:26:31 +00:00
static UInt16 execute(Int64 t, Int64 months, const DateLUTImpl & time_zone, Int64 scale_multiplier)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfMonthInterval(time_zone.toDayNum(t / scale_multiplier), months);
}
};
template <>
struct ToStartOfInterval<IntervalKind::Quarter>
{
2023-10-08 14:26:31 +00:00
static UInt16 execute(UInt16 d, Int64 quarters, const DateLUTImpl & time_zone, Int64)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfQuarterInterval(DayNum(d), quarters);
}
2023-10-08 14:26:31 +00:00
static UInt16 execute(Int32 d, Int64 quarters, const DateLUTImpl & time_zone, Int64)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfQuarterInterval(ExtendedDayNum(d), quarters);
}
2023-10-08 14:26:31 +00:00
static UInt16 execute(UInt32 t, Int64 quarters, const DateLUTImpl & time_zone, Int64)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfQuarterInterval(time_zone.toDayNum(t), quarters);
}
2023-10-08 14:26:31 +00:00
static UInt16 execute(Int64 t, Int64 quarters, const DateLUTImpl & time_zone, Int64 scale_multiplier)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfQuarterInterval(time_zone.toDayNum(t / scale_multiplier), quarters);
}
};
template <>
struct ToStartOfInterval<IntervalKind::Year>
{
2023-10-08 14:26:31 +00:00
static UInt16 execute(UInt16 d, Int64 years, const DateLUTImpl & time_zone, Int64)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfYearInterval(DayNum(d), years);
}
2023-10-08 14:26:31 +00:00
static UInt16 execute(Int32 d, Int64 years, const DateLUTImpl & time_zone, Int64)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfYearInterval(ExtendedDayNum(d), years);
}
2023-10-08 14:26:31 +00:00
static UInt16 execute(UInt32 t, Int64 years, const DateLUTImpl & time_zone, Int64)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfYearInterval(time_zone.toDayNum(t), years);
}
2023-10-08 14:26:31 +00:00
static UInt16 execute(Int64 t, Int64 years, const DateLUTImpl & time_zone, Int64 scale_multiplier)
2023-09-29 16:52:48 +00:00
{
return time_zone.toStartOfYearInterval(time_zone.toDayNum(t / scale_multiplier), years);
}
};
struct ToTimeImpl
{
2021-11-08 07:19:31 +00:00
/// When transforming to time, the date will be equated to 1970-01-02.
static constexpr auto name = "toTime";
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
static UInt32 execute(const DecimalUtils::DecimalComponents<DateTime64> & t, const DateLUTImpl & time_zone)
{
return static_cast<UInt32>(time_zone.toTime(t.whole) + 86400);
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return static_cast<UInt32>(time_zone.toTime(t) + 86400);
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(Int32, const DateLUTImpl &)
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt16, const DateLUTImpl &)
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ToDateImpl;
};
struct ToStartOfMinuteImpl
{
static constexpr auto name = "toStartOfMinute";
2023-09-09 16:48:17 +00:00
static UInt32 execute(const DecimalUtils::DecimalComponents<DateTime64> & t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return static_cast<UInt32>(time_zone.toStartOfMinute(t.whole));
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toStartOfMinute(t);
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(Int32, const DateLUTImpl &)
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt16, const DateLUTImpl &)
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static DecimalUtils::DecimalComponents<DateTime64> executeExtendedResult(const DecimalUtils::DecimalComponents<DateTime64> & t, const DateLUTImpl & time_zone)
{
return {time_zone.toStartOfMinute(t.whole), 0};
}
2023-09-09 16:48:17 +00:00
static Int64 executeExtendedResult(Int32, const DateLUTImpl &)
{
throwDate32IsNotSupported(name);
}
using FactorTransform = ZeroTransform;
};
// Rounding towards negative infinity.
// 1.01 => 1.00
// -1.01 => -2
struct ToStartOfSecondImpl
{
static constexpr auto name = "toStartOfSecond";
2023-09-09 16:48:17 +00:00
static DateTime64 execute(const DateTime64 & datetime64, Int64 scale_multiplier, const DateLUTImpl &)
{
auto fractional_with_sign = DecimalUtils::getFractionalPartWithScaleMultiplier<DateTime64, true>(datetime64, scale_multiplier);
// given that scale is 3, scale_multiplier is 1000
// for DateTime64 value of 123.456:
// 123456 - 456 = 123000
// for DateTime64 value of -123.456:
// -123456 - (1000 + (-456)) = -124000
if (fractional_with_sign < 0)
fractional_with_sign += scale_multiplier;
return datetime64 - fractional_with_sign;
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt32, const DateLUTImpl &)
{
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type DateTime of argument for function {}", name);
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(Int32, const DateLUTImpl &)
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt16, const DateLUTImpl &)
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ZeroTransform;
};
2022-02-13 14:54:03 +00:00
struct ToStartOfMillisecondImpl
{
static constexpr auto name = "toStartOfMillisecond";
2023-09-09 16:48:17 +00:00
static DateTime64 execute(const DateTime64 & datetime64, Int64 scale_multiplier, const DateLUTImpl &)
2022-02-13 14:54:03 +00:00
{
// given that scale is 6, scale_multiplier is 1000000
// for DateTime64 value of 123.456789:
// 123456789 - 789 = 123456000
// for DateTime64 value of -123.456789:
// -123456789 - (1000 + (-789)) = -123457000
2022-02-13 21:04:09 +00:00
if (scale_multiplier == 1000)
{
return datetime64;
}
else if (scale_multiplier <= 1000)
{
2022-02-13 14:54:03 +00:00
return datetime64 * (1000 / scale_multiplier);
}
else
{
auto droppable_part_with_sign = DecimalUtils::getFractionalPartWithScaleMultiplier<DateTime64, true>(datetime64, scale_multiplier / 1000);
if (droppable_part_with_sign < 0)
droppable_part_with_sign += scale_multiplier;
return datetime64 - droppable_part_with_sign;
}
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt32, const DateLUTImpl &)
2022-02-13 14:54:03 +00:00
{
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type DateTime of argument for function {}", name);
2022-02-13 14:54:03 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(Int32, const DateLUTImpl &)
2022-02-13 14:54:03 +00:00
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
2022-02-13 14:54:03 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt16, const DateLUTImpl &)
2022-02-13 14:54:03 +00:00
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
2022-02-13 14:54:03 +00:00
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
2022-02-13 14:54:03 +00:00
using FactorTransform = ZeroTransform;
};
struct ToStartOfMicrosecondImpl
{
static constexpr auto name = "toStartOfMicrosecond";
2023-09-09 16:48:17 +00:00
static DateTime64 execute(const DateTime64 & datetime64, Int64 scale_multiplier, const DateLUTImpl &)
2022-02-13 14:54:03 +00:00
{
// @see ToStartOfMillisecondImpl
2022-02-13 21:04:09 +00:00
if (scale_multiplier == 1000000)
{
return datetime64;
}
else if (scale_multiplier <= 1000000)
{
2022-02-13 14:54:03 +00:00
return datetime64 * (1000000 / scale_multiplier);
}
else
{
auto droppable_part_with_sign = DecimalUtils::getFractionalPartWithScaleMultiplier<DateTime64, true>(datetime64, scale_multiplier / 1000000);
if (droppable_part_with_sign < 0)
droppable_part_with_sign += scale_multiplier;
return datetime64 - droppable_part_with_sign;
}
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt32, const DateLUTImpl &)
2022-02-13 14:54:03 +00:00
{
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type DateTime of argument for function {}", name);
2022-02-13 14:54:03 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(Int32, const DateLUTImpl &)
2022-02-13 14:54:03 +00:00
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
2022-02-13 14:54:03 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt16, const DateLUTImpl &)
2022-02-13 14:54:03 +00:00
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
2022-02-13 14:54:03 +00:00
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
2022-02-13 14:54:03 +00:00
using FactorTransform = ZeroTransform;
};
struct ToStartOfNanosecondImpl
{
static constexpr auto name = "toStartOfNanosecond";
2023-09-09 16:48:17 +00:00
static DateTime64 execute(const DateTime64 & datetime64, Int64 scale_multiplier, const DateLUTImpl &)
2022-02-13 14:54:03 +00:00
{
// @see ToStartOfMillisecondImpl
2022-02-13 21:04:09 +00:00
if (scale_multiplier == 1000000000)
{
2022-02-13 14:54:03 +00:00
return datetime64;
}
2022-02-13 21:04:09 +00:00
else if (scale_multiplier <= 1000000000)
{
2022-02-13 14:54:03 +00:00
return datetime64 * (1000000000 / scale_multiplier);
}
else
{
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type of argument for function {}, DateTime64 expected", name);
2022-02-13 14:54:03 +00:00
}
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt32, const DateLUTImpl &)
2022-02-13 14:54:03 +00:00
{
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type DateTime of argument for function {}", name);
2022-02-13 14:54:03 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(Int32, const DateLUTImpl &)
2022-02-13 14:54:03 +00:00
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
2022-02-13 14:54:03 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt16, const DateLUTImpl &)
2022-02-13 14:54:03 +00:00
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
2022-02-13 14:54:03 +00:00
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
2022-02-13 14:54:03 +00:00
using FactorTransform = ZeroTransform;
};
struct ToStartOfFiveMinutesImpl
{
static constexpr auto name = "toStartOfFiveMinutes";
2023-09-09 16:48:17 +00:00
static UInt32 execute(const DecimalUtils::DecimalComponents<DateTime64> & t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return static_cast<UInt32>(time_zone.toStartOfFiveMinutes(t.whole));
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toStartOfFiveMinutes(t);
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(Int32, const DateLUTImpl &)
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt16, const DateLUTImpl &)
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static DecimalUtils::DecimalComponents<DateTime64> executeExtendedResult(const DecimalUtils::DecimalComponents<DateTime64> & t, const DateLUTImpl & time_zone)
{
return {time_zone.toStartOfFiveMinutes(t.whole), 0};
}
2023-09-09 16:48:17 +00:00
static Int64 executeExtendedResult(Int32, const DateLUTImpl &)
{
throwDate32IsNotSupported(name);
}
using FactorTransform = ZeroTransform;
};
2019-02-06 22:50:04 +00:00
struct ToStartOfTenMinutesImpl
{
static constexpr auto name = "toStartOfTenMinutes";
2023-09-09 16:48:17 +00:00
static UInt32 execute(const DecimalUtils::DecimalComponents<DateTime64> & t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return static_cast<UInt32>(time_zone.toStartOfTenMinutes(t.whole));
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
2019-02-06 22:50:04 +00:00
{
return time_zone.toStartOfTenMinutes(t);
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(Int32, const DateLUTImpl &)
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt16, const DateLUTImpl &)
2019-02-06 22:50:04 +00:00
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
2019-02-06 22:50:04 +00:00
}
2023-09-09 16:48:17 +00:00
static DecimalUtils::DecimalComponents<DateTime64> executeExtendedResult(const DecimalUtils::DecimalComponents<DateTime64> & t, const DateLUTImpl & time_zone)
{
return {time_zone.toStartOfTenMinutes(t.whole), 0};
}
2023-09-09 16:48:17 +00:00
static Int64 executeExtendedResult(Int32, const DateLUTImpl &)
{
throwDate32IsNotSupported(name);
}
2019-02-06 22:50:04 +00:00
using FactorTransform = ZeroTransform;
};
struct ToStartOfFifteenMinutesImpl
{
static constexpr auto name = "toStartOfFifteenMinutes";
2023-09-09 16:48:17 +00:00
static UInt32 execute(const DecimalUtils::DecimalComponents<DateTime64> & t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return static_cast<UInt32>(time_zone.toStartOfFifteenMinutes(t.whole));
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toStartOfFifteenMinutes(t);
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(Int32, const DateLUTImpl &)
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt16, const DateLUTImpl &)
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static DecimalUtils::DecimalComponents<DateTime64> executeExtendedResult(const DecimalUtils::DecimalComponents<DateTime64> & t, const DateLUTImpl & time_zone)
{
return {time_zone.toStartOfFifteenMinutes(t.whole), 0};
}
2023-09-09 16:48:17 +00:00
static Int64 executeExtendedResult(Int32, const DateLUTImpl &)
{
throwDate32IsNotSupported(name);
}
using FactorTransform = ZeroTransform;
};
2022-04-15 22:20:47 +00:00
/// Round to start of half-an-hour length interval with unspecified offset. This transform is specific for Metrica web analytics system.
struct TimeSlotImpl
{
static constexpr auto name = "timeSlot";
2023-09-09 16:48:17 +00:00
static UInt32 execute(const DecimalUtils::DecimalComponents<DateTime64> & t, const DateLUTImpl &)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return static_cast<UInt32>(t.whole / 1800 * 1800);
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt32 t, const DateLUTImpl &)
{
return t / 1800 * 1800;
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(Int32, const DateLUTImpl &)
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt16, const DateLUTImpl &)
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static DecimalUtils::DecimalComponents<DateTime64> executeExtendedResult(const DecimalUtils::DecimalComponents<DateTime64> & t, const DateLUTImpl &)
2022-09-29 15:44:56 +00:00
{
if (likely(t.whole >= 0))
return {t.whole / 1800 * 1800, 0};
return {(t.whole + 1 - 1800) / 1800 * 1800, 0};
}
2023-09-09 16:48:17 +00:00
static Int64 executeExtendedResult(Int32, const DateLUTImpl &)
2022-09-22 09:19:22 +00:00
{
throwDate32IsNotSupported(name);
2022-09-22 09:19:22 +00:00
}
using FactorTransform = ZeroTransform;
};
struct ToStartOfHourImpl
{
static constexpr auto name = "toStartOfHour";
2023-09-09 16:48:17 +00:00
static UInt32 execute(const DecimalUtils::DecimalComponents<DateTime64> & t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return static_cast<UInt32>(time_zone.toStartOfHour(t.whole));
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toStartOfHour(t);
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(Int32, const DateLUTImpl &)
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt16, const DateLUTImpl &)
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static DecimalUtils::DecimalComponents<DateTime64> executeExtendedResult(const DecimalUtils::DecimalComponents<DateTime64> & t, const DateLUTImpl & time_zone)
{
2022-09-22 09:19:22 +00:00
return {time_zone.toStartOfHour(t.whole), 0};
}
2023-09-09 16:48:17 +00:00
static Int64 executeExtendedResult(Int32, const DateLUTImpl &)
{
throwDate32IsNotSupported(name);
}
using FactorTransform = ZeroTransform;
};
struct ToYearImpl
{
static constexpr auto name = "toYear";
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int64 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return time_zone.toYear(t);
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toYear(t);
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int32 d, const DateLUTImpl & time_zone)
{
return time_zone.toYear(ExtendedDayNum(d));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
{
2021-11-08 07:19:31 +00:00
return time_zone.toYear(DayNum(d));
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return true; }
2023-09-09 16:48:17 +00:00
static RangeOrNull getPreimage(const IDataType & type, const Field & point)
{
if (point.getType() != Field::Types::UInt64) return std::nullopt;
auto year = point.get<UInt64>();
if (year < DATE_LUT_MIN_YEAR || year >= DATE_LUT_MAX_YEAR) return std::nullopt;
2023-07-05 09:57:18 +00:00
const DateLUTImpl & date_lut = DateLUT::instance("UTC");
auto start_time = date_lut.makeDateTime(year, 1, 1, 0, 0, 0);
auto end_time = date_lut.addYears(start_time, 1);
if (isDateOrDate32(type) || isDateTime(type) || isDateTime64(type))
return {std::make_pair(Field(start_time), Field(end_time))};
else
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
"Illegal type {} of argument of function {}. Should be Date, Date32, DateTime or DateTime64",
type.getName(), name);
}
using FactorTransform = ZeroTransform;
};
2023-02-07 02:03:03 +00:00
struct ToWeekYearImpl
{
static constexpr auto name = "toWeekYear";
static constexpr Int8 week_mode = 3;
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int64 t, const DateLUTImpl & time_zone)
{
return time_zone.toYearWeek(t, week_mode).first;
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toYearWeek(t, week_mode).first;
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int32 d, const DateLUTImpl & time_zone)
{
return time_zone.toYearWeek(ExtendedDayNum(d), week_mode).first;
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
{
return time_zone.toYearWeek(DayNum(d), week_mode).first;
}
using FactorTransform = ZeroTransform;
};
struct ToWeekOfWeekYearImpl
{
static constexpr auto name = "toWeekOfWeekYear";
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int64 t, const DateLUTImpl & time_zone)
{
return time_zone.toISOWeek(t);
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toISOWeek(t);
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int32 d, const DateLUTImpl & time_zone)
{
return time_zone.toISOWeek(ExtendedDayNum(d));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
{
return time_zone.toISOWeek(DayNum(d));
}
using FactorTransform = ZeroTransform;
};
struct ToQuarterImpl
{
static constexpr auto name = "toQuarter";
2023-09-09 16:48:17 +00:00
static UInt8 execute(Int64 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return time_zone.toQuarter(t);
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toQuarter(t);
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(Int32 d, const DateLUTImpl & time_zone)
{
return time_zone.toQuarter(ExtendedDayNum(d));
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(UInt16 d, const DateLUTImpl & time_zone)
{
2021-11-08 07:19:31 +00:00
return time_zone.toQuarter(DayNum(d));
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ToStartOfYearImpl;
};
struct ToMonthImpl
{
static constexpr auto name = "toMonth";
2023-09-09 16:48:17 +00:00
static UInt8 execute(Int64 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return time_zone.toMonth(t);
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toMonth(t);
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(Int32 d, const DateLUTImpl & time_zone)
{
return time_zone.toMonth(ExtendedDayNum(d));
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(UInt16 d, const DateLUTImpl & time_zone)
{
2021-11-08 07:19:31 +00:00
return time_zone.toMonth(DayNum(d));
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ToStartOfYearImpl;
};
struct ToDayOfMonthImpl
{
static constexpr auto name = "toDayOfMonth";
2023-09-09 16:48:17 +00:00
static UInt8 execute(Int64 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return time_zone.toDayOfMonth(t);
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toDayOfMonth(t);
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(Int32 d, const DateLUTImpl & time_zone)
{
return time_zone.toDayOfMonth(ExtendedDayNum(d));
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(UInt16 d, const DateLUTImpl & time_zone)
{
2021-11-08 07:19:31 +00:00
return time_zone.toDayOfMonth(DayNum(d));
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ToStartOfMonthImpl;
};
struct ToDayOfWeekImpl
{
static constexpr auto name = "toDayOfWeek";
2023-09-09 16:48:17 +00:00
static UInt8 execute(Int64 t, UInt8 mode, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
2023-01-13 14:01:13 +00:00
return time_zone.toDayOfWeek(t, mode);
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(UInt32 t, UInt8 mode, const DateLUTImpl & time_zone)
{
2023-01-13 14:01:13 +00:00
return time_zone.toDayOfWeek(t, mode);
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(Int32 d, UInt8 mode, const DateLUTImpl & time_zone)
{
2023-01-13 14:01:13 +00:00
return time_zone.toDayOfWeek(ExtendedDayNum(d), mode);
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(UInt16 d, UInt8 mode, const DateLUTImpl & time_zone)
{
2023-01-13 14:01:13 +00:00
return time_zone.toDayOfWeek(DayNum(d), mode);
}
using FactorTransform = ToMondayImpl;
};
struct ToDayOfYearImpl
{
static constexpr auto name = "toDayOfYear";
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int64 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return time_zone.toDayOfYear(t);
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toDayOfYear(t);
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int32 d, const DateLUTImpl & time_zone)
{
return time_zone.toDayOfYear(ExtendedDayNum(d));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
{
2021-11-08 07:19:31 +00:00
return time_zone.toDayOfYear(DayNum(d));
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ToStartOfYearImpl;
};
struct ToDaysSinceYearZeroImpl
{
2023-09-10 12:55:15 +00:00
private:
2023-09-22 11:52:02 +00:00
static constexpr auto DAYS_BETWEEN_YEARS_0_AND_1970 = 719'528; /// 01 January, each. Constant taken from Java LocalDate. Consistent with MySQL's TO_DAYS().
static constexpr auto SECONDS_PER_DAY = 60 * 60 * 24;
2023-09-10 12:55:15 +00:00
public:
static constexpr auto name = "toDaysSinceYearZero";
2023-09-22 13:13:55 +00:00
static UInt32 execute(Int64 t, const DateLUTImpl & time_zone)
{
2023-09-22 13:13:55 +00:00
return DAYS_BETWEEN_YEARS_0_AND_1970 + static_cast<UInt32>(time_zone.toDayNum(t));
}
static UInt32 execute(UInt32 d, const DateLUTImpl &)
{
2023-09-22 11:52:02 +00:00
return DAYS_BETWEEN_YEARS_0_AND_1970 + d / SECONDS_PER_DAY;
}
static UInt32 execute(Int32 d, const DateLUTImpl &)
{
return DAYS_BETWEEN_YEARS_0_AND_1970 + d;
}
static UInt32 execute(UInt16 d, const DateLUTImpl &)
{
return DAYS_BETWEEN_YEARS_0_AND_1970 + d;
}
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ZeroTransform;
};
struct ToHourImpl
{
static constexpr auto name = "toHour";
2023-09-09 16:48:17 +00:00
static UInt8 execute(Int64 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return time_zone.toHour(t);
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toHour(t);
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(Int32, const DateLUTImpl &)
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(UInt16, const DateLUTImpl &)
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ToDateImpl;
};
2021-02-02 15:35:45 +00:00
struct TimezoneOffsetImpl
2021-02-02 03:01:20 +00:00
{
static constexpr auto name = "timezoneOffset";
2023-09-09 16:48:17 +00:00
static time_t execute(Int64 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return time_zone.timezoneOffset(t);
}
2023-09-09 16:48:17 +00:00
static time_t execute(UInt32 t, const DateLUTImpl & time_zone)
2021-02-02 03:01:20 +00:00
{
return time_zone.timezoneOffset(t);
}
2023-09-09 16:48:17 +00:00
static time_t execute(Int32, const DateLUTImpl &)
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static time_t execute(UInt16, const DateLUTImpl &)
2021-02-02 03:01:20 +00:00
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
2021-02-02 03:01:20 +00:00
}
2021-02-02 15:35:45 +00:00
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
2021-02-02 15:35:45 +00:00
using FactorTransform = ToTimeImpl;
2021-02-02 03:01:20 +00:00
};
struct ToMinuteImpl
{
static constexpr auto name = "toMinute";
2023-09-09 16:48:17 +00:00
static UInt8 execute(Int64 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return time_zone.toMinute(t);
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toMinute(t);
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(Int32, const DateLUTImpl &)
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(UInt16, const DateLUTImpl &)
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ToStartOfHourImpl;
};
struct ToSecondImpl
{
static constexpr auto name = "toSecond";
2023-09-09 16:48:17 +00:00
static UInt8 execute(Int64 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return time_zone.toSecond(t);
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toSecond(t);
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(Int32, const DateLUTImpl &)
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(UInt16, const DateLUTImpl &)
{
2023-09-09 16:48:17 +00:00
throwDateIsNotSupported(name);
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ToStartOfMinuteImpl;
};
struct ToISOYearImpl
{
static constexpr auto name = "toISOYear";
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int64 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return time_zone.toISOYear(time_zone.toDayNum(t));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toISOYear(time_zone.toDayNum(t));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int32 d, const DateLUTImpl & time_zone)
{
return time_zone.toISOYear(ExtendedDayNum(d));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
{
2021-11-08 07:19:31 +00:00
return time_zone.toISOYear(DayNum(d));
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ZeroTransform;
};
struct ToStartOfISOYearImpl
{
static constexpr auto name = "toStartOfISOYear";
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int64 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return t < 0 ? 0 : time_zone.toFirstDayNumOfISOYear(ExtendedDayNum(std::min(Int32(time_zone.toDayNum(t)), Int32(DATE_LUT_MAX_DAY_NUM))));
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toFirstDayNumOfISOYear(time_zone.toDayNum(t));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(Int32 d, const DateLUTImpl & time_zone)
{
return d < 0 ? 0 : time_zone.toFirstDayNumOfISOYear(ExtendedDayNum(std::min(d, Int32(DATE_LUT_MAX_DAY_NUM))));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
{
2021-11-08 07:19:31 +00:00
return time_zone.toFirstDayNumOfISOYear(DayNum(d));
}
2023-09-09 16:48:17 +00:00
static Int64 executeExtendedResult(Int64 t, const DateLUTImpl & time_zone)
{
return time_zone.toFirstDayNumOfISOYear(time_zone.toDayNum(t));
}
2023-09-09 16:48:17 +00:00
static Int32 executeExtendedResult(Int32 d, const DateLUTImpl & time_zone)
{
return time_zone.toFirstDayNumOfISOYear(ExtendedDayNum(d));
}
using FactorTransform = ZeroTransform;
};
struct ToISOWeekImpl
{
static constexpr auto name = "toISOWeek";
2023-09-09 16:48:17 +00:00
static UInt8 execute(Int64 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return time_zone.toISOWeek(time_zone.toDayNum(t));
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toISOWeek(time_zone.toDayNum(t));
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(Int32 d, const DateLUTImpl & time_zone)
{
return time_zone.toISOWeek(ExtendedDayNum(d));
}
2023-09-09 16:48:17 +00:00
static UInt8 execute(UInt16 d, const DateLUTImpl & time_zone)
{
2021-11-08 07:19:31 +00:00
return time_zone.toISOWeek(DayNum(d));
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ToISOYearImpl;
};
enum class ResultPrecision
{
Standard,
Extended
};
/// Standard precision results (precision_ == ResultPrecision::Standard) potentially lead to overflows when returning values.
/// This mode is used by SQL functions "toRelative*Num()" which cannot easily be changed due to backward compatibility.
/// According to documentation, these functions merely need to compute the time difference to a deterministic, fixed point in the past.
/// As a future TODO, we should fix their behavior in a backwards-compatible way.
/// See https://github.com/ClickHouse/ClickHouse/issues/41977#issuecomment-1267536814.
template <ResultPrecision precision_>
struct ToRelativeYearNumImpl
{
static constexpr auto name = "toRelativeYearNum";
2023-09-09 16:48:17 +00:00
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));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return time_zone.toYear(static_cast<time_t>(t));
}
2023-09-09 16:48:17 +00:00
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)));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
{
2021-11-08 07:19:31 +00:00
return time_zone.toYear(DayNum(d));
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ZeroTransform;
};
template <ResultPrecision precision_>
struct ToRelativeQuarterNumImpl
{
static constexpr auto name = "toRelativeQuarterNum";
2023-09-09 16:48:17 +00:00
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));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return time_zone.toRelativeQuarterNum(static_cast<time_t>(t));
}
2023-09-09 16:48:17 +00:00
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)));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
{
2021-11-08 07:19:31 +00:00
return time_zone.toRelativeQuarterNum(DayNum(d));
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ZeroTransform;
};
template <ResultPrecision precision_>
struct ToRelativeMonthNumImpl
{
static constexpr auto name = "toRelativeMonthNum";
2023-09-09 16:48:17 +00:00
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));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return time_zone.toRelativeMonthNum(static_cast<time_t>(t));
}
2023-09-09 16:48:17 +00:00
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)));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
{
2021-11-08 07:19:31 +00:00
return time_zone.toRelativeMonthNum(DayNum(d));
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ZeroTransform;
};
template <ResultPrecision precision_>
struct ToRelativeWeekNumImpl
{
static constexpr auto name = "toRelativeWeekNum";
2023-09-09 16:48:17 +00:00
static auto execute(Int64 t, const DateLUTImpl & time_zone)
{
if constexpr (precision_ == ResultPrecision::Extended)
return static_cast<Int32>(time_zone.toRelativeWeekNum(t));
else
return static_cast<UInt16>(time_zone.toRelativeWeekNum(t));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return time_zone.toRelativeWeekNum(static_cast<time_t>(t));
}
2023-09-09 16:48:17 +00:00
static auto execute(Int32 d, const DateLUTImpl & time_zone)
{
if constexpr (precision_ == ResultPrecision::Extended)
return static_cast<Int32>(time_zone.toRelativeWeekNum(ExtendedDayNum(d)));
else
return static_cast<UInt16>(time_zone.toRelativeWeekNum(ExtendedDayNum(d)));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt16 d, const DateLUTImpl & time_zone)
{
2021-11-08 07:19:31 +00:00
return time_zone.toRelativeWeekNum(DayNum(d));
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ZeroTransform;
};
template <ResultPrecision precision_>
struct ToRelativeDayNumImpl
{
static constexpr auto name = "toRelativeDayNum";
2023-09-09 16:48:17 +00:00
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));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt32 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return time_zone.toDayNum(static_cast<time_t>(t));
}
2023-09-09 16:48:17 +00:00
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));
}
2023-09-09 16:48:17 +00:00
static UInt16 execute(UInt16 d, const DateLUTImpl &)
{
return static_cast<DayNum>(d);
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ZeroTransform;
};
template <ResultPrecision precision_>
struct ToRelativeHourNumImpl
{
static constexpr auto name = "toRelativeHourNum";
2023-09-09 16:48:17 +00:00
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));
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
if constexpr (precision_ == ResultPrecision::Extended)
2022-11-28 12:38:00 +00:00
return static_cast<UInt32>(time_zone.toStableRelativeHourNum(static_cast<DateLUTImpl::Time>(t)));
else
2022-11-28 12:38:00 +00:00
return static_cast<UInt32>(time_zone.toRelativeHourNum(static_cast<DateLUTImpl::Time>(t)));
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
}
2023-09-09 16:48:17 +00:00
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)));
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
{
if constexpr (precision_ == ResultPrecision::Extended)
return static_cast<UInt32>(time_zone.toStableRelativeHourNum(DayNum(d)));
else
return static_cast<UInt32>(time_zone.toRelativeHourNum(DayNum(d)));
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ZeroTransform;
};
template <ResultPrecision precision_>
struct ToRelativeMinuteNumImpl
{
static constexpr auto name = "toRelativeMinuteNum";
2023-09-09 16:48:17 +00:00
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));
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
2022-11-28 12:38:00 +00:00
return static_cast<UInt32>(time_zone.toRelativeMinuteNum(static_cast<DateLUTImpl::Time>(t)));
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
}
2023-09-09 16:48:17 +00:00
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)));
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
{
return static_cast<UInt32>(time_zone.toRelativeMinuteNum(DayNum(d)));
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ZeroTransform;
};
template <ResultPrecision precision_>
struct ToRelativeSecondNumImpl
{
static constexpr auto name = "toRelativeSecondNum";
2023-09-09 16:48:17 +00:00
static Int64 execute(Int64 t, const DateLUTImpl &)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return t;
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt32 t, const DateLUTImpl &)
{
return t;
}
2023-09-09 16:48:17 +00:00
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)));
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
{
return static_cast<UInt32>(time_zone.fromDayNum(DayNum(d)));
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ZeroTransform;
};
template <Int64 scale_multiplier>
struct ToRelativeSubsecondNumImpl
{
static constexpr auto name = "toRelativeSubsecondNumImpl";
2023-09-09 16:48:17 +00:00
static Int64 execute(const DateTime64 & t, DateTime64::NativeType scale, const DateLUTImpl &)
{
static_assert(scale_multiplier == 1000 || scale_multiplier == 1000000);
if (scale == scale_multiplier)
return t.value;
if (scale > scale_multiplier)
return t.value / (scale / scale_multiplier);
return t.value * (scale_multiplier / scale);
}
2023-09-09 16:48:17 +00:00
static Int64 execute(UInt32 t, const DateLUTImpl &)
{
return t * scale_multiplier;
}
2023-09-09 16:48:17 +00:00
static Int64 execute(Int32 d, const DateLUTImpl & time_zone)
{
return static_cast<Int64>(time_zone.fromDayNum(ExtendedDayNum(d))) * scale_multiplier;
}
2023-09-09 16:48:17 +00:00
static Int64 execute(UInt16 d, const DateLUTImpl & time_zone)
{
return static_cast<Int64>(time_zone.fromDayNum(DayNum(d)) * scale_multiplier);
}
using FactorTransform = ZeroTransform;
};
struct ToYYYYMMImpl
{
static constexpr auto name = "toYYYYMM";
2023-09-09 16:48:17 +00:00
static UInt32 execute(Int64 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return time_zone.toNumYYYYMM(t);
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toNumYYYYMM(t);
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(Int32 d, const DateLUTImpl & time_zone)
{
2021-11-08 07:19:31 +00:00
return time_zone.toNumYYYYMM(ExtendedDayNum(d));
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
{
2021-11-08 07:19:31 +00:00
return time_zone.toNumYYYYMM(DayNum(d));
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return true; }
2023-09-09 16:48:17 +00:00
static RangeOrNull getPreimage(const IDataType & type, const Field & point)
{
if (point.getType() != Field::Types::UInt64) return std::nullopt;
auto year_month = point.get<UInt64>();
auto year = year_month / 100;
auto month = year_month % 100;
if (year < DATE_LUT_MIN_YEAR || year > DATE_LUT_MAX_YEAR || month < 1 || month > 12 || (year == DATE_LUT_MAX_YEAR && month == 12))
return std::nullopt;
2023-07-05 09:57:18 +00:00
const DateLUTImpl & date_lut = DateLUT::instance("UTC");
auto start_time = date_lut.makeDateTime(year, month, 1, 0, 0, 0);
auto end_time = date_lut.addMonths(start_time, 1);
if (isDateOrDate32(type) || isDateTime(type) || isDateTime64(type))
return {std::make_pair(Field(start_time), Field(end_time))};
else
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT,
"Illegal type {} of argument of function {}. Should be Date, Date32, DateTime or DateTime64",
type.getName(), name);
}
using FactorTransform = ZeroTransform;
};
struct ToYYYYMMDDImpl
{
static constexpr auto name = "toYYYYMMDD";
2023-09-09 16:48:17 +00:00
static UInt32 execute(Int64 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return time_zone.toNumYYYYMMDD(t);
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toNumYYYYMMDD(t);
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(Int32 d, const DateLUTImpl & time_zone)
{
2021-11-08 07:19:31 +00:00
return time_zone.toNumYYYYMMDD(ExtendedDayNum(d));
}
2023-09-09 16:48:17 +00:00
static UInt32 execute(UInt16 d, const DateLUTImpl & time_zone)
{
2021-11-08 07:19:31 +00:00
return time_zone.toNumYYYYMMDD(DayNum(d));
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ZeroTransform;
};
struct ToYYYYMMDDhhmmssImpl
{
static constexpr auto name = "toYYYYMMDDhhmmss";
2023-09-09 16:48:17 +00:00
static UInt64 execute(Int64 t, const DateLUTImpl & time_zone)
Extended range of DateTime64 to years 1925 - 2238 The Year 1925 is a starting point because most of the timezones switched to saner (mostly 15-minutes based) offsets somewhere during 1924 or before. And that significantly simplifies implementation. 2238 is to simplify arithmetics for sanitizing LUT index access; there are less than 0x1ffff days from 1925. * Extended DateLUTImpl internal LUT to 0x1ffff items, some of which represent negative (pre-1970) time values. As a collateral benefit, Date now correctly supports dates up to 2149 (instead of 2106). * Added a new strong typedef ExtendedDayNum, which represents dates pre-1970 and post 2149. * Functions that used to return DayNum now return ExtendedDayNum. * Refactored DateLUTImpl to untie DayNum from the dual role of being a value and an index (due to negative time). Index is now a different type LUTIndex with explicit conversion functions from DatNum, time_t, and ExtendedDayNum. * Updated DateLUTImpl to properly support values close to epoch start (1970-01-01 00:00), including negative ones. * Reduced resolution of DateLUTImpl::Values::time_at_offset_change to multiple of 15-minutes to allow storing 64-bits of time_t in DateLUTImpl::Value while keeping same size. * Minor performance updates to DateLUTImpl when building month LUT by skipping non-start-of-month days. * Fixed extractTimeZoneFromFunctionArguments to work correctly with DateTime64. * New unit-tests and stateless integration tests for both DateTime and DateTime64.
2020-04-17 13:26:44 +00:00
{
return time_zone.toNumYYYYMMDDhhmmss(t);
}
2023-09-09 16:48:17 +00:00
static UInt64 execute(UInt32 t, const DateLUTImpl & time_zone)
{
return time_zone.toNumYYYYMMDDhhmmss(t);
}
2023-09-09 16:48:17 +00:00
static UInt64 execute(Int32 d, const DateLUTImpl & time_zone)
{
2021-11-08 07:19:31 +00:00
return time_zone.toNumYYYYMMDDhhmmss(time_zone.toDate(ExtendedDayNum(d)));
}
2023-09-09 16:48:17 +00:00
static UInt64 execute(UInt16 d, const DateLUTImpl & time_zone)
{
2021-11-08 07:19:31 +00:00
return time_zone.toNumYYYYMMDDhhmmss(time_zone.toDate(DayNum(d)));
}
2023-09-09 16:48:17 +00:00
static constexpr bool hasPreimage() { return false; }
using FactorTransform = ZeroTransform;
};
struct DateTimeComponentsWithFractionalPart : public DateLUTImpl::DateTimeComponents
{
UInt16 millisecond;
UInt16 microsecond;
};
struct ToDateTimeComponentsImpl
{
static constexpr auto name = "toDateTimeComponents";
2023-09-09 16:48:17 +00:00
static DateTimeComponentsWithFractionalPart execute(const DateTime64 & t, DateTime64::NativeType scale_multiplier, const DateLUTImpl & time_zone)
{
auto components = DecimalUtils::splitWithScaleMultiplier(t, scale_multiplier);
if (t.value < 0 && components.fractional)
{
components.fractional = scale_multiplier + (components.whole ? Int64(-1) : Int64(1)) * components.fractional;
--components.whole;
}
Int64 fractional = components.fractional;
if (scale_multiplier > microsecond_multiplier)
fractional = fractional / (scale_multiplier / microsecond_multiplier);
else if (scale_multiplier < microsecond_multiplier)
fractional = fractional * (microsecond_multiplier / scale_multiplier);
constexpr Int64 divider = microsecond_multiplier/ millisecond_multiplier;
UInt16 millisecond = static_cast<UInt16>(fractional / divider);
UInt16 microsecond = static_cast<UInt16>(fractional % divider);
return DateTimeComponentsWithFractionalPart{time_zone.toDateTimeComponents(components.whole), millisecond, microsecond};
}
2023-09-09 16:48:17 +00:00
static DateTimeComponentsWithFractionalPart execute(UInt32 t, const DateLUTImpl & time_zone)
{
return DateTimeComponentsWithFractionalPart{time_zone.toDateTimeComponents(static_cast<DateLUTImpl::Time>(t)), 0, 0};
}
2023-09-09 16:48:17 +00:00
static DateTimeComponentsWithFractionalPart execute(Int32 d, const DateLUTImpl & time_zone)
{
return DateTimeComponentsWithFractionalPart{time_zone.toDateTimeComponents(ExtendedDayNum(d)), 0, 0};
}
2023-09-09 16:48:17 +00:00
static DateTimeComponentsWithFractionalPart execute(UInt16 d, const DateLUTImpl & time_zone)
{
return DateTimeComponentsWithFractionalPart{time_zone.toDateTimeComponents(DayNum(d)), 0, 0};
}
using FactorTransform = ZeroTransform;
};
struct DateTimeAccurateConvertStrategyAdditions {};
struct DateTimeAccurateOrNullConvertStrategyAdditions {};
template <typename FromType, typename ToType, typename Transform, bool is_extended_result = false, typename Additions = void *>
struct Transformer
{
template <typename FromTypeVector, typename ToTypeVector>
static void vector(const FromTypeVector & vec_from, ToTypeVector & vec_to, const DateLUTImpl & time_zone, const Transform & transform,
2023-06-09 10:29:44 +00:00
[[maybe_unused]] ColumnUInt8::Container * vec_null_map_to)
{
using ValueType = typename ToTypeVector::value_type;
size_t size = vec_from.size();
vec_to.resize(size);
for (size_t i = 0; i < size; ++i)
{
2023-06-09 10:29:44 +00:00
if constexpr (std::is_same_v<ToType, DataTypeDate> || std::is_same_v<ToType, DataTypeDateTime>)
{
2023-06-09 10:29:44 +00:00
if constexpr (std::is_same_v<Additions, DateTimeAccurateConvertStrategyAdditions>
|| std::is_same_v<Additions, DateTimeAccurateOrNullConvertStrategyAdditions>)
2023-06-06 11:08:21 +00:00
{
2023-06-09 10:29:44 +00:00
bool is_valid_input = vec_from[i] >= 0 && vec_from[i] <= 0xFFFFFFFFL;
2023-06-06 11:08:21 +00:00
2023-06-09 10:29:44 +00:00
if (!is_valid_input)
2023-06-06 11:08:21 +00:00
{
2023-06-09 10:29:44 +00:00
if constexpr (std::is_same_v<Additions, DateTimeAccurateOrNullConvertStrategyAdditions>)
{
vec_to[i] = 0;
2023-06-06 11:08:21 +00:00
(*vec_null_map_to)[i] = true;
2023-06-09 10:29:44 +00:00
continue;
}
else
{
2023-06-09 11:11:49 +00:00
throw Exception(ErrorCodes::CANNOT_CONVERT_TYPE, "Value {} cannot be safely converted into type {}",
vec_from[i], TypeName<ValueType>);
2023-06-09 10:29:44 +00:00
}
}
}
}
2023-06-01 19:52:48 +00:00
if constexpr (is_extended_result)
vec_to[i] = static_cast<ValueType>(transform.executeExtendedResult(vec_from[i], time_zone));
else
vec_to[i] = static_cast<ValueType>(transform.execute(vec_from[i], time_zone));
}
}
};
template <typename FromDataType, typename ToDataType, typename Transform, bool is_extended_result = false>
struct DateTimeTransformImpl
{
template <typename Additions = void *>
2021-05-06 23:17:39 +00:00
static ColumnPtr execute(
const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t /*input_rows_count*/, const Transform & transform = {})
{
2023-06-06 11:08:21 +00:00
using Op = Transformer<FromDataType, ToDataType, Transform, is_extended_result, Additions>;
2020-10-17 14:23:37 +00:00
const ColumnPtr source_col = arguments[0].column;
if (const auto * sources = checkAndGetColumn<typename FromDataType::ColumnType>(source_col.get()))
{
ColumnUInt8::MutablePtr col_null_map_to;
ColumnUInt8::Container * vec_null_map_to [[maybe_unused]] = nullptr;
if constexpr (std::is_same_v<Additions, DateTimeAccurateOrNullConvertStrategyAdditions>)
{
col_null_map_to = ColumnUInt8::create(sources->getData().size(), false);
vec_null_map_to = &col_null_map_to->getData();
}
2023-06-01 19:52:48 +00:00
2020-10-17 14:23:37 +00:00
auto mutable_result_col = result_type->createColumn();
auto * col_to = assert_cast<typename ToDataType::ColumnType *>(mutable_result_col.get());
2021-05-14 20:07:08 +00:00
WhichDataType result_data_type(result_type);
2021-05-14 21:46:17 +00:00
if (result_data_type.isDateTime() || result_data_type.isDateTime64())
2021-05-14 20:07:08 +00:00
{
const auto & time_zone = dynamic_cast<const TimezoneMixin &>(*result_type).getTimeZone();
Op::vector(sources->getData(), col_to->getData(), time_zone, transform, vec_null_map_to);
2021-05-14 20:07:08 +00:00
}
else
{
2021-06-28 16:56:15 +00:00
size_t time_zone_argument_position = 1;
if constexpr (std::is_same_v<ToDataType, DataTypeDateTime64>)
time_zone_argument_position = 2;
const DateLUTImpl & time_zone = extractTimeZoneFromFunctionArguments(arguments, time_zone_argument_position, 0);
Op::vector(sources->getData(), col_to->getData(), time_zone, transform, vec_null_map_to);
}
2023-06-02 12:03:50 +00:00
if constexpr (std::is_same_v<Additions, DateTimeAccurateOrNullConvertStrategyAdditions>)
{
2023-06-02 12:03:50 +00:00
if (vec_null_map_to)
{
return ColumnNullable::create(std::move(mutable_result_col), std::move(col_null_map_to));
}
2021-05-14 20:07:08 +00:00
}
2020-10-17 14:23:37 +00:00
return mutable_result_col;
}
else
{
throw Exception(ErrorCodes::ILLEGAL_COLUMN,
"Illegal column {} of first argument of function {}",
arguments[0].column->getName(), Transform::name);
}
}
};
}