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),