提交 8b16b1f2 authored 作者: Thomas Mueller's avatar Thomas Mueller

Some timestamps with timezone were not converted correctly.

上级 2c65762f
...@@ -19,7 +19,11 @@ Change Log ...@@ -19,7 +19,11 @@ Change Log
<h1>Change Log</h1> <h1>Change Log</h1>
<h2>Next Version (unreleased)</h2> <h2>Next Version (unreleased)</h2>
<ul><li>Sequences with cache size smaller than 0 did not work correctly. <ul><li>Some timestamps with timezone were not converted correctly.
For example, in the PST timezone, the timestamp 2011-10-26 08:00:00Z was converted to
2011-10-25 25:00:00 instead of 2011-10-26 01:00:00.
Depending on the database operation, this caused subsequent error.
</li><li>Sequences with cache size smaller than 0 did not work correctly.
</li><li>Issue 356: for Blob objects, InputStream.skip() returned 0, </li><li>Issue 356: for Blob objects, InputStream.skip() returned 0,
causing EOFException in Blob.getBytes(.., ..). causing EOFException in Blob.getBytes(.., ..).
</li><li>Updateable result sets: if the value is not set when inserting a new row, </li><li>Updateable result sets: if the value is not set when inserting a new row,
......
...@@ -26,6 +26,9 @@ import org.h2.value.ValueTimestamp; ...@@ -26,6 +26,9 @@ import org.h2.value.ValueTimestamp;
/** /**
* This utility class contains time conversion functions. * This utility class contains time conversion functions.
* <p>
* Date value: a bit field with bits for the year, month, and day.
* Absolute day: the day number (0 means 1970-01-01).
*/ */
public class DateTimeUtils { public class DateTimeUtils {
...@@ -34,7 +37,7 @@ public class DateTimeUtils { ...@@ -34,7 +37,7 @@ public class DateTimeUtils {
*/ */
public static final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000L; public static final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000L;
private static final long NANOS_PER_DAY = MILLIS_PER_DAY * 1000000; public static final long NANOS_PER_DAY = MILLIS_PER_DAY * 1000000;
private static final int SHIFT_YEAR = 9; private static final int SHIFT_YEAR = 9;
private static final int SHIFT_MONTH = 5; private static final int SHIFT_MONTH = 5;
...@@ -325,10 +328,10 @@ public class DateTimeUtils { ...@@ -325,10 +328,10 @@ public class DateTimeUtils {
} }
/** /**
* Calculate the milliseconds for the given date and time in the specified * Calculate the milliseconds since 1970-01-01 (UTC) for the given date and
* timezone. * time (in the specified timezone).
* *
* @param tz the timezone * @param tz the timezone of the parameters
* @param year the absolute year (positive or negative) * @param year the absolute year (positive or negative)
* @param month the month (1-12) * @param month the month (1-12)
* @param day the day (1-31) * @param day the day (1-31)
...@@ -336,7 +339,7 @@ public class DateTimeUtils { ...@@ -336,7 +339,7 @@ public class DateTimeUtils {
* @param minute the minutes (0-59) * @param minute the minutes (0-59)
* @param second the number of seconds (0-59) * @param second the number of seconds (0-59)
* @param millis the number of milliseconds * @param millis the number of milliseconds
* @return the number of milliseconds * @return the number of milliseconds (UTC)
*/ */
public static long getMillis(TimeZone tz, int year, int month, int day, int hour, int minute, int second, int millis) { public static long getMillis(TimeZone tz, int year, int month, int day, int hour, int minute, int second, int millis) {
try { try {
......
...@@ -151,8 +151,10 @@ public class ValueTimestamp extends Value { ...@@ -151,8 +151,10 @@ public class ValueTimestamp extends Value {
minute -= hour * 60; minute -= hour * 60;
long millis = DateTimeUtils.getMillis(tz, year, month, day, hour, minute, (int) second, (int) ms); long millis = DateTimeUtils.getMillis(tz, year, month, day, hour, minute, (int) second, (int) ms);
ms = DateTimeUtils.convertToLocal(new Date(millis), Calendar.getInstance(TimeZone.getTimeZone("UTC"))); ms = DateTimeUtils.convertToLocal(new Date(millis), Calendar.getInstance(TimeZone.getTimeZone("UTC")));
dateValue = DateTimeUtils.dateValueFromDate(ms); long mpd = DateTimeUtils.MILLIS_PER_DAY;
nanos += (ms - DateTimeUtils.absoluteDayFromDateValue(dateValue) * DateTimeUtils.MILLIS_PER_DAY) * 1000000; long absoluteDay = (ms >= 0 ? ms : ms - mpd + 1) / mpd;
ms -= absoluteDay * mpd;
nanos += ms * 1000000;
} }
} }
return ValueTimestamp.fromDateValueAndNanos(dateValue, nanos); return ValueTimestamp.fromDateValueAndNanos(dateValue, nanos);
......
...@@ -52,6 +52,7 @@ public class TestDate extends TestBase { ...@@ -52,6 +52,7 @@ public class TestDate extends TestBase {
testValueDate(); testValueDate();
testValueTime(); testValueTime();
testValueTimestamp(); testValueTimestamp();
testValueTimestampWithTimezone();
testValidDate(); testValidDate();
testAbsoluteDay(); testAbsoluteDay();
testCalculateLocalMillis(); testCalculateLocalMillis();
...@@ -175,6 +176,21 @@ public class TestDate extends TestBase { ...@@ -175,6 +176,21 @@ public class TestDate extends TestBase {
convertTo(Value.DATE).getString()); convertTo(Value.DATE).getString());
} }
private void testValueTimestampWithTimezone() {
for (int m = 1; m <= 12; m++) {
for (int d = 1; d <= 28; d++) {
for (int h = 0; h <= 23; h++) {
String s = "2011-" + (m < 10 ? "0" : "") + m + "-" + (d < 10 ? "0" : "") + d + " " +
(h < 10 ? "0" : "") + h + ":00:00";
ValueTimestamp ts = ValueTimestamp.parse(s + "Z");
String s2 = ts.getString();
ValueTimestamp ts2 = ValueTimestamp.parse(s2);
assertEquals(ts.getString(), ts2.getString());
}
}
}
}
private void testValueTimestamp() { private void testValueTimestamp() {
assertEquals("2001-02-03 04:05:06.0", ValueTimestamp.get( assertEquals("2001-02-03 04:05:06.0", ValueTimestamp.get(
Timestamp.valueOf("2001-02-03 04:05:06")).getString()); Timestamp.valueOf("2001-02-03 04:05:06")).getString());
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论