You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2018/06/01 22:39:13 UTC
[2/3] calcite-avatica git commit: [CALCITE-1884] DateTimeUtils
produces incorrect results for days before the Gregorian cutover (Haohui Mai,
Julian Hyde, Sergey Nuyanzin)
[CALCITE-1884] DateTimeUtils produces incorrect results for days before the Gregorian cutover (Haohui Mai, Julian Hyde, Sergey Nuyanzin)
Remove conversion to Gregorian in case of DateTimeUtils#ymdToJulian, and added tests.
Close apache/calcite-avatica#11
Close apache/calcite-avatica#52
Project: http://git-wip-us.apache.org/repos/asf/calcite-avatica/repo
Commit: http://git-wip-us.apache.org/repos/asf/calcite-avatica/commit/4beeef40
Tree: http://git-wip-us.apache.org/repos/asf/calcite-avatica/tree/4beeef40
Diff: http://git-wip-us.apache.org/repos/asf/calcite-avatica/diff/4beeef40
Branch: refs/heads/master
Commit: 4beeef40d0fc1d3ce5d361b177e94fb156234f43
Parents: 4ac7e1c
Author: snuyanzin <sn...@gmail.com>
Authored: Tue May 29 18:08:05 2018 +0300
Committer: Julian Hyde <jh...@apache.org>
Committed: Fri Jun 1 10:52:03 2018 -0700
----------------------------------------------------------------------
.../calcite/avatica/util/DateTimeUtils.java | 6 +-
.../calcite/avatica/util/DateTimeUtilsTest.java | 88 ++++++++++++++++++--
2 files changed, 81 insertions(+), 13 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/calcite-avatica/blob/4beeef40/core/src/main/java/org/apache/calcite/avatica/util/DateTimeUtils.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/calcite/avatica/util/DateTimeUtils.java b/core/src/main/java/org/apache/calcite/avatica/util/DateTimeUtils.java
index 0f3d466..e1f6999 100644
--- a/core/src/main/java/org/apache/calcite/avatica/util/DateTimeUtils.java
+++ b/core/src/main/java/org/apache/calcite/avatica/util/DateTimeUtils.java
@@ -902,16 +902,12 @@ public class DateTimeUtils {
int a = (14 - month) / 12;
int y = year + 4800 - a;
int m = month + 12 * a - 3;
- int j = day + (153 * m + 2) / 5
+ return day + (153 * m + 2) / 5
+ 365 * y
+ y / 4
- y / 100
+ y / 400
- 32045;
- if (j < 2299161) {
- j = day + (153 * m + 2) / 5 + 365 * y + y / 4 - 32083;
- }
- return j;
}
public static long unixTimestamp(int year, int month, int day, int hour,
http://git-wip-us.apache.org/repos/asf/calcite-avatica/blob/4beeef40/core/src/test/java/org/apache/calcite/avatica/util/DateTimeUtilsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/calcite/avatica/util/DateTimeUtilsTest.java b/core/src/test/java/org/apache/calcite/avatica/util/DateTimeUtilsTest.java
index f433884..ea25349 100644
--- a/core/src/test/java/org/apache/calcite/avatica/util/DateTimeUtilsTest.java
+++ b/core/src/test/java/org/apache/calcite/avatica/util/DateTimeUtilsTest.java
@@ -25,8 +25,6 @@ import java.util.Locale;
import static org.apache.calcite.avatica.util.DateTimeUtils.EPOCH_JULIAN;
import static org.apache.calcite.avatica.util.DateTimeUtils.addMonths;
import static org.apache.calcite.avatica.util.DateTimeUtils.dateStringToUnixDate;
-
-
import static org.apache.calcite.avatica.util.DateTimeUtils.digitCount;
import static org.apache.calcite.avatica.util.DateTimeUtils.floorDiv;
import static org.apache.calcite.avatica.util.DateTimeUtils.floorMod;
@@ -142,6 +140,19 @@ public class DateTimeUtilsTest {
checkDateString("1972-02-29", 0 + 365 * 2 + 31 + (29 - 1));
//noinspection PointlessArithmeticExpression
checkDateString("1972-03-01", 0 + 365 * 2 + 31 + 29 + (1 - 1));
+
+ final int d1900 = -(70 * 365 + 70 / 4);
+ final int century = 100 * 365 + 100 / 4;
+ checkDateString("1900-01-01", d1900);
+ // +1 because 1800 is not a leap year
+ final int d1800 = d1900 - century + 1;
+ checkDateString("1800-01-01", d1800);
+ final int d1700 = d1800 - century + 1;
+ checkDateString("1700-01-01", d1700);
+ final int d1600 = d1700 - century;
+ checkDateString("1600-01-01", d1600);
+ final int d1500 = d1600 - century + 1;
+ checkDateString("1500-01-01", d1500); // fails, about 10 days off
}
private void checkDateString(String s, int d) {
@@ -410,11 +421,9 @@ public class DateTimeUtilsTest {
assertThat(
unixDateExtract(TimeUnitRange.CENTURY, ymdToUnixDate(1, 2, 1)),
is(1L));
- // TODO: For a small time range around year 1, due to the Gregorian shift,
- // we end up in the wrong century. Should be 1.
assertThat(
unixDateExtract(TimeUnitRange.CENTURY, ymdToUnixDate(1, 1, 1)),
- is(0L));
+ is(1L));
assertThat(
unixDateExtract(TimeUnitRange.CENTURY, ymdToUnixDate(-2, 1, 1)),
is(-1L));
@@ -429,11 +438,9 @@ public class DateTimeUtilsTest {
assertThat(
unixDateExtract(TimeUnitRange.MILLENNIUM, ymdToUnixDate(1852, 6, 7)),
is(2L));
- // TODO: For a small time range around year 1, due to the Gregorian shift,
- // we end up in the wrong millennium. Should be 1.
assertThat(
unixDateExtract(TimeUnitRange.MILLENNIUM, ymdToUnixDate(1, 1, 1)),
- is(0L));
+ is(1L));
assertThat(
unixDateExtract(TimeUnitRange.MILLENNIUM, ymdToUnixDate(1, 2, 1)),
is(1L));
@@ -442,6 +449,71 @@ public class DateTimeUtilsTest {
is(-1L));
}
+ @Test public void testUnixDate() {
+ int days = DateTimeUtils.dateStringToUnixDate("1500-04-30");
+ assertThat(DateTimeUtils.unixDateToString(days), is("1500-04-30"));
+ assertThat(
+ DateTimeUtils.unixDateToString(
+ DateTimeUtils.dateStringToUnixDate(
+ DateTimeUtils.unixDateToString(
+ DateTimeUtils.dateStringToUnixDate(
+ DateTimeUtils.unixDateToString(
+ DateTimeUtils.dateStringToUnixDate("1500-04-30")))))),
+ is("1500-04-30"));
+
+ final int d1900 = -(70 * 365 + 70 / 4);
+ final int century = 100 * 365 + 100 / 4;
+ checkDateString("1900-01-01", d1900);
+ // +1 because 1800 is not a leap year
+ final int d1800 = d1900 - century + 1;
+ checkDateString("1800-01-01", d1800);
+ final int d1700 = d1800 - century + 1;
+ checkDateString("1700-01-01", d1700);
+ final int d1600 = d1700 - century;
+ checkDateString("1600-01-01", d1600);
+ final int d1500 = d1600 - century + 1;
+ checkDateString("1500-01-01", d1500);
+ final int d1400 = d1500 - century + 1;
+ checkDateString("1400-01-01", d1400);
+ final int d1300 = d1400 - century + 1;
+ checkDateString("1300-01-01", d1300);
+ final int d1200 = d1300 - century;
+ checkDateString("1200-01-01", d1200);
+ final int d1100 = d1200 - century + 1;
+ checkDateString("1100-01-01", d1100);
+ final int d1000 = d1100 - century + 1;
+ checkDateString("1000-01-01", d1000);
+ final int d900 = d1000 - century + 1;
+ checkDateString("0900-01-01", d900);
+ final int d800 = d900 - century;
+ checkDateString("0800-01-01", d800);
+ final int d700 = d800 - century + 1;
+ checkDateString("0700-01-01", d700);
+ final int d600 = d700 - century + 1;
+ checkDateString("0600-01-01", d600);
+ final int d500 = d600 - century + 1;
+ checkDateString("0500-01-01", d500);
+ final int d400 = d500 - century;
+ checkDateString("0400-01-01", d400);
+ final int d300 = d400 - century + 1;
+ checkDateString("0300-01-01", d300);
+ final int d200 = d300 - century + 1;
+ checkDateString("0200-01-01", d200);
+ final int d100 = d200 - century + 1;
+ checkDateString("0100-01-01", d100);
+ final int d000 = d100 - century;
+ checkDateString("0000-01-01", d000);
+ }
+
+ @Test public void testDateConversion() {
+ for (int i = 0; i < 4000; ++i) {
+ for (int j = 1; j <= 12; ++j) {
+ String date = String.format(Locale.ENGLISH, "%04d-%02d-28", i, j);
+ assertThat(unixDateToString(ymdToUnixDate(i, j, 28)), is(date));
+ }
+ }
+ }
+
private void thereAndBack(int year, int month, int day) {
final int unixDate = ymdToUnixDate(year, month, day);
assertThat(unixDateExtract(TimeUnitRange.YEAR, unixDate),