This is an automated email from the ASF dual-hosted git repository.
jhyde pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/calcite-avatica.git
The following commit(s) were added to refs/heads/master by this push:
new f93e72b [CALCITE-3881] DateTimeUtils.addMonths yields incorrect
results (Zhenghua Gao)
f93e72b is described below
commit f93e72b8f93318ee2b1c78e772a75f5ecef97b2a
Author: Zhenghua Gao <[email protected]>
AuthorDate: Fri Mar 27 20:11:25 2020 +0800
[CALCITE-3881] DateTimeUtils.addMonths yields incorrect results (Zhenghua
Gao)
Close apache/calcite-avatica#121
---
.../apache/calcite/avatica/util/DateTimeUtils.java | 25 +++++++++++++++++++---
.../calcite/avatica/util/DateTimeUtilsTest.java | 2 ++
2 files changed, 24 insertions(+), 3 deletions(-)
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 1243ef4..7e5e109 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
@@ -965,6 +965,19 @@ public class DateTimeUtils {
return julian - EPOCH_JULIAN;
}
+ /** Calculates the Julian Day Number for any valid date in the Gregorian
+ * calendar.
+ *
+ * <p>If date is invalid, result is unspecified.
+ *
+ * <p>See an
+ * <a
href="http://www.cs.utsa.edu/~cs1063/projects/Spring2011/Project1/jdn-explanation.html">
+ * explanation</a> of this algorithm.
+ *
+ * @param year Year (e.g. 2020 means 2020 CE, 1 means 1 CE, 0 means 1 BCE
+ * because there is no 0 CE, -1 means 2 BCE, etc.)
+ * @param month Month (between 1 and 12 inclusive, 1 meaning January)
+ * @param day Day of month (between 1 and 31 inclusive) */
public static int ymdToJulian(int year, int month, int day) {
int a = (14 - month) / 12;
int y = year + 4800 - a;
@@ -1003,9 +1016,15 @@ public class DateTimeUtils {
int y0 = (int) DateTimeUtils.unixDateExtract(TimeUnitRange.YEAR, date);
int m0 = (int) DateTimeUtils.unixDateExtract(TimeUnitRange.MONTH, date);
int d0 = (int) DateTimeUtils.unixDateExtract(TimeUnitRange.DAY, date);
- int y = m / 12;
- y0 += y;
- m0 += m - y * 12;
+ m0 += m;
+ int deltaYear = (int) DateTimeUtils.floorDiv(m0, 12);
+ y0 += deltaYear;
+ m0 = (int) DateTimeUtils.floorMod(m0, 12);
+ if (m0 == 0) {
+ y0 -= 1;
+ m0 += 12;
+ }
+
int last = lastDay(y0, m0);
if (d0 > last) {
d0 = 1;
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 8cf32c4..6a33adf 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
@@ -820,6 +820,8 @@ public class DateTimeUtilsTest {
checkAddMonths(2016, 3, 31, 2016, 3, 1, -1);
checkAddMonths(2016, 3, 31, 2116, 3, 31, 1200);
checkAddMonths(2016, 2, 28, 2116, 2, 28, 1200);
+ checkAddMonths(2019, 9, 1, 2020, 3, 1, 6);
+ checkAddMonths(2019, 9, 1, 2016, 8, 1, -37);
}
private void checkAddMonths(int y0, int m0, int d0, int y1, int m1, int d1,