Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
7224c100
提交
7224c100
authored
2月 22, 2016
作者:
Noel Grandin
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Experimental support for datatype TIMESTAMP WITH TIMEZONE
上级
86792ec9
隐藏空白字符变更
内嵌
并排
正在显示
14 个修改的文件
包含
606 行增加
和
5 行删除
+606
-5
changelog.html
h2/src/docsrc/html/changelog.html
+2
-0
TimestampWithTimeZone.java
h2/src/main/org/h2/api/TimestampWithTimeZone.java
+57
-0
Parser.java
h2/src/main/org/h2/command/Parser.java
+5
-0
JdbcConnection.java
h2/src/main/org/h2/jdbc/JdbcConnection.java
+0
-1
ValueDataType.java
h2/src/main/org/h2/mvstore/db/ValueDataType.java
+20
-0
Data.java
h2/src/main/org/h2/store/Data.java
+22
-0
Column.java
h2/src/main/org/h2/table/Column.java
+3
-0
DataType.java
h2/src/main/org/h2/value/DataType.java
+17
-0
Transfer.java
h2/src/main/org/h2/value/Transfer.java
+10
-0
Value.java
h2/src/main/org/h2/value/Value.java
+59
-1
ValueTimestampTimeZone.java
h2/src/main/org/h2/value/ValueTimestampTimeZone.java
+356
-0
TestAll.java
h2/src/test/org/h2/test/TestAll.java
+6
-2
TestTimeStampWithTimeZone.java
h2/src/test/org/h2/test/unit/TestTimeStampWithTimeZone.java
+46
-0
TestValueMemory.java
h2/src/test/org/h2/test/unit/TestValueMemory.java
+3
-1
没有找到文件。
h2/src/docsrc/html/changelog.html
浏览文件 @
7224c100
...
...
@@ -21,6 +21,8 @@ Change Log
<h2>
Next Version (unreleased)
</h2>
<ul>
<li>
Experimental support for datatype TIMESTAMP WITH TIMEZONE
</li>
<li>
Add support for ALTER TABLE ... RENAME CONSTRAINT .. TO ...
</li>
<li>
Add support for PostgreSQL ALTER TABLE ... RENAME COLUMN .. TO ...
...
...
h2/src/main/org/h2/api/TimestampWithTimeZone.java
0 → 100644
浏览文件 @
7224c100
/*
* Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
api
;
import
java.sql.Timestamp
;
/**
* Extends java.sql.Timestamp to add our time zone information.
*
*/
public
class
TimestampWithTimeZone
extends
Timestamp
{
/**
* Time zone offset from UTC in minutes, range of -12hours to +12hours
*/
private
final
short
timeZoneOffsetMins
;
public
TimestampWithTimeZone
(
long
time_ms
,
int
nanos
,
short
timeZoneOffsetMins
)
{
super
(
time_ms
);
setNanos
(
nanos
);
this
.
timeZoneOffsetMins
=
timeZoneOffsetMins
;
}
/**
* The timezone offset in minutes.
*
* @return the offset
*/
public
short
getTimeZoneOffsetMins
()
{
return
timeZoneOffsetMins
;
}
@Override
public
int
hashCode
()
{
final
int
prime
=
31
;
int
result
=
super
.
hashCode
();
result
=
prime
*
result
+
timeZoneOffsetMins
;
return
result
;
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
return
true
;
if
(!
super
.
equals
(
obj
))
return
false
;
if
(
getClass
()
!=
obj
.
getClass
())
return
false
;
TimestampWithTimeZone
other
=
(
TimestampWithTimeZone
)
obj
;
if
(
timeZoneOffsetMins
!=
other
.
timeZoneOffsetMins
)
return
false
;
return
true
;
}
}
h2/src/main/org/h2/command/Parser.java
浏览文件 @
7224c100
...
...
@@ -4033,6 +4033,11 @@ public class Parser {
if
(
readIf
(
"VARYING"
))
{
original
+=
" VARYING"
;
}
}
else
if
(
readIf
(
"TIMESTAMP"
))
{
if
(
readIf
(
"WITH"
))
{
read
(
"TIMEZONE"
);
original
+=
" WITH TIMEZONE"
;
}
}
else
{
regular
=
true
;
}
...
...
h2/src/main/org/h2/jdbc/JdbcConnection.java
浏览文件 @
7224c100
...
...
@@ -28,7 +28,6 @@ import java.sql.Struct;
import
java.util.ArrayList
;
import
java.util.Map
;
import
java.util.Properties
;
import
org.h2.api.ErrorCode
;
import
org.h2.command.CommandInterface
;
import
org.h2.engine.ConnectionInfo
;
...
...
h2/src/main/org/h2/mvstore/db/ValueDataType.java
浏览文件 @
7224c100
...
...
@@ -45,6 +45,7 @@ import org.h2.value.ValueStringFixed;
import
org.h2.value.ValueStringIgnoreCase
;
import
org.h2.value.ValueTime
;
import
org.h2.value.ValueTimestamp
;
import
org.h2.value.ValueTimestampTimeZone
;
import
org.h2.value.ValueTimestampUtc
;
import
org.h2.value.ValueUuid
;
...
...
@@ -283,6 +284,19 @@ public class ValueDataType implements DataType {
buff
.
put
((
byte
)
type
).
putVarLong
(
dateTimeValue
);
break
;
}
case
Value
.
TIMESTAMP_TZ
:
{
ValueTimestampTimeZone
ts
=
(
ValueTimestampTimeZone
)
v
;
long
dateValue
=
ts
.
getDateValue
();
long
nanos
=
ts
.
getTimeNanos
();
long
millis
=
nanos
/
1000000
;
nanos
-=
millis
*
1000000
;
buff
.
put
((
byte
)
type
).
putVarLong
(
dateValue
).
putVarLong
(
millis
).
putVarLong
(
nanos
).
putVarInt
(
ts
.
getTimeZoneOffsetMins
());
break
;
}
case
Value
.
JAVA_OBJECT
:
{
byte
[]
b
=
v
.
getBytesNoCopy
();
buff
.
put
((
byte
)
type
).
...
...
@@ -492,6 +506,12 @@ public class ValueDataType implements DataType {
long
dateTimeValue
=
readVarLong
(
buff
);
return
ValueTimestampUtc
.
fromNanos
(
dateTimeValue
);
}
case
Value
.
TIMESTAMP_TZ
:
{
long
dateValue
=
readVarLong
(
buff
);
long
nanos
=
readVarLong
(
buff
)
*
1000000
+
readVarLong
(
buff
);
short
tz
=
(
short
)
readVarInt
(
buff
);
return
ValueTimestampTimeZone
.
fromDateValueAndNanos
(
dateValue
,
nanos
,
tz
);
}
case
Value
.
BYTES
:
{
int
len
=
readVarInt
(
buff
);
byte
[]
b
=
DataUtils
.
newBytes
(
len
);
...
...
h2/src/main/org/h2/store/Data.java
浏览文件 @
7224c100
...
...
@@ -49,6 +49,7 @@ import org.h2.value.ValueStringFixed;
import
org.h2.value.ValueStringIgnoreCase
;
import
org.h2.value.ValueTime
;
import
org.h2.value.ValueTimestamp
;
import
org.h2.value.ValueTimestampTimeZone
;
import
org.h2.value.ValueTimestampUtc
;
import
org.h2.value.ValueUuid
;
...
...
@@ -544,6 +545,13 @@ public class Data {
writeVarLong
(
ts
.
getUtcDateTimeNanos
());
break
;
}
case
Value
.
TIMESTAMP_TZ
:
{
ValueTimestampTimeZone
ts
=
(
ValueTimestampTimeZone
)
v
;
writeByte
((
byte
)
type
);
writeVarLong
(
ts
.
getDateValue
());
writeVarLong
(
ts
.
getTimeNanos
());
writeVarInt
(
ts
.
getTimeZoneOffsetMins
());
}
case
Value
.
GEOMETRY
:
case
Value
.
JAVA_OBJECT
:
{
writeByte
((
byte
)
type
);
...
...
@@ -781,6 +789,12 @@ public class Data {
case
Value
.
TIMESTAMP_UTC
:
{
return
ValueTimestampUtc
.
fromNanos
(
readVarLong
());
}
case
Value
.
TIMESTAMP_TZ
:
{
long
dateValue
=
readVarLong
();
long
nanos
=
readVarLong
();
short
tz
=
(
short
)
readVarInt
();
return
ValueTimestampTimeZone
.
fromDateValueAndNanos
(
dateValue
,
nanos
,
tz
);
}
case
Value
.
BYTES
:
{
int
len
=
readVarInt
();
byte
[]
b
=
DataUtils
.
newBytes
(
len
);
...
...
@@ -1033,6 +1047,14 @@ public class Data {
ValueTimestampUtc
ts
=
(
ValueTimestampUtc
)
v
;
return
1
+
getVarLongLen
(
ts
.
getUtcDateTimeNanos
());
}
case
Value
.
TIMESTAMP_TZ
:
{
ValueTimestampTimeZone
ts
=
(
ValueTimestampTimeZone
)
v
;
long
dateValue
=
ts
.
getDateValue
();
long
nanos
=
ts
.
getTimeNanos
();
short
tz
=
ts
.
getTimeZoneOffsetMins
();
return
1
+
getVarLongLen
(
dateValue
)
+
getVarLongLen
(
nanos
)
+
getVarIntLen
(
tz
);
}
case
Value
.
GEOMETRY
:
case
Value
.
JAVA_OBJECT
:
{
byte
[]
b
=
v
.
getBytesNoCopy
();
...
...
h2/src/main/org/h2/table/Column.java
浏览文件 @
7224c100
...
...
@@ -31,6 +31,7 @@ import org.h2.value.ValueNull;
import
org.h2.value.ValueString
;
import
org.h2.value.ValueTime
;
import
org.h2.value.ValueTimestamp
;
import
org.h2.value.ValueTimestampTimeZone
;
import
org.h2.value.ValueTimestampUtc
;
import
org.h2.value.ValueUuid
;
...
...
@@ -296,6 +297,8 @@ public class Column {
value
=
ValueTimestamp
.
fromMillis
(
session
.
getTransactionStart
());
}
else
if
(
dt
.
type
==
Value
.
TIMESTAMP_UTC
)
{
value
=
ValueTimestampUtc
.
fromMillis
(
session
.
getTransactionStart
());
}
else
if
(
dt
.
type
==
Value
.
TIMESTAMP_TZ
)
{
value
=
ValueTimestampTimeZone
.
fromMillis
(
session
.
getTransactionStart
(),
(
short
)
0
);
}
else
if
(
dt
.
type
==
Value
.
TIME
)
{
value
=
ValueTime
.
fromNanos
(
0
);
}
else
if
(
dt
.
type
==
Value
.
DATE
)
{
...
...
h2/src/main/org/h2/value/DataType.java
浏览文件 @
7224c100
...
...
@@ -23,6 +23,7 @@ import java.util.ArrayList;
import
java.util.HashMap
;
import
java.util.UUID
;
import
org.h2.api.ErrorCode
;
import
org.h2.api.TimestampWithTimeZone
;
import
org.h2.engine.Constants
;
import
org.h2.engine.SessionInterface
;
import
org.h2.engine.SysProperties
;
...
...
@@ -321,6 +322,13 @@ public class DataType {
// 24 for ValueTimestampUtc, 32 for java.sql.Timestamp
56
);
add
(
Value
.
TIMESTAMP_TZ
,
Types
.
OTHER
,
"TimestampTimeZone"
,
createDate
(
ValueTimestampTimeZone
.
PRECISION
,
"TIMESTAMP_TZ"
,
ValueTimestampTimeZone
.
DEFAULT_SCALE
,
ValueTimestampTimeZone
.
DISPLAY_SIZE
),
new
String
[]{
"TIMESTAMP WITH TIMEZONE"
},
// 26 for ValueTimestampUtc, 32 for java.sql.Timestamp
58
);
add
(
Value
.
BYTES
,
Types
.
VARBINARY
,
"Bytes"
,
createString
(
false
),
new
String
[]{
"VARBINARY"
},
...
...
@@ -551,6 +559,12 @@ public class DataType {
ValueTimestampUtc
.
fromMillisNanos
(
value
.
getTime
(),
value
.
getNanos
());
break
;
}
case
Value
.
TIMESTAMP_TZ
:
{
TimestampWithTimeZone
value
=
(
TimestampWithTimeZone
)
rs
.
getTimestamp
(
columnIndex
);
v
=
value
==
null
?
(
Value
)
ValueNull
.
INSTANCE
:
ValueTimestampTimeZone
.
get
(
value
);
break
;
}
case
Value
.
DECIMAL
:
{
BigDecimal
value
=
rs
.
getBigDecimal
(
columnIndex
);
v
=
value
==
null
?
(
Value
)
ValueNull
.
INSTANCE
:
...
...
@@ -726,6 +740,9 @@ public class DataType {
case
Value
.
TIMESTAMP_UTC
:
// "java.sql.Timestamp";
return
Timestamp
.
class
.
getName
();
case
Value
.
TIMESTAMP_TZ
:
// "org.h2.api.TimestampWithTimeZone";
return
TimestampWithTimeZone
.
class
.
getName
();
case
Value
.
BYTES
:
case
Value
.
UUID
:
// "[B", not "byte[]";
...
...
h2/src/main/org/h2/value/Transfer.java
浏览文件 @
7224c100
...
...
@@ -392,6 +392,13 @@ public class Transfer {
writeLong
(
ts
.
getUtcDateTimeNanos
());
break
;
}
case
Value
.
TIMESTAMP_TZ
:
{
ValueTimestampTimeZone
ts
=
(
ValueTimestampTimeZone
)
v
;
writeLong
(
ts
.
getDateValue
());
writeLong
(
ts
.
getTimeNanos
());
writeInt
(
ts
.
getTimeZoneOffsetMins
());
break
;
}
case
Value
.
DECIMAL
:
writeString
(
v
.
getString
());
break
;
...
...
@@ -581,6 +588,9 @@ public class Transfer {
case
Value
.
TIMESTAMP_UTC
:
{
return
ValueTimestampUtc
.
fromNanos
(
readLong
());
}
case
Value
.
TIMESTAMP_TZ
:
{
return
ValueTimestampTimeZone
.
fromDateValueAndNanos
(
readLong
(),
readLong
(),
(
short
)
readInt
());
}
case
Value
.
DECIMAL
:
return
ValueDecimal
.
get
(
new
BigDecimal
(
readString
()));
case
Value
.
DOUBLE
:
...
...
h2/src/main/org/h2/value/Value.java
浏览文件 @
7224c100
...
...
@@ -162,11 +162,15 @@ public abstract class Value {
* The value type for TIMESTAMP UTC values.
*/
public
static
final
int
TIMESTAMP_UTC
=
23
;
/**
* The value type for TIMESTAMP WITH TIMEZONE values.
*/
public
static
final
int
TIMESTAMP_TZ
=
24
;
/**
* The number of value types.
*/
public
static
final
int
TYPE_COUNT
=
TIMESTAMP_
UTC
+
1
;
public
static
final
int
TYPE_COUNT
=
TIMESTAMP_
TZ
+
1
;
private
static
SoftReference
<
Value
[]>
softCache
=
new
SoftReference
<
Value
[]>(
null
);
...
...
@@ -304,6 +308,8 @@ public abstract class Value {
return
32
;
case
TIMESTAMP_UTC:
return
33
;
case
TIMESTAMP_TZ:
return
34
;
case
BYTES:
return
40
;
case
BLOB:
...
...
@@ -548,6 +554,7 @@ public abstract class Value {
case
DATE:
case
TIMESTAMP:
case
TIMESTAMP_UTC:
case
TIMESTAMP_TZ:
case
BYTES:
case
JAVA_OBJECT:
case
UUID:
...
...
@@ -575,6 +582,9 @@ public abstract class Value {
return
ValueByte
.
get
(
convertToByte
(
convertToLong
(
getFloat
())));
case
BYTES:
return
ValueByte
.
get
((
byte
)
Integer
.
parseInt
(
getString
(),
16
));
case
TIMESTAMP_TZ:
throw
DbException
.
get
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
getString
());
}
break
;
}
...
...
@@ -597,6 +607,9 @@ public abstract class Value {
return
ValueShort
.
get
(
convertToShort
(
convertToLong
(
getFloat
())));
case
BYTES:
return
ValueShort
.
get
((
short
)
Integer
.
parseInt
(
getString
(),
16
));
case
TIMESTAMP_TZ:
throw
DbException
.
get
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
getString
());
}
break
;
}
...
...
@@ -619,6 +632,9 @@ public abstract class Value {
return
ValueInt
.
get
(
convertToInt
(
convertToLong
(
getFloat
())));
case
BYTES:
return
ValueInt
.
get
((
int
)
Long
.
parseLong
(
getString
(),
16
));
case
TIMESTAMP_TZ:
throw
DbException
.
get
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
getString
());
}
break
;
}
...
...
@@ -648,6 +664,9 @@ public abstract class Value {
}
case
TIMESTAMP_UTC:
return
ValueLong
.
get
(
getLong
());
case
TIMESTAMP_TZ:
throw
DbException
.
get
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
getString
());
}
break
;
}
...
...
@@ -682,6 +701,9 @@ public abstract class Value {
// better rounding behavior than BigDecimal.valueOf(f)
return
ValueDecimal
.
get
(
new
BigDecimal
(
Float
.
toString
(
f
)));
}
case
TIMESTAMP_TZ:
throw
DbException
.
get
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
getString
());
}
break
;
}
...
...
@@ -702,6 +724,9 @@ public abstract class Value {
return
ValueDouble
.
get
(
getBigDecimal
().
doubleValue
());
case
FLOAT:
return
ValueDouble
.
get
(
getFloat
());
case
TIMESTAMP_TZ:
throw
DbException
.
get
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
getString
());
}
break
;
}
...
...
@@ -722,6 +747,9 @@ public abstract class Value {
return
ValueFloat
.
get
(
getBigDecimal
().
floatValue
());
case
DOUBLE:
return
ValueFloat
.
get
((
float
)
getDouble
());
case
TIMESTAMP_TZ:
throw
DbException
.
get
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
getString
());
}
break
;
}
...
...
@@ -738,6 +766,9 @@ public abstract class Value {
case
TIMESTAMP_UTC:
return
ValueDate
.
fromMillis
(
((
ValueTimestampUtc
)
this
).
getUtcDateTimeMillis
());
case
TIMESTAMP_TZ:
return
ValueDate
.
fromDateValue
(
((
ValueTimestampTimeZone
)
this
).
getDateValue
());
}
break
;
}
...
...
@@ -753,6 +784,9 @@ public abstract class Value {
case
TIMESTAMP_UTC:
return
ValueTime
.
fromMillis
(
((
ValueTimestampUtc
)
this
).
getUtcDateTimeMillis
());
case
TIMESTAMP_TZ:
return
ValueTime
.
fromNanos
(
((
ValueTimestampTimeZone
)
this
).
getTimeNanos
());
}
break
;
}
...
...
@@ -768,6 +802,10 @@ public abstract class Value {
return
ValueTimestamp
.
fromMillisNanos
(
((
ValueTimestampUtc
)
this
).
getUtcDateTimeMillis
(),
((
ValueTimestampUtc
)
this
).
getNanosSinceLastMillis
());
case
TIMESTAMP_TZ:
return
ValueTimestamp
.
fromDateValueAndNanos
(
((
ValueTimestampTimeZone
)
this
).
getDateValue
(),
((
ValueTimestampTimeZone
)
this
).
getTimeNanos
());
}
break
;
}
...
...
@@ -793,6 +831,9 @@ public abstract class Value {
return
ValueTimestampUtc
.
fromMillisNanos
(
((
ValueTimestamp
)
this
).
getTimestamp
().
getTime
(),
((
ValueTimestamp
)
this
).
getTimestamp
().
getNanos
());
case
TIMESTAMP_TZ:
// TODO
throw
DbException
.
getUnsupportedException
(
"unimplemented"
);
}
break
;
}
...
...
@@ -835,6 +876,9 @@ public abstract class Value {
(
byte
)
x
});
}
case
TIMESTAMP_TZ:
throw
DbException
.
get
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
getString
());
}
break
;
}
...
...
@@ -844,6 +888,9 @@ public abstract class Value {
case
BLOB:
return
ValueJavaObject
.
getNoCopy
(
null
,
getBytesNoCopy
(),
getDataHandler
());
case
TIMESTAMP_TZ:
throw
DbException
.
get
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
getString
());
}
break
;
}
...
...
@@ -852,6 +899,9 @@ public abstract class Value {
case
BYTES:
return
ValueLobDb
.
createSmallLob
(
Value
.
BLOB
,
getBytesNoCopy
());
case
TIMESTAMP_TZ:
throw
DbException
.
get
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
getString
());
}
break
;
}
...
...
@@ -859,6 +909,9 @@ public abstract class Value {
switch
(
getType
())
{
case
BYTES:
return
ValueUuid
.
get
(
getBytesNoCopy
());
case
TIMESTAMP_TZ:
throw
DbException
.
get
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
getString
());
}
}
case
GEOMETRY:
...
...
@@ -870,6 +923,9 @@ public abstract class Value {
if
(
DataType
.
isGeometry
(
object
))
{
return
ValueGeometry
.
getFromGeometry
(
object
);
}
case
TIMESTAMP_TZ:
throw
DbException
.
get
(
ErrorCode
.
DATA_CONVERSION_ERROR_1
,
getString
());
}
}
// conversion by parsing the string value
...
...
@@ -911,6 +967,8 @@ public abstract class Value {
return
ValueTimestamp
.
parse
(
s
.
trim
());
case
TIMESTAMP_UTC:
return
ValueTimestampUtc
.
parse
(
s
.
trim
());
case
TIMESTAMP_TZ:
return
ValueTimestampTimeZone
.
parse
(
s
.
trim
());
case
BYTES:
return
ValueBytes
.
getNoCopy
(
StringUtils
.
convertHexToBytes
(
s
.
trim
()));
...
...
h2/src/main/org/h2/value/ValueTimestampTimeZone.java
0 → 100644
浏览文件 @
7224c100
/*
* Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
value
;
import
java.math.BigDecimal
;
import
java.sql.PreparedStatement
;
import
java.sql.SQLException
;
import
java.sql.Timestamp
;
import
java.util.TimeZone
;
import
org.h2.api.ErrorCode
;
import
org.h2.api.TimestampWithTimeZone
;
import
org.h2.message.DbException
;
import
org.h2.util.DateTimeUtils
;
import
org.h2.util.MathUtils
;
import
org.h2.util.StringUtils
;
/**
* Implementation of the TIMESTAMP WITH TIMEZONE data type.
*
* @see <a href="https://en.wikipedia.org/wiki/ISO_8601#Time_zone_designators">ISO 8601 Time zone designators</a>
*/
public
class
ValueTimestampTimeZone
extends
Value
{
/**
* The precision in digits.
*/
public
static
final
int
PRECISION
=
30
;
/**
* The display size of the textual representation of a timestamp.
* Example: 2001-01-01 23:59:59.000 +10:00
*/
static
final
int
DISPLAY_SIZE
=
30
;
/**
* The default scale for timestamps.
*/
static
final
int
DEFAULT_SCALE
=
10
;
/**
* A bit field with bits for the year, month, and day (see DateTimeUtils for
* encoding)
*/
private
final
long
dateValue
;
/**
* The nanoseconds since midnight.
*/
private
final
long
timeNanos
;
/**
* Time zone offset from UTC in minutes, range of -12hours to +12hours
*/
private
final
short
timeZoneOffsetMins
;
private
ValueTimestampTimeZone
(
long
dateValue
,
long
timeNanos
,
short
timeZoneOffsetMins
)
{
if
(
timeNanos
<
0
||
timeNanos
>=
24L
*
60
*
60
*
1000
*
1000
*
1000
)
{
throw
new
IllegalArgumentException
(
"timeNanos out of range "
+
timeNanos
);
}
if
(
timeZoneOffsetMins
<
(-
12
*
60
)
||
timeZoneOffsetMins
>=
(
12
*
60
))
{
throw
new
IllegalArgumentException
(
"timeZoneOffsetMins out of range "
+
timeZoneOffsetMins
);
}
this
.
dateValue
=
dateValue
;
this
.
timeNanos
=
timeNanos
;
this
.
timeZoneOffsetMins
=
timeZoneOffsetMins
;
}
/**
* Get or create a date value for the given date.
*
* @param dateValue the date value, a bit field with bits for the year,
* month, and day
* @param timeNanos the nanoseconds since midnight
* @return the value
*/
public
static
ValueTimestampTimeZone
fromDateValueAndNanos
(
long
dateValue
,
long
timeNanos
,
short
timeZoneOffsetMins
)
{
return
(
ValueTimestampTimeZone
)
Value
.
cache
(
new
ValueTimestampTimeZone
(
dateValue
,
timeNanos
,
timeZoneOffsetMins
));
}
/**
* Get or create a timestamp value for the given timestamp.
*
* @param timestamp the timestamp
* @return the value
*/
public
static
ValueTimestampTimeZone
get
(
TimestampWithTimeZone
timestamp
)
{
long
ms
=
timestamp
.
getTime
();
long
nanos
=
timestamp
.
getNanos
()
%
1000000
;
long
dateValue
=
DateTimeUtils
.
dateValueFromDate
(
ms
);
nanos
+=
DateTimeUtils
.
nanosFromDate
(
ms
);
return
fromDateValueAndNanos
(
dateValue
,
nanos
,
timestamp
.
getTimeZoneOffsetMins
());
}
/**
* Get or create a timestamp value for the given date/time in millis.
*
* @param ms the milliseconds
* @param nanos the nanoseconds
* @return the value
*/
public
static
ValueTimestampTimeZone
fromMillisNanos
(
long
ms
,
int
nanos
,
short
timeZoneOffsetMins
)
{
long
dateValue
=
DateTimeUtils
.
dateValueFromDate
(
ms
);
long
timeNanos
=
nanos
+
DateTimeUtils
.
nanosFromDate
(
ms
);
return
fromDateValueAndNanos
(
dateValue
,
timeNanos
,
timeZoneOffsetMins
);
}
/**
* Get or create a timestamp value for the given date/time in millis.
*
* @param ms the milliseconds
* @return the value
*/
public
static
ValueTimestampTimeZone
fromMillis
(
long
ms
,
short
timeZoneOffsetMins
)
{
long
dateValue
=
DateTimeUtils
.
dateValueFromDate
(
ms
);
long
nanos
=
DateTimeUtils
.
nanosFromDate
(
ms
);
return
fromDateValueAndNanos
(
dateValue
,
nanos
,
timeZoneOffsetMins
);
}
/**
* Parse a string to a ValueTimestamp. This method supports the format
* +/-year-month-day hour:minute:seconds.fractional and an optional timezone
* part.
*
* @param s the string to parse
* @return the date
*/
public
static
ValueTimestampTimeZone
parse
(
String
s
)
{
try
{
return
parseTry
(
s
);
}
catch
(
Exception
e
)
{
throw
DbException
.
get
(
ErrorCode
.
INVALID_DATETIME_CONSTANT_2
,
e
,
"TIMESTAMP WITH TIMEZONE"
,
s
);
}
}
private
static
ValueTimestampTimeZone
parseTry
(
String
s
)
{
int
dateEnd
=
s
.
indexOf
(
' '
);
if
(
dateEnd
<
0
)
{
// ISO 8601 compatibility
dateEnd
=
s
.
indexOf
(
'T'
);
}
int
timeStart
;
if
(
dateEnd
<
0
)
{
dateEnd
=
s
.
length
();
timeStart
=
-
1
;
}
else
{
timeStart
=
dateEnd
+
1
;
}
long
dateValue
=
DateTimeUtils
.
parseDateValue
(
s
,
0
,
dateEnd
);
long
nanos
;
short
tz_mins
=
0
;
if
(
timeStart
<
0
)
{
nanos
=
0
;
}
else
{
int
timeEnd
=
s
.
length
();
if
(
s
.
endsWith
(
"Z"
))
{
timeEnd
--;
}
else
{
int
timeZoneStart
=
s
.
indexOf
(
'+'
,
dateEnd
);
if
(
timeZoneStart
<
0
)
{
timeZoneStart
=
s
.
indexOf
(
'-'
,
dateEnd
);
}
TimeZone
tz
=
null
;
if
(
timeZoneStart
>=
0
)
{
String
tzName
=
"GMT"
+
s
.
substring
(
timeZoneStart
);
tz
=
TimeZone
.
getTimeZone
(
tzName
);
if
(!
tz
.
getID
().
startsWith
(
tzName
))
{
throw
new
IllegalArgumentException
(
tzName
+
" ("
+
tz
.
getID
()
+
"?)"
);
}
timeEnd
=
timeZoneStart
;
}
else
{
timeZoneStart
=
s
.
indexOf
(
' '
,
dateEnd
+
1
);
if
(
timeZoneStart
>
0
)
{
String
tzName
=
s
.
substring
(
timeZoneStart
+
1
);
tz
=
TimeZone
.
getTimeZone
(
tzName
);
if
(!
tz
.
getID
().
startsWith
(
tzName
))
{
throw
new
IllegalArgumentException
(
tzName
);
}
timeEnd
=
timeZoneStart
;
}
}
if
(
tz
!=
null
)
{
long
millis
=
DateTimeUtils
.
convertDateValueToDate
(
dateValue
).
getTime
();
tz_mins
=
(
short
)
(
tz
.
getOffset
(
millis
)
/
1000
/
60
);
}
}
nanos
=
DateTimeUtils
.
parseTimeNanos
(
s
,
dateEnd
+
1
,
timeEnd
,
true
);
}
return
ValueTimestampTimeZone
.
fromDateValueAndNanos
(
dateValue
,
nanos
,
tz_mins
);
}
/**
* A bit field with bits for the year, month, and day (see DateTimeUtils for
* encoding).
*
* @return the data value
*/
public
long
getDateValue
()
{
return
dateValue
;
}
/**
* The nanoseconds since midnight.
*
* @return the nanoseconds
*/
public
long
getTimeNanos
()
{
return
timeNanos
;
}
/**
* The timezone offset in minutes.
*
* @return the offset
*/
public
short
getTimeZoneOffsetMins
()
{
return
timeZoneOffsetMins
;
}
@Override
public
Timestamp
getTimestamp
()
{
Timestamp
ts
=
DateTimeUtils
.
convertDateValueToTimestamp
(
dateValue
,
timeNanos
);
return
new
TimestampWithTimeZone
(
ts
.
getTime
(),
ts
.
getNanos
(),
getTimeZoneOffsetMins
());
}
@Override
public
int
getType
()
{
return
Value
.
TIMESTAMP_TZ
;
}
@Override
public
String
getString
()
{
StringBuilder
buff
=
new
StringBuilder
(
DISPLAY_SIZE
);
ValueDate
.
appendDate
(
buff
,
dateValue
);
buff
.
append
(
' '
);
ValueTime
.
appendTime
(
buff
,
timeNanos
,
true
);
buff
.
append
(
' '
);
appendTimeZone
(
buff
,
timeZoneOffsetMins
);
return
buff
.
toString
();
}
/**
* Append a time zone to the string builder.
*
* @param buff the target string builder
* @param tz the time zone in minutes
*/
private
static
void
appendTimeZone
(
StringBuilder
buff
,
short
tz
)
{
if
(
tz
<
0
)
{
buff
.
append
(
'-'
);
tz
=
(
short
)-
tz
;
}
int
hours
=
tz
/
60
;
tz
-=
hours
*
60
;
int
mins
=
tz
;
StringUtils
.
appendZeroPadded
(
buff
,
2
,
hours
);
if
(
mins
!=
0
)
{
buff
.
append
(
':'
);
StringUtils
.
appendZeroPadded
(
buff
,
2
,
mins
);
}
}
@Override
public
String
getSQL
()
{
return
"TIMESTAMP WITH TIMEZONE '"
+
getString
()
+
"'"
;
}
@Override
public
long
getPrecision
()
{
return
PRECISION
;
}
@Override
public
int
getScale
()
{
return
DEFAULT_SCALE
;
}
@Override
public
int
getDisplaySize
()
{
return
DISPLAY_SIZE
;
}
@Override
public
Value
convertScale
(
boolean
onlyToSmallerScale
,
int
targetScale
)
{
if
(
targetScale
>=
DEFAULT_SCALE
)
{
return
this
;
}
if
(
targetScale
<
0
)
{
throw
DbException
.
getInvalidValueException
(
"scale"
,
targetScale
);
}
long
n
=
timeNanos
;
BigDecimal
bd
=
BigDecimal
.
valueOf
(
n
);
bd
=
bd
.
movePointLeft
(
9
);
bd
=
ValueDecimal
.
setScale
(
bd
,
targetScale
);
bd
=
bd
.
movePointRight
(
9
);
long
n2
=
bd
.
longValue
();
if
(
n2
==
n
)
{
return
this
;
}
return
fromDateValueAndNanos
(
dateValue
,
n2
,
timeZoneOffsetMins
);
}
@Override
protected
int
compareSecure
(
Value
o
,
CompareMode
mode
)
{
ValueTimestampTimeZone
t
=
(
ValueTimestampTimeZone
)
o
;
int
c
=
MathUtils
.
compareLong
(
dateValue
,
t
.
dateValue
);
if
(
c
!=
0
)
{
return
c
;
}
c
=
MathUtils
.
compareLong
(
timeNanos
,
t
.
timeNanos
);
if
(
c
!=
0
)
{
return
c
;
}
return
MathUtils
.
compareInt
(
timeZoneOffsetMins
,
t
.
timeZoneOffsetMins
);
}
@Override
public
boolean
equals
(
Object
other
)
{
if
(
this
==
other
)
{
return
true
;
}
else
if
(!(
other
instanceof
ValueTimestampTimeZone
))
{
return
false
;
}
ValueTimestampTimeZone
x
=
(
ValueTimestampTimeZone
)
other
;
return
dateValue
==
x
.
dateValue
&&
timeNanos
==
x
.
timeNanos
&&
timeZoneOffsetMins
==
x
.
timeZoneOffsetMins
;
}
@Override
public
int
hashCode
()
{
return
(
int
)
(
dateValue
^
(
dateValue
>>>
32
)
^
timeNanos
^
(
timeNanos
>>>
32
)
^
timeZoneOffsetMins
);
}
@Override
public
Object
getObject
()
{
return
getTimestamp
();
}
@Override
public
void
set
(
PreparedStatement
prep
,
int
parameterIndex
)
throws
SQLException
{
prep
.
setString
(
parameterIndex
,
getString
());
}
@Override
public
Value
add
(
Value
v
)
{
throw
DbException
.
getUnsupportedException
(
"manipulating TIMESTAMP WITH TIMEZONE values is unsupported"
);
}
@Override
public
Value
subtract
(
Value
v
)
{
throw
DbException
.
getUnsupportedException
(
"manipulating TIMESTAMP WITH TIMEZONE values is unsupported"
);
}
}
h2/src/test/org/h2/test/TestAll.java
浏览文件 @
7224c100
...
...
@@ -24,6 +24,7 @@ import org.h2.test.db.TestCases;
import
org.h2.test.db.TestCheckpoint
;
import
org.h2.test.db.TestCluster
;
import
org.h2.test.db.TestCompatibility
;
import
org.h2.test.db.TestCompatibilityOracle
;
import
org.h2.test.db.TestCsv
;
import
org.h2.test.db.TestDateStorage
;
import
org.h2.test.db.TestDeadlock
;
...
...
@@ -46,7 +47,6 @@ import org.h2.test.db.TestMultiThread;
import
org.h2.test.db.TestMultiThreadedKernel
;
import
org.h2.test.db.TestOpenClose
;
import
org.h2.test.db.TestOptimizations
;
import
org.h2.test.db.TestCompatibilityOracle
;
import
org.h2.test.db.TestOptimizerHints
;
import
org.h2.test.db.TestOutOfMemory
;
import
org.h2.test.db.TestPowerOff
;
...
...
@@ -178,8 +178,8 @@ import org.h2.test.unit.TestFileSystem;
import
org.h2.test.unit.TestFtp
;
import
org.h2.test.unit.TestIntArray
;
import
org.h2.test.unit.TestIntIntHashMap
;
import
org.h2.test.unit.TestJmx
;
import
org.h2.test.unit.TestIntPerfectHash
;
import
org.h2.test.unit.TestJmx
;
import
org.h2.test.unit.TestLocale
;
import
org.h2.test.unit.TestMathUtils
;
import
org.h2.test.unit.TestModifyOnWrite
;
...
...
@@ -203,6 +203,8 @@ import org.h2.test.unit.TestSort;
import
org.h2.test.unit.TestStreams
;
import
org.h2.test.unit.TestStringCache
;
import
org.h2.test.unit.TestStringUtils
;
import
org.h2.test.unit.TestTimeStampUtc
;
import
org.h2.test.unit.TestTimeStampWithTimeZone
;
import
org.h2.test.unit.TestTools
;
import
org.h2.test.unit.TestTraceSystem
;
import
org.h2.test.unit.TestUtils
;
...
...
@@ -851,6 +853,8 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
addTest
(
new
TestSort
());
addTest
(
new
TestStreams
());
addTest
(
new
TestStringUtils
());
addTest
(
new
TestTimeStampUtc
());
addTest
(
new
TestTimeStampWithTimeZone
());
addTest
(
new
TestTraceSystem
());
addTest
(
new
TestUpgrade
());
addTest
(
new
TestUsingIndex
());
...
...
h2/src/test/org/h2/test/unit/TestTimeStampWithTimeZone.java
0 → 100644
浏览文件 @
7224c100
/*
* Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0, and the
* EPL 1.0 (http://h2database.com/html/license.html). Initial Developer: H2
* Group
*/
package
org
.
h2
.
test
.
unit
;
import
java.sql.Connection
;
import
java.sql.ResultSet
;
import
java.sql.SQLException
;
import
java.sql.Statement
;
import
org.h2.api.TimestampWithTimeZone
;
import
org.h2.test.TestBase
;
/**
*/
public
class
TestTimeStampWithTimeZone
extends
TestBase
{
/**
* Run just this test.
*
* @param a ignored
*/
public
static
void
main
(
String
...
a
)
throws
Exception
{
TestBase
.
createCaller
().
init
().
test
();
}
@Override
public
void
test
()
throws
SQLException
{
deleteDb
(
"timestamp_tz"
);
test1
();
deleteDb
(
"timestamp_tz"
);
}
private
void
test1
()
throws
SQLException
{
Connection
conn
=
getConnection
(
"timestamp_tz"
);
Statement
stat
=
conn
.
createStatement
();
stat
.
execute
(
"create table test(id identity, t1 timestamp with timezone)"
);
stat
.
execute
(
"insert into test(t1) values('1970-01-01 12:00:00.00+00:15')"
);
ResultSet
rs
=
stat
.
executeQuery
(
"select t1 from test"
);
rs
.
next
();
assertTrue
(
new
TimestampWithTimeZone
(
36000000
,
00
,
(
short
)
15
).
equals
(
rs
.
getTimestamp
(
1
)));
conn
.
close
();
}
}
h2/src/test/org/h2/test/unit/TestValueMemory.java
浏览文件 @
7224c100
...
...
@@ -12,7 +12,6 @@ import java.sql.SQLException;
import
java.util.ArrayList
;
import
java.util.IdentityHashMap
;
import
java.util.Random
;
import
org.h2.api.JavaObjectSerializer
;
import
org.h2.engine.Constants
;
import
org.h2.store.DataHandler
;
...
...
@@ -47,6 +46,7 @@ import org.h2.value.ValueStringFixed;
import
org.h2.value.ValueStringIgnoreCase
;
import
org.h2.value.ValueTime
;
import
org.h2.value.ValueTimestamp
;
import
org.h2.value.ValueTimestampTimeZone
;
import
org.h2.value.ValueTimestampUtc
;
import
org.h2.value.ValueUuid
;
...
...
@@ -166,6 +166,8 @@ public class TestValueMemory extends TestBase implements DataHandler {
return
ValueTimestamp
.
fromMillis
(
random
.
nextLong
());
case
Value
.
TIMESTAMP_UTC
:
return
ValueTimestampUtc
.
fromMillis
(
random
.
nextLong
());
case
Value
.
TIMESTAMP_TZ
:
return
ValueTimestampTimeZone
.
fromMillis
(
random
.
nextLong
(),
(
short
)
0
);
case
Value
.
BYTES
:
return
ValueBytes
.
get
(
randomBytes
(
random
.
nextInt
(
1000
)));
case
Value
.
STRING
:
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论