提交 d0e0e8f9 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Remap Instant to Value.TIMESTAMP_TZ

上级 cecf30f0
......@@ -101,9 +101,13 @@ public class LocalDateTimeUtils {
private static final Method LOCAL_DATE_AT_START_OF_DAY;
/**
* {@code java.sql.Timestamp.from(java.time.Instant)} or {@code null}.
* {@code java.time.Instant#getEpochSecond()} or {@code null}.
*/
private static final Method TIMESTAMP_FROM;
private static final Method INSTANT_GET_EPOCH_SECOND;
/**
* {@code java.time.Instant#getNano()} or {@code null}.
*/
private static final Method INSTANT_GET_NANO;
/**
* {@code java.sql.Timestamp.toInstant()} or {@code null}.
*/
......@@ -186,7 +190,8 @@ public class LocalDateTimeUtils {
LOCAL_DATE_GET_DAY_OF_MONTH = getMethod(LOCAL_DATE, "getDayOfMonth");
LOCAL_DATE_AT_START_OF_DAY = getMethod(LOCAL_DATE, "atStartOfDay");
TIMESTAMP_FROM = getMethod(Timestamp.class, "from", INSTANT);
INSTANT_GET_EPOCH_SECOND = getMethod(INSTANT, "getEpochSecond");
INSTANT_GET_NANO = getMethod(INSTANT, "getNano");
TIMESTAMP_TO_INSTANT = getMethod(Timestamp.class, "toInstant");
LOCAL_TIME_PARSE = getMethod(LOCAL_TIME, "parse", CharSequence.class);
......@@ -214,7 +219,8 @@ public class LocalDateTimeUtils {
LOCAL_DATE_GET_MONTH_VALUE = null;
LOCAL_DATE_GET_DAY_OF_MONTH = null;
LOCAL_DATE_AT_START_OF_DAY = null;
TIMESTAMP_FROM = null;
INSTANT_GET_EPOCH_SECOND = null;
INSTANT_GET_NANO = null;
TIMESTAMP_TO_INSTANT = null;
LOCAL_TIME_PARSE = null;
LOCAL_DATE_TIME_PLUS_NANOS = null;
......@@ -485,7 +491,16 @@ public class LocalDateTimeUtils {
*/
public static Value instantToValue(Object instant) {
try {
return ValueTimestamp.get((Timestamp) TIMESTAMP_FROM.invoke(null, instant));
long epochSecond = (long) INSTANT_GET_EPOCH_SECOND.invoke(instant);
int nano = (int) INSTANT_GET_NANO.invoke(instant);
long absoluteDay = epochSecond / 86_400;
// Round toward negative infinity
if (epochSecond < 0 && (absoluteDay * 86_400 != epochSecond)) {
absoluteDay--;
}
long timeNanos = (epochSecond - absoluteDay * 86_400) * 1_000_000_000 + nano;
return ValueTimestampTimeZone.fromDateValueAndNanos(
DateTimeUtils.dateValueFromAbsoluteDay(absoluteDay), timeNanos, (short) 0);
} catch (IllegalAccessException e) {
throw DbException.convert(e);
} catch (InvocationTargetException e) {
......
......@@ -1020,9 +1020,9 @@ public class DataType {
return Value.DATE;
} else if (LocalDateTimeUtils.LOCAL_TIME == x) {
return Value.TIME;
} else if (LocalDateTimeUtils.LOCAL_DATE_TIME == x || LocalDateTimeUtils.INSTANT == x) {
} else if (LocalDateTimeUtils.LOCAL_DATE_TIME == x) {
return Value.TIMESTAMP;
} else if (LocalDateTimeUtils.OFFSET_DATE_TIME == x) {
} else if (LocalDateTimeUtils.OFFSET_DATE_TIME == x || LocalDateTimeUtils.INSTANT == x) {
return Value.TIMESTAMP_TZ;
} else {
if (JdbcUtils.customDataTypesHandler != null) {
......
......@@ -9,6 +9,7 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
......@@ -755,18 +756,26 @@ public class TestPreparedStatement extends TestBase {
if (!LocalDateTimeUtils.isJava8DateApiPresent()) {
return;
}
Method timestampToInstant = Timestamp.class.getMethod("toInstant"),
now = LocalDateTimeUtils.INSTANT.getMethod("now");
Method timestampToInstant = Timestamp.class.getMethod("toInstant");
Method now = LocalDateTimeUtils.INSTANT.getMethod("now");
Method parse = LocalDateTimeUtils.INSTANT.getMethod("parse", CharSequence.class);
PreparedStatement prep = conn.prepareStatement("SELECT ?");
Object instant1 = now.invoke(null);
prep.setObject(1, instant1);
testInstant8Impl(prep, timestampToInstant, now.invoke(null));
testInstant8Impl(prep, timestampToInstant, parse.invoke(null, "2000-01-15T12:13:14.123456789Z"));
testInstant8Impl(prep, timestampToInstant, parse.invoke(null, "1500-09-10T23:22:11.123456789Z"));
}
private void testInstant8Impl(PreparedStatement prep, Method timestampToInstant, Object instant)
throws SQLException, IllegalAccessException, InvocationTargetException {
prep.setObject(1, instant);
ResultSet rs = prep.executeQuery();
rs.next();
Object instant2 = rs.getObject(1, LocalDateTimeUtils.INSTANT);
assertEquals(instant1, instant2);
assertEquals(instant, instant2);
Timestamp ts = rs.getTimestamp(1);
assertEquals(instant1, timestampToInstant.invoke(ts));
assertEquals(instant, timestampToInstant.invoke(ts));
assertFalse(rs.next());
rs.close();
......@@ -774,7 +783,7 @@ public class TestPreparedStatement extends TestBase {
rs = prep.executeQuery();
rs.next();
instant2 = rs.getObject(1, LocalDateTimeUtils.INSTANT);
assertEquals(instant1, instant2);
assertEquals(instant, instant2);
assertFalse(rs.next());
rs.close();
}
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论