Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
2dot5
ClickHouse
提交
7ecc63fe
C
ClickHouse
项目概览
2dot5
/
ClickHouse
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
ClickHouse
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
7ecc63fe
编写于
10月 29, 2017
作者:
A
Alexey Milovidov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Functions for interval arithmetic on DateTime and Date: development [#CLICKHOUSE-2].
上级
7bdbd71d
变更
5
展开全部
显示空白变更内容
内联
并排
Showing
5 changed file
with
526 addition
and
87 deletion
+526
-87
dbms/src/Functions/FunctionsConversion.h
dbms/src/Functions/FunctionsConversion.h
+12
-8
dbms/src/Functions/FunctionsDateTime.cpp
dbms/src/Functions/FunctionsDateTime.cpp
+7
-0
dbms/src/Functions/FunctionsDateTime.h
dbms/src/Functions/FunctionsDateTime.h
+367
-74
libs/libcommon/include/common/DateLUTImpl.h
libs/libcommon/include/common/DateLUTImpl.h
+132
-5
libs/libcommon/src/DateLUTImpl.cpp
libs/libcommon/src/DateLUTImpl.cpp
+8
-0
未找到文件。
dbms/src/Functions/FunctionsConversion.h
浏览文件 @
7ecc63fe
...
@@ -94,6 +94,8 @@ struct ConvertImpl
...
@@ -94,6 +94,8 @@ struct ConvertImpl
*/
*/
struct
ToDateTimeImpl
struct
ToDateTimeImpl
{
{
static
constexpr
auto
name
=
"toDateTime"
;
static
inline
UInt32
execute
(
UInt16
d
,
const
DateLUTImpl
&
time_zone
)
static
inline
UInt32
execute
(
UInt16
d
,
const
DateLUTImpl
&
time_zone
)
{
{
return
time_zone
.
fromDayNum
(
DayNum_t
(
d
));
return
time_zone
.
fromDayNum
(
DayNum_t
(
d
));
...
@@ -101,7 +103,7 @@ struct ToDateTimeImpl
...
@@ -101,7 +103,7 @@ struct ToDateTimeImpl
};
};
template
<
typename
Name
>
struct
ConvertImpl
<
DataTypeDate
,
DataTypeDateTime
,
Name
>
template
<
typename
Name
>
struct
ConvertImpl
<
DataTypeDate
,
DataTypeDateTime
,
Name
>
:
DateTimeTransformImpl
<
UInt16
,
UInt32
,
ToDateTimeImpl
,
Name
>
{};
:
DateTimeTransformImpl
<
UInt16
,
UInt32
,
ToDateTimeImpl
>
{};
/// Implementation of toDate function.
/// Implementation of toDate function.
...
@@ -109,6 +111,8 @@ template <typename Name> struct ConvertImpl<DataTypeDate, DataTypeDateTime, Name
...
@@ -109,6 +111,8 @@ template <typename Name> struct ConvertImpl<DataTypeDate, DataTypeDateTime, Name
template
<
typename
FromType
,
typename
ToType
>
template
<
typename
FromType
,
typename
ToType
>
struct
ToDateTransform32Or64
struct
ToDateTransform32Or64
{
{
static
constexpr
auto
name
=
"toDate"
;
static
inline
ToType
execute
(
const
FromType
&
from
,
const
DateLUTImpl
&
time_zone
)
static
inline
ToType
execute
(
const
FromType
&
from
,
const
DateLUTImpl
&
time_zone
)
{
{
return
(
from
<
0xFFFF
)
?
from
:
time_zone
.
toDayNum
(
from
);
return
(
from
<
0xFFFF
)
?
from
:
time_zone
.
toDayNum
(
from
);
...
@@ -118,7 +122,7 @@ struct ToDateTransform32Or64
...
@@ -118,7 +122,7 @@ struct ToDateTransform32Or64
/** Conversion of DateTime to Date: throw off time component.
/** Conversion of DateTime to Date: throw off time component.
*/
*/
template
<
typename
Name
>
struct
ConvertImpl
<
DataTypeDateTime
,
DataTypeDate
,
Name
>
template
<
typename
Name
>
struct
ConvertImpl
<
DataTypeDateTime
,
DataTypeDate
,
Name
>
:
DateTimeTransformImpl
<
UInt32
,
UInt16
,
ToDateImpl
,
Name
>
{};
:
DateTimeTransformImpl
<
UInt32
,
UInt16
,
ToDateImpl
>
{};
/** Special case of converting (U)Int32 or (U)Int64 (and also, for convenience, Float32, Float64) to Date.
/** Special case of converting (U)Int32 or (U)Int64 (and also, for convenience, Float32, Float64) to Date.
* If number is less than 65536, then it is treated as DayNum, and if greater or equals, then as unix timestamp.
* If number is less than 65536, then it is treated as DayNum, and if greater or equals, then as unix timestamp.
...
@@ -128,17 +132,17 @@ template <typename Name> struct ConvertImpl<DataTypeDateTime, DataTypeDate, Name
...
@@ -128,17 +132,17 @@ template <typename Name> struct ConvertImpl<DataTypeDateTime, DataTypeDate, Name
* (otherwise such usage would be frequent mistake).
* (otherwise such usage would be frequent mistake).
*/
*/
template
<
typename
Name
>
struct
ConvertImpl
<
DataTypeUInt32
,
DataTypeDate
,
Name
>
template
<
typename
Name
>
struct
ConvertImpl
<
DataTypeUInt32
,
DataTypeDate
,
Name
>
:
DateTimeTransformImpl
<
UInt32
,
UInt16
,
ToDateTransform32Or64
<
UInt32
,
UInt16
>
,
Name
>
{};
:
DateTimeTransformImpl
<
UInt32
,
UInt16
,
ToDateTransform32Or64
<
UInt32
,
UInt16
>>
{};
template
<
typename
Name
>
struct
ConvertImpl
<
DataTypeUInt64
,
DataTypeDate
,
Name
>
template
<
typename
Name
>
struct
ConvertImpl
<
DataTypeUInt64
,
DataTypeDate
,
Name
>
:
DateTimeTransformImpl
<
UInt64
,
UInt16
,
ToDateTransform32Or64
<
UInt64
,
UInt16
>
,
Name
>
{};
:
DateTimeTransformImpl
<
UInt64
,
UInt16
,
ToDateTransform32Or64
<
UInt64
,
UInt16
>>
{};
template
<
typename
Name
>
struct
ConvertImpl
<
DataTypeInt32
,
DataTypeDate
,
Name
>
template
<
typename
Name
>
struct
ConvertImpl
<
DataTypeInt32
,
DataTypeDate
,
Name
>
:
DateTimeTransformImpl
<
Int32
,
UInt16
,
ToDateTransform32Or64
<
Int32
,
UInt16
>
,
Name
>
{};
:
DateTimeTransformImpl
<
Int32
,
UInt16
,
ToDateTransform32Or64
<
Int32
,
UInt16
>>
{};
template
<
typename
Name
>
struct
ConvertImpl
<
DataTypeInt64
,
DataTypeDate
,
Name
>
template
<
typename
Name
>
struct
ConvertImpl
<
DataTypeInt64
,
DataTypeDate
,
Name
>
:
DateTimeTransformImpl
<
Int64
,
UInt16
,
ToDateTransform32Or64
<
Int64
,
UInt16
>
,
Name
>
{};
:
DateTimeTransformImpl
<
Int64
,
UInt16
,
ToDateTransform32Or64
<
Int64
,
UInt16
>>
{};
template
<
typename
Name
>
struct
ConvertImpl
<
DataTypeFloat32
,
DataTypeDate
,
Name
>
template
<
typename
Name
>
struct
ConvertImpl
<
DataTypeFloat32
,
DataTypeDate
,
Name
>
:
DateTimeTransformImpl
<
Float32
,
UInt16
,
ToDateTransform32Or64
<
Float32
,
UInt16
>
,
Name
>
{};
:
DateTimeTransformImpl
<
Float32
,
UInt16
,
ToDateTransform32Or64
<
Float32
,
UInt16
>>
{};
template
<
typename
Name
>
struct
ConvertImpl
<
DataTypeFloat64
,
DataTypeDate
,
Name
>
template
<
typename
Name
>
struct
ConvertImpl
<
DataTypeFloat64
,
DataTypeDate
,
Name
>
:
DateTimeTransformImpl
<
Float64
,
UInt16
,
ToDateTransform32Or64
<
Float64
,
UInt16
>
,
Name
>
{};
:
DateTimeTransformImpl
<
Float64
,
UInt16
,
ToDateTransform32Or64
<
Float64
,
UInt16
>>
{};
/** Transformation of numbers, dates, datetimes to strings: through formatting.
/** Transformation of numbers, dates, datetimes to strings: through formatting.
...
...
dbms/src/Functions/FunctionsDateTime.cpp
浏览文件 @
7ecc63fe
...
@@ -37,6 +37,13 @@ void registerFunctionsDateTime(FunctionFactory & factory)
...
@@ -37,6 +37,13 @@ void registerFunctionsDateTime(FunctionFactory & factory)
factory
.
registerFunction
<
FunctionToYYYYMM
>
();
factory
.
registerFunction
<
FunctionToYYYYMM
>
();
factory
.
registerFunction
<
FunctionToYYYYMMDD
>
();
factory
.
registerFunction
<
FunctionToYYYYMMDD
>
();
factory
.
registerFunction
<
FunctionToYYYYMMDDhhmmss
>
();
factory
.
registerFunction
<
FunctionToYYYYMMDDhhmmss
>
();
factory
.
registerFunction
<
FunctionAddSeconds
>
();
factory
.
registerFunction
<
FunctionAddMinutes
>
();
factory
.
registerFunction
<
FunctionAddHours
>
();
factory
.
registerFunction
<
FunctionAddDays
>
();
factory
.
registerFunction
<
FunctionAddWeeks
>
();
factory
.
registerFunction
<
FunctionAddMonths
>
();
factory
.
registerFunction
<
FunctionAddYears
>
();
}
}
}
}
dbms/src/Functions/FunctionsDateTime.h
浏览文件 @
7ecc63fe
此差异已折叠。
点击以展开。
libs/libcommon/include/common/DateLUTImpl.h
浏览文件 @
7ecc63fe
...
@@ -44,6 +44,10 @@ public:
...
@@ -44,6 +44,10 @@ public:
UInt8
day_of_month
;
UInt8
day_of_month
;
UInt8
day_of_week
;
UInt8
day_of_week
;
/// Total number of days in current month. Actually we can use separate table that is independent of time zone.
/// But due to alignment, this field is totally zero cost.
UInt8
days_in_month
;
/// For days, when offset from UTC was changed due to daylight saving time or permanent change, following values could be non zero.
/// For days, when offset from UTC was changed due to daylight saving time or permanent change, following values could be non zero.
UInt16
time_at_offset_change
;
/// In seconds from beginning of the day. Assuming offset never changed close to the end of day (so, value < 65536).
UInt16
time_at_offset_change
;
/// In seconds from beginning of the day. Assuming offset never changed close to the end of day (so, value < 65536).
Int16
amount_of_offset_change
;
/// Usually -3600 or 3600, but look at Lord Howe Island.
Int16
amount_of_offset_change
;
/// Usually -3600 or 3600, but look at Lord Howe Island.
...
@@ -217,13 +221,20 @@ public:
...
@@ -217,13 +221,20 @@ public:
return
lut
[
index
-
(
lut
[
index
].
day_of_month
-
1
)].
date
;
return
lut
[
index
-
(
lut
[
index
].
day_of_month
-
1
)].
date
;
}
}
inline
size_t
daysInMonth
(
DayNum_t
d
)
const
{
return
lut
[
d
].
days_in_month
;
}
inline
size_t
daysInMonth
(
time_t
t
)
const
inline
size_t
daysInMonth
(
time_t
t
)
const
{
{
size_t
today
=
findIndex
(
t
);
return
find
(
t
).
days_in_month
;
size_t
start_of_month
=
today
-
(
lut
[
today
].
day_of_month
-
1
);
}
size_t
next_month
=
start_of_month
+
31
;
size_t
start_of_next_month
=
next_month
-
(
lut
[
next_month
].
day_of_month
-
1
);
inline
size_t
daysInMonth
(
short
year
,
char
month
)
const
return
start_of_next_month
-
start_of_month
;
{
auto
any_day_of_month
=
years_lut
[
year
-
DATE_LUT_MIN_YEAR
]
+
31
*
(
month
-
1
);
return
lut
[
any_day_of_month
].
days_in_month
;
}
}
/** Round to start of day, then shift for specified amount of days.
/** Round to start of day, then shift for specified amount of days.
...
@@ -445,6 +456,122 @@ public:
...
@@ -445,6 +456,122 @@ public:
num
%
100
);
num
%
100
);
}
}
/// Adding calendar intervals.
/// Implementation specific behaviour when delta is too big.
inline
time_t
addDays
(
time_t
t
,
ssize_t
delta
)
const
{
size_t
index
=
findIndex
(
t
);
time_t
time_offset
=
toHour
(
t
)
*
3600
+
toMinute
(
t
)
*
60
+
toSecond
(
t
);
index
+=
delta
;
if
(
time_offset
>=
lut
[
index
].
time_at_offset_change
)
time_offset
-=
lut
[
index
].
amount_of_offset_change
;
return
lut
[
index
].
date
+
time_offset
;
}
inline
time_t
addWeeks
(
time_t
t
,
ssize_t
delta
)
const
{
return
addDays
(
t
,
delta
*
7
);
}
inline
char
saturateDayOfMonth
(
short
year
,
char
month
,
char
day_of_month
)
const
{
if
(
likely
(
day_of_month
<=
28
))
return
day_of_month
;
auto
days_in_month
=
daysInMonth
(
year
,
month
);
if
(
day_of_month
>
days_in_month
)
day_of_month
=
days_in_month
;
return
day_of_month
;
}
/// If resulting month has less deys than source month, then saturation can happen.
/// Example: 31 Aug + 1 month = 30 Sep.
inline
time_t
addMonths
(
time_t
t
,
ssize_t
delta
)
const
{
size_t
index
=
findIndex
(
t
);
const
Values
&
values
=
lut
[
index
];
time_t
time_offset
=
toHour
(
t
)
*
3600
+
toMinute
(
t
)
*
60
+
toSecond
(
t
);
auto
month
=
values
.
month
+
delta
;
bool
year_will_be_next
=
month
>
12
;
if
(
year_will_be_next
)
month
-=
12
;
auto
year
=
values
.
year
+
year_will_be_next
;
auto
day_of_month
=
saturateDayOfMonth
(
year
,
month
,
values
.
day_of_month
);
DayNum_t
result_day
=
makeDayNum
(
year
,
month
,
day_of_month
);
if
(
time_offset
>=
lut
[
result_day
].
time_at_offset_change
)
time_offset
-=
lut
[
result_day
].
amount_of_offset_change
;
return
lut
[
result_day
].
date
+
time_offset
;
}
inline
DayNum_t
addMonths
(
DayNum_t
d
,
ssize_t
delta
)
const
{
const
Values
&
values
=
lut
[
d
];
auto
month
=
values
.
month
+
delta
;
bool
year_will_be_next
=
month
>
12
;
if
(
year_will_be_next
)
month
-=
12
;
auto
year
=
values
.
year
+
year_will_be_next
;
auto
day_of_month
=
saturateDayOfMonth
(
year
,
month
,
values
.
day_of_month
);
return
makeDayNum
(
year
,
month
,
day_of_month
);
}
/// Saturation can occur if 29 Feb is mapped to non-leap year.
inline
time_t
addYears
(
time_t
t
,
ssize_t
delta
)
const
{
size_t
index
=
findIndex
(
t
);
const
Values
&
values
=
lut
[
index
];
time_t
time_offset
=
toHour
(
t
)
*
3600
+
toMinute
(
t
)
*
60
+
toSecond
(
t
);
auto
year
=
values
.
year
+
delta
;
auto
month
=
values
.
month
;
auto
day_of_month
=
values
.
day_of_month
;
/// Saturation to 28 Feb can happen.
if
(
unlikely
(
day_of_month
==
29
&&
month
==
2
))
day_of_month
=
saturateDayOfMonth
(
year
,
month
,
day_of_month
);
DayNum_t
result_day
=
makeDayNum
(
year
,
month
,
day_of_month
);
if
(
time_offset
>=
lut
[
result_day
].
time_at_offset_change
)
time_offset
-=
lut
[
result_day
].
amount_of_offset_change
;
return
lut
[
result_day
].
date
+
time_offset
;
}
inline
DayNum_t
addYears
(
DayNum_t
d
,
ssize_t
delta
)
const
{
const
Values
&
values
=
lut
[
d
];
auto
year
=
values
.
year
+
delta
;
auto
month
=
values
.
month
;
auto
day_of_month
=
values
.
day_of_month
;
/// Saturation to 28 Feb can happen.
if
(
unlikely
(
day_of_month
==
29
&&
month
==
2
))
day_of_month
=
saturateDayOfMonth
(
year
,
month
,
day_of_month
);
return
makeDayNum
(
year
,
month
,
day_of_month
);
}
inline
std
::
string
timeToString
(
time_t
t
)
const
inline
std
::
string
timeToString
(
time_t
t
)
const
{
{
const
Values
&
values
=
find
(
t
);
const
Values
&
values
=
find
(
t
);
...
...
libs/libcommon/src/DateLUTImpl.cpp
浏览文件 @
7ecc63fe
...
@@ -64,6 +64,14 @@ DateLUTImpl::DateLUTImpl(const std::string & time_zone_)
...
@@ -64,6 +64,14 @@ DateLUTImpl::DateLUTImpl(const std::string & time_zone_)
values
.
day_of_week
=
getDayOfWeek
(
date
);
values
.
day_of_week
=
getDayOfWeek
(
date
);
values
.
date
=
start_of_day
;
values
.
date
=
start_of_day
;
if
(
values
.
day_of_month
==
1
)
{
cctz
::
civil_month
month
(
date
);
values
.
days_in_month
=
cctz
::
civil_day
(
month
+
1
)
-
cctz
::
civil_day
(
month
);
}
else
values
.
days_in_month
=
i
!=
0
?
lut
[
i
-
1
].
days_in_month
:
31
;
values
.
time_at_offset_change
=
0
;
values
.
time_at_offset_change
=
0
;
values
.
amount_of_offset_change
=
0
;
values
.
amount_of_offset_change
=
0
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录