Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
71fee8d6
提交
71fee8d6
authored
7 年前
作者:
Evgenij Ryazanov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Reimplement DATEDIFF without a Calendar
上级
e856bfb1
隐藏空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
71 行增加
和
57 行删除
+71
-57
Function.java
h2/src/main/org/h2/expression/Function.java
+47
-57
datediff.sql
...st/org/h2/test/scripts/functions/timeanddate/datediff.sql
+24
-0
没有找到文件。
h2/src/main/org/h2/expression/Function.java
浏览文件 @
71fee8d6
...
...
@@ -20,7 +20,6 @@ import java.util.ArrayList;
import
java.util.Calendar
;
import
java.util.HashMap
;
import
java.util.Locale
;
import
java.util.TimeZone
;
import
java.util.regex.Pattern
;
import
java.util.regex.PatternSyntaxException
;
...
...
@@ -175,6 +174,7 @@ public class Function extends Expression implements FunctionCall {
DATE_PART
.
put
(
"WW"
,
WEEK
);
DATE_PART
.
put
(
"WK"
,
WEEK
);
DATE_PART
.
put
(
"WEEK"
,
WEEK
);
DATE_PART
.
put
(
"ISO_WEEK"
,
ISO_WEEK
);
DATE_PART
.
put
(
"DAY"
,
DAY_OF_MONTH
);
DATE_PART
.
put
(
"DD"
,
DAY_OF_MONTH
);
DATE_PART
.
put
(
"D"
,
DAY_OF_MONTH
);
...
...
@@ -1489,8 +1489,7 @@ public class Function extends Expression implements FunctionCall {
v0
.
getString
(),
v1
.
getLong
(),
v2
.
getTimestamp
()));
break
;
case
DATE_DIFF:
result
=
ValueLong
.
get
(
datediff
(
v0
.
getString
(),
v1
.
getTimestamp
(),
v2
.
getTimestamp
()));
result
=
ValueLong
.
get
(
datediff
(
v0
.
getString
(),
v1
,
v2
));
break
;
case
EXTRACT:
{
int
field
=
getDatePart
(
v0
.
getString
());
...
...
@@ -1863,79 +1862,70 @@ public class Function extends Expression implements FunctionCall {
* </pre>
*
* @param part the part
* @param
d1 the first dat
e
* @param
d2 the second dat
e
* @param
v1 the first date-time valu
e
* @param
v2 the second date-time valu
e
* @return the number of crossed boundaries
*/
private
static
long
datediff
(
String
part
,
Timestamp
d1
,
Timestamp
d
2
)
{
private
static
long
datediff
(
String
part
,
Value
v1
,
Value
v
2
)
{
int
field
=
getDatePart
(
part
);
Calendar
calendar
=
DateTimeUtils
.
createGregorianCalendar
();
long
t1
=
d1
.
getTime
(),
t2
=
d2
.
getTime
();
// need to convert to UTC, otherwise we get inconsistent results with
// certain time zones (those that are 30 minutes off)
TimeZone
zone
=
calendar
.
getTimeZone
();
calendar
.
setTime
(
d1
);
t1
+=
zone
.
getOffset
(
calendar
.
get
(
Calendar
.
ERA
),
calendar
.
get
(
Calendar
.
YEAR
),
calendar
.
get
(
Calendar
.
MONTH
),
calendar
.
get
(
Calendar
.
DAY_OF_MONTH
),
calendar
.
get
(
Calendar
.
DAY_OF_WEEK
),
calendar
.
get
(
Calendar
.
MILLISECOND
));
calendar
.
setTime
(
d2
);
t2
+=
zone
.
getOffset
(
calendar
.
get
(
Calendar
.
ERA
),
calendar
.
get
(
Calendar
.
YEAR
),
calendar
.
get
(
Calendar
.
MONTH
),
calendar
.
get
(
Calendar
.
DAY_OF_MONTH
),
calendar
.
get
(
Calendar
.
DAY_OF_WEEK
),
calendar
.
get
(
Calendar
.
MILLISECOND
));
long
[]
a1
=
DateTimeUtils
.
dateAndTimeFromValue
(
v1
);
long
dateValue1
=
a1
[
0
];
long
absolute1
=
DateTimeUtils
.
absoluteDayFromDateValue
(
dateValue1
);
long
[]
a2
=
DateTimeUtils
.
dateAndTimeFromValue
(
v2
);
long
dateValue2
=
a2
[
0
];
long
absolute2
=
DateTimeUtils
.
absoluteDayFromDateValue
(
dateValue2
);
switch
(
field
)
{
case
MILLISECOND:
return
t2
-
t1
;
case
SECOND:
case
MINUTE:
case
HOUR:
case
DAY_OF_YEAR:
case
WEEK:
{
// first 'normalize' the numbers so both are not negative
long
hour
=
60
*
60
*
1000
;
long
add
=
Math
.
min
(
t1
/
hour
*
hour
,
t2
/
hour
*
hour
);
t1
-=
add
;
t2
-=
add
;
long
timeNanos1
=
a1
[
1
];
long
timeNanos2
=
a2
[
1
];
switch
(
field
)
{
case
MILLISECOND:
return
(
absolute2
-
absolute1
)
*
DateTimeUtils
.
MILLIS_PER_DAY
+
(
timeNanos2
/
1_000_000
-
timeNanos1
/
1_000_000
);
case
SECOND:
return
t2
/
1000
-
t1
/
1000
;
return
(
absolute2
-
absolute1
)
*
86_400
+
(
timeNanos2
/
1_000_000_000
-
timeNanos1
/
1_000_000_000
);
case
MINUTE:
return
t2
/
(
60
*
1000
)
-
t1
/
(
60
*
1000
);
return
(
absolute2
-
absolute1
)
*
1_440
+
(
timeNanos2
/
60_000_000_000L
-
timeNanos1
/
60_000_000_000L
);
case
HOUR:
return
t2
/
hour
-
t1
/
hour
;
case
DAY_OF_YEAR:
return
t2
/
(
hour
*
24
)
-
t1
/
(
hour
*
24
);
case
WEEK:
return
t2
/
(
hour
*
24
*
7
)
-
t1
/
(
hour
*
24
*
7
);
default
:
throw
DbException
.
throwInternalError
(
"field:"
+
field
);
return
(
absolute2
-
absolute1
)
*
24
+
(
timeNanos2
/
3_600_000_000_000L
-
timeNanos1
/
3_600_000_000_000L
);
}
}
// Fake fall-through
//$FALL-THROUGH$
case
DAY_OF_MONTH:
return
t2
/
(
24
*
60
*
60
*
1000
)
-
t1
/
(
24
*
60
*
60
*
1000
);
case
DAY_OF_YEAR:
return
absolute2
-
absolute1
;
case
WEEK:
return
weekdiff
(
absolute1
,
absolute2
,
0
);
case
ISO_WEEK:
return
weekdiff
(
absolute1
,
absolute2
,
1
);
case
MONTH:
return
(
DateTimeUtils
.
yearFromDateValue
(
dateValue2
)
-
DateTimeUtils
.
yearFromDateValue
(
dateValue1
))
*
12
+
DateTimeUtils
.
monthFromDateValue
(
dateValue2
)
-
DateTimeUtils
.
monthFromDateValue
(
dateValue1
);
case
YEAR:
return
DateTimeUtils
.
yearFromDateValue
(
dateValue2
)
-
DateTimeUtils
.
yearFromDateValue
(
dateValue1
);
default
:
break
;
}
calendar
=
DateTimeUtils
.
createGregorianCalendar
(
DateTimeUtils
.
UTC
);
calendar
.
setTimeInMillis
(
t1
);
int
year1
=
calendar
.
get
(
Calendar
.
YEAR
);
int
month1
=
calendar
.
get
(
Calendar
.
MONTH
);
calendar
.
setTimeInMillis
(
t2
);
int
year2
=
calendar
.
get
(
Calendar
.
YEAR
);
int
month2
=
calendar
.
get
(
Calendar
.
MONTH
);
int
result
=
year2
-
year1
;
if
(
field
==
MONTH
)
{
return
12
*
result
+
(
month2
-
month1
);
}
else
if
(
field
==
YEAR
)
{
return
result
;
}
else
{
throw
DbException
.
getUnsupportedException
(
"DATEDIFF "
+
part
);
}
}
private
static
long
weekdiff
(
long
absolute1
,
long
absolute2
,
int
firstDayOfWeek
)
{
long
r1
=
(
absolute1
-
firstDayOfWeek
+
4
)
/
7
;
if
(
absolute1
<
0
&&
(
r1
*
7
!=
absolute1
))
{
r1
--;
}
long
r2
=
(
absolute2
-
firstDayOfWeek
+
4
)
/
7
;
if
(
absolute2
<
0
&&
(
r2
*
7
!=
absolute2
))
{
r2
--;
}
return
r2
-
r1
;
}
private
static
String
substring
(
String
s
,
int
start
,
int
length
)
{
int
len
=
s
.
length
();
start
--;
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/scripts/functions/timeanddate/datediff.sql
浏览文件 @
71fee8d6
...
...
@@ -158,3 +158,27 @@ call datediff('MS', TIMESTAMP '1900-01-01 00:00:01.000', TIMESTAMP '2008-01-01 0
>
-------------
>
3408134399000
>
rows
:
1
SELECT
DATEDIFF
(
'WEEK'
,
DATE
'2018-02-02'
,
DATE
'2018-02-03'
),
DATEDIFF
(
'ISO_WEEK'
,
DATE
'2018-02-02'
,
DATE
'2018-02-03'
);
>
0
0
>
-
-
>
0
0
>
rows
:
1
SELECT
DATEDIFF
(
'WEEK'
,
DATE
'2018-02-03'
,
DATE
'2018-02-04'
),
DATEDIFF
(
'ISO_WEEK'
,
DATE
'2018-02-03'
,
DATE
'2018-02-04'
);
>
1
0
>
-
-
>
1
0
>
rows
:
1
SELECT
DATEDIFF
(
'WEEK'
,
DATE
'2018-02-04'
,
DATE
'2018-02-05'
),
DATEDIFF
(
'ISO_WEEK'
,
DATE
'2018-02-04'
,
DATE
'2018-02-05'
);
>
0
1
>
-
-
>
0
1
>
rows
:
1
SELECT
DATEDIFF
(
'WEEK'
,
DATE
'2018-02-05'
,
DATE
'2018-02-06'
),
DATEDIFF
(
'ISO_WEEK'
,
DATE
'2018-02-05'
,
DATE
'2018-02-06'
);
>
0
0
>
-
-
>
0
0
>
rows
:
1
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论