This is an automated email from the ASF dual-hosted git repository.
jhyde pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite-avatica.git
The following commit(s) were added to refs/heads/main by this push:
new d9a2e105a [CALCITE-5369] In Avatica DateTimeUtils, add support for
FLOOR and CEIL to ISOYEAR
d9a2e105a is described below
commit d9a2e105a906e9334ca4603d658d6adedb863e88
Author: Julian Hyde <[email protected]>
AuthorDate: Sun Nov 6 16:56:02 2022 -0800
[CALCITE-5369] In Avatica DateTimeUtils, add support for FLOOR and CEIL to
ISOYEAR
Close apache/calcite-avatica#192
---
.../apache/calcite/avatica/util/DateTimeUtils.java | 11 +++
.../calcite/avatica/util/DateTimeUtilsTest.java | 85 ++++++++++++++++++++--
2 files changed, 90 insertions(+), 6 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 b342c94b7..64db2e95a 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
@@ -939,6 +939,17 @@ public class DateTimeUtils {
++year;
}
return ymdToUnixDate(year, 1, 1);
+ case ISOYEAR:
+ final int isoWeek = getIso8601WeekNumber(julian, year, month, day);
+ final int dowMon = Math.floorMod(julian, 7); // mon=0, sun=6
+ final int isoYearFloor = julian - 7 * (isoWeek - 1) - dowMon;
+ if (floor || isoYearFloor == julian) {
+ return isoYearFloor - EPOCH_JULIAN;
+ } else {
+ // CEIL of this date is the FLOOR of the date 53 weeks later.
+ // (Usually 52 weeks later, sometimes 53 weeks later.)
+ return julianDateFloor(range, isoYearFloor + 7 * 53, true);
+ }
case QUARTER:
final int q = (month - 1) / 3;
if (!floor) {
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 bd8d79864..bad4e51b7 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
@@ -20,6 +20,8 @@ import org.junit.Test;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.temporal.IsoFields;
import java.util.Calendar;
import java.util.Locale;
@@ -503,6 +505,9 @@ public class DateTimeUtilsTest {
thereAndBack(1901, 1, 1);
thereAndBack(1901, 2, 28); // no leap day
thereAndBack(1901, 3, 1);
+ thereAndBack(1902, 1, 1);
+ thereAndBack(1903, 1, 1);
+ thereAndBack(1904, 1, 1);
thereAndBack(2000, 1, 1);
thereAndBack(2000, 2, 28);
thereAndBack(2000, 2, 29); // leap day
@@ -782,6 +787,8 @@ public class DateTimeUtilsTest {
private void thereAndBack(int year, int month, int day) {
final int unixDate = ymdToUnixDate(year, month, day);
+ final LocalDate javaDate = LocalDate.of(year, month, day); // ref impl
+
assertThat(unixDateExtract(TimeUnitRange.YEAR, unixDate),
is((long) year));
assertThat(unixDateExtract(TimeUnitRange.MONTH, unixDate),
@@ -790,22 +797,48 @@ public class DateTimeUtilsTest {
is((long) day));
final long isoYear = unixDateExtract(TimeUnitRange.ISOYEAR, unixDate);
assertTrue(isoYear >= year - 1 && isoYear <= year + 1);
+ assertThat(isoYear, is((long) javaDate.get(IsoFields.WEEK_BASED_YEAR)));
+
final long w = unixDateExtract(TimeUnitRange.WEEK, unixDate);
assertTrue(w >= 1 && w <= 53);
+ assertThat(w, is((long) javaDate.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR)));
+
final long dow = unixDateExtract(TimeUnitRange.DOW, unixDate);
assertTrue(dow >= 1 && dow <= 7);
final long iso_dow = unixDateExtract(TimeUnitRange.ISODOW, unixDate);
assertTrue(iso_dow >= 1 && iso_dow <= 7);
+
+ final long isoYearFloor = unixDateFloor(TimeUnitRange.ISOYEAR, unixDate);
+ assertThat(unixDateExtract(TimeUnitRange.ISOYEAR, isoYearFloor),
+ is(isoYear));
+ assertThat(unixDateExtract(TimeUnitRange.ISOYEAR, isoYearFloor - 1),
+ is(isoYear - 1));
+
+ final long isoYearCeil = unixDateCeil(TimeUnitRange.ISOYEAR, unixDate);
+ if (isoYearFloor == unixDate) {
+ assertThat(unixDateExtract(TimeUnitRange.ISOYEAR, isoYearCeil),
+ is(isoYear));
+ assertThat(unixDateExtract(TimeUnitRange.ISOYEAR, isoYearCeil - 1),
+ is(isoYear - 1));
+ } else {
+ assertThat(unixDateExtract(TimeUnitRange.ISOYEAR, isoYearCeil),
+ is(isoYear + 1));
+ assertThat(unixDateExtract(TimeUnitRange.ISOYEAR, isoYearCeil - 1),
+ is(isoYear));
+ }
+
final long doy = unixDateExtract(TimeUnitRange.DOY, unixDate);
assertTrue(doy >= 1 && doy <= 366);
final long q = unixDateExtract(TimeUnitRange.QUARTER, unixDate);
assertTrue(q >= 1 && q <= 4);
final long d = unixDateExtract(TimeUnitRange.DECADE, unixDate);
- assertTrue(d == year / 10);
+ assertThat(d, is((long) year / 10));
final long c = unixDateExtract(TimeUnitRange.CENTURY, unixDate);
- assertTrue(c == (year > 0 ? (year + 99) / 100 : (year - 99) / 100));
+ assertThat(c,
+ is(year > 0 ? ((long) year + 99) / 100 : ((long) year - 99) / 100));
final long m = unixDateExtract(TimeUnitRange.MILLENNIUM, unixDate);
- assertTrue(m == (year > 0 ? (year + 999) / 1000 : (year - 999) / 1000));
+ assertThat(m,
+ is(year > 0 ? ((long) year + 999) / 1000 : ((long) year - 999) /
1000));
}
@Test public void testAddMonths() {
@@ -915,12 +948,17 @@ public class DateTimeUtilsTest {
final long y1801 = -(169 * 365 + 169 / 4 - 1);
final long y1890 = -(80 * 365 + 80 / 4 - 1);
final long y1900 = -(70 * 365 + 70 / 4);
+ final long y1899 = y1900 - 365;
+ final long y1901 = y1900 + 365;
+ final long y1902 = y1901 + 365;
+ final long y1903 = y1902 + 365;
+ final long y1904 = y1903 + 365;
+ final long y1905 = y1904 + 366;
+ final long y1906 = y1905 + 365;
+ final long y1907 = y1903 + 4 * 365 + 1;
final long y1910 = -(60 * 365 + 60 / 4);
- final long y1907 = -(63 * 365 + 63 / 4);
final long y2001 = 31 * 365 + 31 / 4 + 1;
final long y1900_0102 = y1900 + 1;
- final long y1899 = y1900 - 365;
- final long y1901 = y1900 + 365;
final long y1900_0506 = y1900 - 1 + 31 + 28 + 31 + 30 + 6; // sunday
final long y1900_0512 = y1900 - 1 + 31 + 28 + 31 + 30 + 12; // saturday
final long y1900_0513 = y1900 - 1 + 31 + 28 + 31 + 30 + 13; // sunday
@@ -932,11 +970,25 @@ public class DateTimeUtilsTest {
final long y1900_0701 = y1900 - 1 + 31 + 28 + 31 + 30 + 31 + 30 + 1;
final long y1900_1001 = y1900 - 1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31
+ 30 + 1;
final long y1900_1002 = y1900 - 1 + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31
+ 30 + 2;
+ final long y1900_1231 = y1901 - 1;
+ final long y1902_1229 = y1903 - 3;
+ final long y1904_0103 = y1904 + 2;
+ final long y1904_0104 = y1904 + 3;
checkDateString("1801-01-01", (int) y1801);
checkDateString("1900-01-01", (int) y1900);
checkDateString("1900-01-02", (int) y1900_0102);
checkDateString("1899-01-01", (int) y1899);
checkDateString("1901-01-01", (int) y1901);
+ checkDateString("1902-01-01", (int) y1902);
+ checkDateString("1902-12-29", (int) y1902_1229);
+ checkDateString("1903-01-01", (int) y1903);
+ checkDateString("1904-01-01", (int) y1904);
+ checkDateString("1904-01-03", (int) y1904_0103);
+ checkDateString("1904-01-04", (int) y1904_0104);
+ checkDateString("1905-01-01", (int) y1905);
+ checkDateString("1906-01-01", (int) y1906);
+ checkDateString("1907-01-01", (int) y1907);
+ checkDateString("1910-01-01", (int) y1910);
checkDateString("2001-01-01", (int) y2001);
assertThat(unixDateFloor(TimeUnitRange.MILLENNIUM, y1907), is(y1001));
assertThat(unixDateCeil(TimeUnitRange.MILLENNIUM, y1907), is(y2001));
@@ -968,6 +1020,27 @@ public class DateTimeUtilsTest {
assertThat(unixDateCeil(TimeUnitRange.WEEK, y1900_0512), is(y1900_0513));
assertThat(unixDateFloor(TimeUnitRange.DAY, y1900_0514), is(y1900_0514));
assertThat(unixDateCeil(TimeUnitRange.DAY, y1900_0514), is(y1900_0514));
+
+ // 1900/01/01 is a Monday, therefore the first day of the ISO year;
+ // the next ISO year starts on 1900/12/31
+ assertThat(unixDateFloor(TimeUnitRange.ISOYEAR, y1900), is(y1900));
+ assertThat(unixDateCeil(TimeUnitRange.ISOYEAR, y1900), is(y1900));
+ assertThat(unixDateFloor(TimeUnitRange.ISOYEAR, y1900_0102), is(y1900));
+ assertThat(unixDateCeil(TimeUnitRange.ISOYEAR, y1900_0102),
is(y1900_1231));
+ assertThat(unixDateFloor(TimeUnitRange.ISOYEAR, y1900_1231),
is(y1900_1231));
+ assertThat(unixDateCeil(TimeUnitRange.ISOYEAR, y1900_1231),
is(y1900_1231));
+ assertThat(unixDateFloor(TimeUnitRange.ISOYEAR, y1901), is(y1900_1231));
+ assertThat(unixDateFloor(TimeUnitRange.ISOYEAR, y1903), is(y1902_1229));
+
+ // 1904/01/01 is a Friday, the next ISO year starts on Mon 1904/01/04,
+ // the previous ISO year started on 1902/12/29.
+ assertThat(unixDateFloor(TimeUnitRange.ISOYEAR, y1904), is(y1902_1229));
+ assertThat(unixDateFloor(TimeUnitRange.ISOYEAR, y1904_0103),
is(y1902_1229));
+ assertThat(unixDateFloor(TimeUnitRange.ISOYEAR, y1904_0104),
is(y1904_0104));
+ assertThat(unixDateFloor(TimeUnitRange.ISOYEAR, y1905), is(y1904_0104));
+
+ // 1906/01/01 is a Monday.
+ assertThat(unixDateFloor(TimeUnitRange.ISOYEAR, y1906), is(y1906));
}
}