Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
04c2fd11
提交
04c2fd11
authored
7 年前
作者:
Evgenij Ryazanov
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Reimplement DATEADD without a Calendar and correct its return type
上级
f011b5bc
显示空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
118 行增加
和
39 行删除
+118
-39
Function.java
h2/src/main/org/h2/expression/Function.java
+59
-35
DateTimeUtils.java
h2/src/main/org/h2/util/DateTimeUtils.java
+34
-0
dateadd.sql
...est/org/h2/test/scripts/functions/timeanddate/dateadd.sql
+22
-1
testScript.sql
h2/src/test/org/h2/test/scripts/testScript.sql
+3
-3
没有找到文件。
h2/src/main/org/h2/expression/Function.java
浏览文件 @
04c2fd11
...
...
@@ -14,7 +14,6 @@ import java.nio.charset.StandardCharsets;
import
java.sql.Connection
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.sql.Timestamp
;
import
java.text.SimpleDateFormat
;
import
java.util.ArrayList
;
import
java.util.Calendar
;
...
...
@@ -1485,8 +1484,7 @@ public class Function extends Expression implements FunctionCall {
database
.
getMode
().
treatEmptyStringsAsNull
);
break
;
case
DATE_ADD:
result
=
ValueTimestamp
.
get
(
dateadd
(
v0
.
getString
(),
v1
.
getLong
(),
v2
.
getTimestamp
()));
result
=
dateadd
(
v0
.
getString
(),
v1
.
getLong
(),
v2
);
break
;
case
DATE_DIFF:
result
=
ValueLong
.
get
(
datediff
(
v0
.
getString
(),
v1
,
v2
));
...
...
@@ -1805,53 +1803,79 @@ public class Function extends Expression implements FunctionCall {
return
p
.
intValue
();
}
private
static
Timestamp
dateadd
(
String
part
,
long
count
,
Timestamp
d
)
{
private
static
Value
dateadd
(
String
part
,
long
count
,
Value
v
)
{
int
field
=
getDatePart
(
part
);
//v = v.convertTo(Value.TIMESTAMP);
if
(
field
!=
MILLISECOND
&&
count
>
Integer
.
MAX_VALUE
||
count
<
Integer
.
MIN_VALUE
)
{
throw
DbException
.
getInvalidValueException
(
"DATEADD count"
,
count
);
}
boolean
withDate
=
!(
v
instanceof
ValueTime
),
withTime
=
!(
v
instanceof
ValueDate
),
forceTimestamp
=
false
;
long
[]
a
=
DateTimeUtils
.
dateAndTimeFromValue
(
v
);
long
dateValue
=
a
[
0
];
long
timeNanos
=
a
[
1
];
switch
(
field
)
{
case
YEAR:
field
=
Calendar
.
YEAR
;
break
;
case
MONTH:
field
=
Calendar
.
MONTH
;
break
;
case
MONTH:
{
if
(!
withDate
)
{
throw
DbException
.
getInvalidValueException
(
"DATEADD timestamp"
,
v
);
}
long
year
=
DateTimeUtils
.
yearFromDateValue
(
dateValue
);
long
month
=
DateTimeUtils
.
monthFromDateValue
(
dateValue
);
int
day
=
DateTimeUtils
.
dayFromDateValue
(
dateValue
);
if
(
field
==
YEAR
)
{
year
+=
count
;
}
else
{
month
+=
count
;
}
dateValue
=
DateTimeUtils
.
dateValueFromDenormalizedDate
(
year
,
month
,
day
);
return
DateTimeUtils
.
dateTimeToValue
(
v
,
dateValue
,
timeNanos
,
forceTimestamp
);
}
case
WEEK:
case
ISO_WEEK:
count
*=
7
;
//$FALL-THROUGH$
case
DAY_OF_WEEK:
case
DAY_OF_MONTH:
field
=
Calendar
.
DAY_OF_MONTH
;
break
;
case
DAY_OF_YEAR:
field
=
Calendar
.
DAY_OF_YEAR
;
break
;
case
WEEK:
field
=
Calendar
.
WEEK_OF_YEAR
;
break
;
if
(!
withDate
)
{
throw
DbException
.
getInvalidValueException
(
"DATEADD timestamp"
,
v
);
}
dateValue
=
DateTimeUtils
.
dateValueFromAbsoluteDay
(
DateTimeUtils
.
absoluteDayFromDateValue
(
dateValue
)
+
count
);
return
DateTimeUtils
.
dateTimeToValue
(
v
,
dateValue
,
timeNanos
,
forceTimestamp
);
case
HOUR:
field
=
Calendar
.
HOUR_OF_DAY
;
count
*=
3_600_000_000_000L
;
break
;
case
MINUTE:
field
=
Calendar
.
MINUTE
;
count
*=
60_000_000_000L
;
break
;
case
SECOND:
field
=
Calendar
.
SECOND
;
count
*=
1_000_000_000
;
break
;
case
MILLISECOND:
count
*=
1_000_000
;
break
;
case
MILLISECOND:
{
Timestamp
ts
=
new
Timestamp
(
d
.
getTime
()
+
count
);
ts
.
setNanos
(
ts
.
getNanos
()
+
(
d
.
getNanos
()
%
1000000
));
return
ts
;
}
default
:
throw
DbException
.
getUnsupportedException
(
"DATEADD "
+
part
);
}
// We allow long for manipulating the millisecond component,
// for the rest we only allow int.
if
(
count
>
Integer
.
MAX_VALUE
)
{
throw
DbException
.
getInvalidValueException
(
"DATEADD count"
,
count
);
if
(!
withTime
)
{
// Treat date as timestamp at the start of this date
forceTimestamp
=
true
;
}
timeNanos
+=
count
;
if
(
timeNanos
>
DateTimeUtils
.
NANOS_PER_DAY
||
timeNanos
<
0
)
{
long
d
;
if
(
timeNanos
>
DateTimeUtils
.
NANOS_PER_DAY
)
{
d
=
timeNanos
/
DateTimeUtils
.
NANOS_PER_DAY
;
}
else
{
d
=
(
timeNanos
-
DateTimeUtils
.
NANOS_PER_DAY
+
1
)
/
DateTimeUtils
.
NANOS_PER_DAY
;
}
timeNanos
-=
d
*
DateTimeUtils
.
NANOS_PER_DAY
;
return
DateTimeUtils
.
dateTimeToValue
(
v
,
DateTimeUtils
.
dateValueFromAbsoluteDay
(
DateTimeUtils
.
absoluteDayFromDateValue
(
dateValue
)
+
d
),
timeNanos
,
forceTimestamp
);
}
Calendar
calendar
=
DateTimeUtils
.
createGregorianCalendar
();
int
nanos
=
d
.
getNanos
()
%
1000000
;
calendar
.
setTime
(
d
);
calendar
.
add
(
field
,
(
int
)
count
);
Timestamp
ts
=
new
Timestamp
(
calendar
.
getTimeInMillis
());
ts
.
setNanos
(
ts
.
getNanos
()
+
nanos
);
return
ts
;
return
DateTimeUtils
.
dateTimeToValue
(
v
,
dateValue
,
timeNanos
,
forceTimestamp
);
}
/**
...
...
This diff is collapsed.
Click to expand it.
h2/src/main/org/h2/util/DateTimeUtils.java
浏览文件 @
04c2fd11
...
...
@@ -591,6 +591,40 @@ public class DateTimeUtils {
return
new
long
[]
{
dateValue
,
timeNanos
};
}
/**
* Creates a new date-time value with the same type as original value. If
* original value is a ValueTimestampTimeZone, returned value will have the same
* time zone offset as original value.
*
* @param original
* original value
* @param dateValue
* date value for the returned value
* @param timeNanos
* nanos of day for the returned value
* @param forceTimestamp
* if {@code true} return ValueTimestamp if original argument is
* ValueDate or ValueTime
* @return new value with specified date value and nanos of day
*/
public
static
Value
dateTimeToValue
(
Value
original
,
long
dateValue
,
long
timeNanos
,
boolean
forceTimestamp
)
{
if
(!(
original
instanceof
ValueTimestamp
))
{
if
(!
forceTimestamp
)
{
if
(
original
instanceof
ValueDate
)
{
return
ValueDate
.
fromDateValue
(
dateValue
);
}
if
(
original
instanceof
ValueTime
)
{
return
ValueTime
.
fromNanos
(
timeNanos
);
}
}
if
(
original
instanceof
ValueTimestampTimeZone
)
{
return
ValueTimestampTimeZone
.
fromDateValueAndNanos
(
dateValue
,
timeNanos
,
((
ValueTimestampTimeZone
)
original
).
getTimeZoneOffsetMins
());
}
}
return
ValueTimestamp
.
fromDateValueAndNanos
(
dateValue
,
timeNanos
);
}
/**
* Get the specified field of a date, however with years normalized to
* positive or negative, and month starting with 1.
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/scripts/functions/timeanddate/dateadd.sql
浏览文件 @
04c2fd11
...
...
@@ -81,7 +81,7 @@ select d + t, t + d - t x from test;
select
1
+
d
+
1
,
d
-
1
,
2
+
ts
+
2
,
ts
-
2
from
test
;
>
DATEADD
(
'DAY'
,
1
,
DATEADD
(
'DAY'
,
1
,
D
))
DATEADD
(
'DAY'
,
-
1
,
D
)
DATEADD
(
'DAY'
,
2
,
DATEADD
(
'DAY'
,
2
,
TS
))
DATEADD
(
'DAY'
,
-
2
,
TS
)
>
--------------------------------------- --------------------- ---------------------------------------- ----------------------
>
2001
-
01
-
03
00
:
00
:
00
.
0
2000
-
12
-
31
00
:
00
:
00
.
0
2010
-
01
-
05
00
:
00
:
00
.
0
2009
-
12
-
30
00
:
00
:
00
.
0
>
2001
-
01
-
03
2000
-
12
-
31
2010
-
01
-
05
00
:
00
:
00
.
0
2009
-
12
-
30
00
:
00
:
00
.
0
>
rows
:
1
select
1
+
d
+
t
+
1
from
test
;
...
...
@@ -104,3 +104,24 @@ call dateadd('MS', 1, TIMESTAMP '2001-02-03 04:05:06.789001');
>
--------------------------------------
>
2001
-
02
-
03
04
:
05
:
06
.
790001
>
rows
:
1
SELECT
DATEADD
(
'HOUR'
,
1
,
DATE
'2010-01-20'
);
>
TIMESTAMP
'2010-01-20 01:00:00.0'
>
---------------------------------
>
2010
-
01
-
20
01
:
00
:
00
.
0
>
rows
:
1
SELECT
DATEADD
(
'MINUTE'
,
30
,
TIME
'12:30:55'
);
>
TIME
'13:00:55'
>
---------------
>
13
:
00
:
55
>
rows
:
1
SELECT
DATEADD
(
'DAY'
,
1
,
TIME
'12:30:55'
);
>
exception
SELECT
DATEADD
(
'DAY'
,
10
,
TIMESTAMP
WITH
TIME
ZONE
'2000-01-05 15:00:30.123456789-10'
);
>
TIMESTAMP
WITH
TIME
ZONE
'2000-01-15 15:00:30.123456789-10'
>
-----------------------------------------------------------
>
2000
-
01
-
15
15
:
00
:
30
.
123456789
-
10
>
rows
:
1
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/scripts/testScript.sql
浏览文件 @
04c2fd11
...
...
@@ -7586,9 +7586,9 @@ SELECT * FROM TEST;
SELECT
XD
+
1
,
XD
-
1
,
XD
-
XD
FROM
TEST
;
>
DATEADD
(
'DAY'
,
1
,
XD
)
DATEADD
(
'DAY'
,
-
1
,
XD
)
DATEDIFF
(
'DAY'
,
XD
,
XD
)
>
--------------------- ---------------------- -----------------------
>
0001
-
02
-
04
00
:
00
:
00
.
0
0001
-
02
-
02
00
:
00
:
00
.
0
0
>
0004
-
05
-
07
00
:
00
:
00
.
0
0004
-
05
-
05
00
:
00
:
00
.
0
0
>
2000
-
01
-
01
00
:
00
:
00
.
0
1999
-
12
-
30
00
:
00
:
00
.
0
0
>
0001
-
02
-
04
0001
-
02
-
02
0
>
0004
-
05
-
07
0004
-
05
-
05
0
>
2000
-
01
-
01
1999
-
12
-
30
0
>
null
null
null
>
rows
:
4
...
...
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论