This is an automated email from the ASF dual-hosted git repository.

alexpl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new 521b54afb46 IGNITE-16977 Move date/time indexes to the core module - 
Fixes #10046.
521b54afb46 is described below

commit 521b54afb4676f9f6f812c3a45c7836985ae226a
Author: Aleksey Plekhanov <[email protected]>
AuthorDate: Thu Jun 2 15:27:19 2022 +0300

    IGNITE-16977 Move date/time indexes to the core module - Fixes #10046.
    
    Signed-off-by: Aleksey Plekhanov <[email protected]>
---
 .../inline/types/DateInlineIndexKeyType.java       |  21 ++-
 .../sorted/inline/types/DateValueConstants.java    |  46 ------
 .../index/sorted/inline/types/DateValueUtils.java  | 135 +++++++++++++++++
 .../inline/types/TimeInlineIndexKeyType.java       |  17 +--
 .../inline/types/TimestampInlineIndexKeyType.java  |  23 ++-
 .../index/sorted/keys/AbstractDateIndexKey.java    |  37 -----
 .../index/sorted/keys/AbstractTimeIndexKey.java    |  36 -----
 .../sorted/keys/AbstractTimestampIndexKey.java     |  40 -----
 .../query/index/sorted/keys/DateIndexKey.java      |  74 ++++++++++
 .../query/index/sorted/keys/IndexKeyFactory.java   |  34 +----
 .../query/index/sorted/keys/TimeIndexKey.java      |  81 +++++++++++
 .../query/index/sorted/keys/TimestampIndexKey.java | 102 +++++++++++++
 .../processors/query/h2/IgniteH2Indexing.java      |  16 --
 .../query/h2/index/keys/DateIndexKey.java          |  58 --------
 .../query/h2/index/keys/H2ValueWrapperMixin.java   |  46 ------
 .../query/h2/index/keys/TimeIndexKey.java          |  58 --------
 .../query/h2/index/keys/TimestampIndexKey.java     |  63 --------
 .../cache/index/DateIndexKeyTypeTest.java          | 162 +++++++++++++++++++++
 .../query/CreateIndexOnInvalidDataTypeTest.java    |   2 +-
 .../IgniteBinaryCacheQueryTestSuite3.java          |   2 +
 20 files changed, 592 insertions(+), 461 deletions(-)

diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/types/DateInlineIndexKeyType.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/types/DateInlineIndexKeyType.java
index 4ff9a8ea673..bc6e91f5840 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/types/DateInlineIndexKeyType.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/types/DateInlineIndexKeyType.java
@@ -18,24 +18,23 @@
 package org.apache.ignite.internal.cache.query.index.sorted.inline.types;
 
 import org.apache.ignite.internal.cache.query.index.sorted.IndexKeyTypes;
-import 
org.apache.ignite.internal.cache.query.index.sorted.keys.AbstractDateIndexKey;
-import 
org.apache.ignite.internal.cache.query.index.sorted.keys.IndexKeyFactory;
+import org.apache.ignite.internal.cache.query.index.sorted.keys.DateIndexKey;
 import org.apache.ignite.internal.pagemem.PageUtils;
 
-import static 
org.apache.ignite.internal.cache.query.index.sorted.inline.types.DateValueConstants.MAX_DATE_VALUE;
-import static 
org.apache.ignite.internal.cache.query.index.sorted.inline.types.DateValueConstants.MIN_DATE_VALUE;
+import static 
org.apache.ignite.internal.cache.query.index.sorted.inline.types.DateValueUtils.MAX_DATE_VALUE;
+import static 
org.apache.ignite.internal.cache.query.index.sorted.inline.types.DateValueUtils.MIN_DATE_VALUE;
 
 /**
- * Inline index key implementation for inlining {@link AbstractDateIndexKey} 
values.
+ * Inline index key implementation for inlining {@link DateIndexKey} values.
  */
-public class DateInlineIndexKeyType extends 
NullableInlineIndexKeyType<AbstractDateIndexKey> {
+public class DateInlineIndexKeyType extends 
NullableInlineIndexKeyType<DateIndexKey> {
     /** */
     public DateInlineIndexKeyType() {
         super(IndexKeyTypes.DATE, (short)8);
     }
 
     /** {@inheritDoc} */
-    @Override public int compare0(long pageAddr, int off, AbstractDateIndexKey 
key) {
+    @Override public int compare0(long pageAddr, int off, DateIndexKey key) {
         long val1 = PageUtils.getLong(pageAddr, off + 1);
         long val2 = key.dateValue();
 
@@ -43,7 +42,7 @@ public class DateInlineIndexKeyType extends 
NullableInlineIndexKeyType<AbstractD
     }
 
     /** {@inheritDoc} */
-    @Override protected int put0(long pageAddr, int off, AbstractDateIndexKey 
key, int maxSize) {
+    @Override protected int put0(long pageAddr, int off, DateIndexKey key, int 
maxSize) {
         PageUtils.putByte(pageAddr, off, (byte)type());
         PageUtils.putLong(pageAddr, off + 1, key.dateValue());
 
@@ -51,7 +50,7 @@ public class DateInlineIndexKeyType extends 
NullableInlineIndexKeyType<AbstractD
     }
 
     /** {@inheritDoc} */
-    @Override protected AbstractDateIndexKey get0(long pageAddr, int off) {
+    @Override protected DateIndexKey get0(long pageAddr, int off) {
         long dateVal = PageUtils.getLong(pageAddr, off + 1);
 
         if (dateVal > MAX_DATE_VALUE)
@@ -59,11 +58,11 @@ public class DateInlineIndexKeyType extends 
NullableInlineIndexKeyType<AbstractD
         else if (dateVal < MIN_DATE_VALUE)
             dateVal = MIN_DATE_VALUE;
 
-        return (AbstractDateIndexKey)IndexKeyFactory.wrapDateValue(type(), 
dateVal, 0L);
+        return new DateIndexKey(dateVal);
     }
 
     /** {@inheritDoc} */
-    @Override protected int inlineSize0(AbstractDateIndexKey key) {
+    @Override protected int inlineSize0(DateIndexKey key) {
         return keySize + 1;
     }
 }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/types/DateValueConstants.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/types/DateValueConstants.java
deleted file mode 100644
index 227e031aae8..00000000000
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/types/DateValueConstants.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.cache.query.index.sorted.inline.types;
-
-/**
- * DateValue is a representation of a date in bit form:
- *
- * dv = (year << SHIFT_YEAR) | (month << SHIFT_MONTH) | day.
- */
-public class DateValueConstants {
-    /** Forbid instantiation of this class. Just hold constants there. */
-    private DateValueConstants() {}
-
-    /** */
-    private static final int SHIFT_YEAR = 9;
-
-    /** */
-    private static final int SHIFT_MONTH = 5;
-
-    /** Min date value. */
-    public static final long MIN_DATE_VALUE = (-999_999_999L << SHIFT_YEAR) + 
(1 << SHIFT_MONTH) + 1;
-
-    /** Max date value. */
-    public static final long MAX_DATE_VALUE = (999_999_999L << SHIFT_YEAR) + 
(12 << SHIFT_MONTH) + 31;
-
-    /** The number of milliseconds per day. */
-    public static final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000L;
-
-    /** The number of nanoseconds per day. */
-    public static final long NANOS_PER_DAY = MILLIS_PER_DAY * 1_000_000;
-}
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/types/DateValueUtils.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/types/DateValueUtils.java
new file mode 100644
index 00000000000..66a52cc644f
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/types/DateValueUtils.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.cache.query.index.sorted.inline.types;
+
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+/**
+ * DateValue is a representation of a date in bit form:
+ *
+ * dv = (year << SHIFT_YEAR) | (month << SHIFT_MONTH) | day.
+ */
+public class DateValueUtils {
+    /** Calendar with UTC time zone instance. */
+    private static final ThreadLocal<Calendar> UTC_CALENDAR = 
ThreadLocal.withInitial(
+        () -> Calendar.getInstance(TimeZone.getTimeZone("UTC")));
+
+    /** Cached default time zone. */
+    private static final TimeZone DEFAULT_TZ = TimeZone.getDefault();
+
+    /** Forbid instantiation of this class. Just hold constants there. */
+    private DateValueUtils() {}
+
+    /** */
+    private static final int SHIFT_YEAR = 9;
+
+    /** */
+    private static final int SHIFT_MONTH = 5;
+
+    /** */
+    private static final long MONTH_MASK = ~(-1L << (SHIFT_YEAR - 
SHIFT_MONTH));
+
+    /** */
+    private static final long DAY_MASK = ~(-1L << SHIFT_MONTH);
+
+    /** Min date value. */
+    public static final long MIN_DATE_VALUE = (-999_999_999L << SHIFT_YEAR) + 
(1 << SHIFT_MONTH) + 1;
+
+    /** Max date value. */
+    public static final long MAX_DATE_VALUE = (999_999_999L << SHIFT_YEAR) + 
(12 << SHIFT_MONTH) + 31;
+
+    /** The number of milliseconds per day. */
+    public static final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000L;
+
+    /** The number of nanoseconds per day. */
+    public static final long NANOS_PER_DAY = MILLIS_PER_DAY * 1_000_000;
+
+    /**
+     * Extract the year from a date value.
+     */
+    private static int yearFromDateValue(long dateVal) {
+        return (int)(dateVal >>> SHIFT_YEAR);
+    }
+
+    /**
+     * Extract the month from a date value.
+     */
+    private static int monthFromDateValue(long dateVal) {
+        return (int)((dateVal >>> SHIFT_MONTH) & MONTH_MASK);
+    }
+
+    /**
+     * Extract the day of month from a date value.
+     */
+    private static int dayFromDateValue(long dateVal) {
+        return (int)(dateVal & DAY_MASK);
+    }
+
+    /**
+     * Construct date value from components.
+     */
+    public static long dateValue(int year, int month, int day) {
+        return ((long)year << SHIFT_YEAR) | month << SHIFT_MONTH | day;
+    }
+
+    /**
+     * Convert date value to epoch milliseconds.
+     */
+    public static long millisFromDateValue(long dateVal) {
+        Calendar cal = UTC_CALENDAR.get();
+
+        cal.clear();
+
+        cal.set(yearFromDateValue(dateVal), monthFromDateValue(dateVal) - 1, 
dayFromDateValue(dateVal));
+
+        return cal.getTimeInMillis();
+    }
+
+    /**
+     * Convert epoch milliseconds to date value.
+     */
+    public static long dateValueFromMillis(long millis) {
+        Calendar cal = UTC_CALENDAR.get();
+
+        cal.setTimeInMillis(millis);
+
+        return dateValue(
+            cal.get(Calendar.ERA) == GregorianCalendar.BC ? 1 - 
cal.get(Calendar.YEAR) : cal.get(Calendar.YEAR),
+            cal.get(Calendar.MONTH) + 1,
+            cal.get(Calendar.DAY_OF_MONTH)
+        );
+    }
+
+    /**
+     * Convert millis in default time zone to UTC millis.
+     */
+    public static long utcMillisFromDefaultTz(long tzMillis) {
+        return tzMillis + DEFAULT_TZ.getOffset(tzMillis);
+    }
+
+    /**
+     * Convert millis in UTC to default time zone millis.
+     */
+    public static long defaultTzMillisFromUtc(long utcMillis) {
+        // Taking into account DST, offset can be changed after converting 
from UTC to time-zone.
+        return utcMillis - DEFAULT_TZ.getOffset(utcMillis - 
DEFAULT_TZ.getOffset(utcMillis));
+
+    }
+}
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/types/TimeInlineIndexKeyType.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/types/TimeInlineIndexKeyType.java
index 778df96f89b..bae43f6b309 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/types/TimeInlineIndexKeyType.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/types/TimeInlineIndexKeyType.java
@@ -18,21 +18,20 @@
 package org.apache.ignite.internal.cache.query.index.sorted.inline.types;
 
 import org.apache.ignite.internal.cache.query.index.sorted.IndexKeyTypes;
-import 
org.apache.ignite.internal.cache.query.index.sorted.keys.AbstractTimeIndexKey;
-import 
org.apache.ignite.internal.cache.query.index.sorted.keys.IndexKeyFactory;
+import org.apache.ignite.internal.cache.query.index.sorted.keys.TimeIndexKey;
 import org.apache.ignite.internal.pagemem.PageUtils;
 
 /**
- * Inline index key implementation for inlining {@link AbstractTimeIndexKey} 
values.
+ * Inline index key implementation for inlining {@link TimeIndexKey} values.
  */
-public class TimeInlineIndexKeyType extends 
NullableInlineIndexKeyType<AbstractTimeIndexKey> {
+public class TimeInlineIndexKeyType extends 
NullableInlineIndexKeyType<TimeIndexKey> {
     /** */
     public TimeInlineIndexKeyType() {
         super(IndexKeyTypes.TIME, (short)8);
     }
 
     /** {@inheritDoc} */
-    @Override public int compare0(long pageAddr, int off, AbstractTimeIndexKey 
key) {
+    @Override public int compare0(long pageAddr, int off, TimeIndexKey key) {
         long val1 = PageUtils.getLong(pageAddr, off + 1);
         long val2 = key.nanos();
 
@@ -40,7 +39,7 @@ public class TimeInlineIndexKeyType extends 
NullableInlineIndexKeyType<AbstractT
     }
 
     /** {@inheritDoc} */
-    @Override protected int put0(long pageAddr, int off, AbstractTimeIndexKey 
key, int maxSize) {
+    @Override protected int put0(long pageAddr, int off, TimeIndexKey key, int 
maxSize) {
         PageUtils.putByte(pageAddr, off, (byte)type());
         PageUtils.putLong(pageAddr, off + 1, key.nanos());
 
@@ -48,14 +47,14 @@ public class TimeInlineIndexKeyType extends 
NullableInlineIndexKeyType<AbstractT
     }
 
     /** {@inheritDoc} */
-    @Override protected AbstractTimeIndexKey get0(long pageAddr, int off) {
+    @Override protected TimeIndexKey get0(long pageAddr, int off) {
         long nanos = PageUtils.getLong(pageAddr, off + 1);
 
-        return (AbstractTimeIndexKey)IndexKeyFactory.wrapDateValue(type(), 0L, 
nanos);
+        return new TimeIndexKey(nanos);
     }
 
     /** {@inheritDoc} */
-    @Override protected int inlineSize0(AbstractTimeIndexKey key) {
+    @Override protected int inlineSize0(TimeIndexKey key) {
         return keySize + 1;
     }
 }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/types/TimestampInlineIndexKeyType.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/types/TimestampInlineIndexKeyType.java
index c890683882f..bd7a328ee78 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/types/TimestampInlineIndexKeyType.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/inline/types/TimestampInlineIndexKeyType.java
@@ -18,25 +18,24 @@
 package org.apache.ignite.internal.cache.query.index.sorted.inline.types;
 
 import org.apache.ignite.internal.cache.query.index.sorted.IndexKeyTypes;
-import 
org.apache.ignite.internal.cache.query.index.sorted.keys.AbstractTimestampIndexKey;
-import 
org.apache.ignite.internal.cache.query.index.sorted.keys.IndexKeyFactory;
+import 
org.apache.ignite.internal.cache.query.index.sorted.keys.TimestampIndexKey;
 import org.apache.ignite.internal.pagemem.PageUtils;
 
-import static 
org.apache.ignite.internal.cache.query.index.sorted.inline.types.DateValueConstants.MAX_DATE_VALUE;
-import static 
org.apache.ignite.internal.cache.query.index.sorted.inline.types.DateValueConstants.MIN_DATE_VALUE;
-import static 
org.apache.ignite.internal.cache.query.index.sorted.inline.types.DateValueConstants.NANOS_PER_DAY;
+import static 
org.apache.ignite.internal.cache.query.index.sorted.inline.types.DateValueUtils.MAX_DATE_VALUE;
+import static 
org.apache.ignite.internal.cache.query.index.sorted.inline.types.DateValueUtils.MIN_DATE_VALUE;
+import static 
org.apache.ignite.internal.cache.query.index.sorted.inline.types.DateValueUtils.NANOS_PER_DAY;
 
 /**
- * Inline index key implementation for inlining {@link 
AbstractTimestampIndexKey} values.
+ * Inline index key implementation for inlining {@link TimestampIndexKey} 
values.
  */
-public class TimestampInlineIndexKeyType extends 
NullableInlineIndexKeyType<AbstractTimestampIndexKey> {
+public class TimestampInlineIndexKeyType extends 
NullableInlineIndexKeyType<TimestampIndexKey> {
     /** */
     public TimestampInlineIndexKeyType() {
         super(IndexKeyTypes.TIMESTAMP, (short)16);
     }
 
     /** {@inheritDoc} */
-    @Override public int compare0(long pageAddr, int off, 
AbstractTimestampIndexKey key) {
+    @Override public int compare0(long pageAddr, int off, TimestampIndexKey 
key) {
         long val1 = PageUtils.getLong(pageAddr, off + 1);
 
         int c = Long.compare(val1, key.dateValue());
@@ -50,7 +49,7 @@ public class TimestampInlineIndexKeyType extends 
NullableInlineIndexKeyType<Abst
     }
 
     /** {@inheritDoc} */
-    @Override protected int put0(long pageAddr, int off, 
AbstractTimestampIndexKey key, int maxSize) {
+    @Override protected int put0(long pageAddr, int off, TimestampIndexKey 
key, int maxSize) {
         PageUtils.putByte(pageAddr, off, (byte)type());
 
         PageUtils.putLong(pageAddr, off + 1, key.dateValue());
@@ -60,7 +59,7 @@ public class TimestampInlineIndexKeyType extends 
NullableInlineIndexKeyType<Abst
     }
 
     /** {@inheritDoc} */
-    @Override protected AbstractTimestampIndexKey get0(long pageAddr, int off) 
{
+    @Override protected TimestampIndexKey get0(long pageAddr, int off) {
         long dv = PageUtils.getLong(pageAddr, off + 1);
         long nanos = PageUtils.getLong(pageAddr, off + 9);
 
@@ -73,11 +72,11 @@ public class TimestampInlineIndexKeyType extends 
NullableInlineIndexKeyType<Abst
             nanos = 0;
         }
 
-        return 
(AbstractTimestampIndexKey)IndexKeyFactory.wrapDateValue(type(), dv, nanos);
+        return new TimestampIndexKey(dv, nanos);
     }
 
     /** {@inheritDoc} */
-    @Override protected int inlineSize0(AbstractTimestampIndexKey key) {
+    @Override protected int inlineSize0(TimestampIndexKey key) {
         return keySize + 1;
     }
 }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/keys/AbstractDateIndexKey.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/keys/AbstractDateIndexKey.java
deleted file mode 100644
index 6db91f36986..00000000000
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/keys/AbstractDateIndexKey.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.cache.query.index.sorted.keys;
-
-import org.apache.ignite.internal.cache.query.index.sorted.IndexKeyTypes;
-import 
org.apache.ignite.internal.cache.query.index.sorted.inline.types.DateInlineIndexKeyType;
-import 
org.apache.ignite.internal.cache.query.index.sorted.inline.types.DateValueConstants;
-
-/**
- * Abstract class for representing Date index key.
- *
- * {@link DateInlineIndexKeyType} relies on this API to store an object in 
inline.
- */
-public abstract class AbstractDateIndexKey implements IndexKey {
-    /** @return a date value {@link DateValueConstants}. */
-    public abstract long dateValue();
-
-    /** {@inheritDoc} */
-    @Override public int type() {
-        return IndexKeyTypes.DATE;
-    }
-}
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/keys/AbstractTimeIndexKey.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/keys/AbstractTimeIndexKey.java
deleted file mode 100644
index 16cceeb9fa5..00000000000
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/keys/AbstractTimeIndexKey.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.cache.query.index.sorted.keys;
-
-import org.apache.ignite.internal.cache.query.index.sorted.IndexKeyTypes;
-import 
org.apache.ignite.internal.cache.query.index.sorted.inline.types.TimeInlineIndexKeyType;
-
-/**
- * Abstract class for representing Time index key.
- *
- * {@link TimeInlineIndexKeyType} relies on this API to store an object in 
inline.
- */
-public abstract class AbstractTimeIndexKey implements IndexKey {
-    /** @return nanoseconds since midnight. */
-    public abstract long nanos();
-
-    /** {@inheritDoc} */
-    @Override public int type() {
-        return IndexKeyTypes.TIME;
-    }
-}
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/keys/AbstractTimestampIndexKey.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/keys/AbstractTimestampIndexKey.java
deleted file mode 100644
index 25b0e00b0ae..00000000000
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/keys/AbstractTimestampIndexKey.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.cache.query.index.sorted.keys;
-
-import org.apache.ignite.internal.cache.query.index.sorted.IndexKeyTypes;
-import 
org.apache.ignite.internal.cache.query.index.sorted.inline.types.DateValueConstants;
-import 
org.apache.ignite.internal.cache.query.index.sorted.inline.types.TimestampInlineIndexKeyType;
-
-/**
- * Abstract class for representing Timestamp index key.
- *
- * {@link TimestampInlineIndexKeyType} relies on this API to store an object 
in inline.
- */
-public abstract class AbstractTimestampIndexKey implements IndexKey {
-    /** @return a date value {@link DateValueConstants}. */
-    public abstract long dateValue();
-
-    /** @return nanoseconds since midnight. */
-    public abstract long nanos();
-
-    /** {@inheritDoc} */
-    @Override public int type() {
-        return IndexKeyTypes.TIMESTAMP;
-    }
-}
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/keys/DateIndexKey.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/keys/DateIndexKey.java
new file mode 100644
index 00000000000..d2dd2f7f87b
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/keys/DateIndexKey.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.cache.query.index.sorted.keys;
+
+import java.sql.Date;
+import java.time.LocalDate;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.internal.cache.query.index.sorted.IndexKeyTypes;
+import 
org.apache.ignite.internal.cache.query.index.sorted.inline.types.DateValueUtils;
+
+/** */
+public class DateIndexKey implements IndexKey {
+    /** */
+    private final long dateVal;
+
+    /** */
+    public DateIndexKey(Object obj) {
+        if (obj instanceof Date) {
+            long millis = 
DateValueUtils.utcMillisFromDefaultTz(((Date)obj).getTime());
+            dateVal = DateValueUtils.dateValueFromMillis(millis);
+        }
+        else if (obj instanceof LocalDate) {
+            LocalDate locDate = (LocalDate)obj;
+            dateVal = DateValueUtils.dateValue(locDate.getYear(), 
locDate.getMonthValue(), locDate.getDayOfMonth());
+        }
+        else {
+            throw new IgniteException("Failed to convert object to date value, 
unexpected class " +
+                obj.getClass().getName());
+        }
+    }
+
+    /** */
+    public DateIndexKey(long dateVal) {
+        this.dateVal = dateVal;
+    }
+
+    /** @return a date value {@link DateValueUtils}. */
+    public long dateValue() {
+        return dateVal;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int type() {
+        return IndexKeyTypes.DATE;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object key() {
+        long millis = DateValueUtils.millisFromDateValue(dateVal);
+        millis = DateValueUtils.defaultTzMillisFromUtc(millis);
+
+        return new Date(millis);
+    }
+
+    /** {@inheritDoc} */
+    @Override public int compare(IndexKey o) {
+        return Long.compare(dateVal, ((DateIndexKey)o).dateVal);
+    }
+}
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/keys/IndexKeyFactory.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/keys/IndexKeyFactory.java
index 01a271d1403..c5e7b694bb2 100644
--- 
a/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/keys/IndexKeyFactory.java
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/keys/IndexKeyFactory.java
@@ -18,11 +18,7 @@
 package org.apache.ignite.internal.cache.query.index.sorted.keys;
 
 import java.math.BigDecimal;
-import java.util.Map;
 import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.BiFunction;
-import java.util.function.Function;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.internal.binary.BinaryObjectImpl;
 import 
org.apache.ignite.internal.cache.query.index.sorted.IndexKeyTypeSettings;
@@ -34,27 +30,6 @@ import 
org.apache.ignite.internal.processors.cache.CacheObjectValueContext;
  * Factory for creating IndexKey objects.
  */
 public class IndexKeyFactory {
-    /** Registry for non-default key types factory methods (e.g., Geometry, 
date/time types). */
-    private static final Map<Integer, Function<Object, IndexKey>> registry = 
new ConcurrentHashMap<>();
-
-    /** Registry for date time key types factory methods. */
-    private static final Map<Integer, BiFunction<Long, Long, IndexKey>> 
dateTimeRegistry = new ConcurrentHashMap<>();
-
-    /** Register wrapper for custom IndexKey type. */
-    public static void register(int keyType, Function<Object, IndexKey> 
wrapper) {
-        registry.put(keyType, wrapper);
-    }
-
-    /** Register factory for date/time index key types. */
-    public static void registerDateValueFactory(int keyType, BiFunction<Long, 
Long, IndexKey> factory) {
-        dateTimeRegistry.put(keyType, factory);
-    }
-
-    /** Wraps a date value and nanos to related date/time IndexKey. */
-    public static IndexKey wrapDateValue(int keyType, long dateVal, long 
nanos) {
-        return dateTimeRegistry.get(keyType).apply(dateVal, nanos);
-    }
-
     /** Wraps user object to {@code IndexKey} object.  */
     public static IndexKey wrap(Object o, int keyType, CacheObjectValueContext 
coctx, IndexKeyTypeSettings keyTypeSettings) {
         if (o == null || keyType == IndexKeyTypes.NULL)
@@ -89,11 +64,14 @@ public class IndexKeyFactory {
                     return new CacheJavaObjectIndexKey((CacheObject)o, coctx);
 
                 return new PlainJavaObjectIndexKey(o, null);
+            case IndexKeyTypes.DATE:
+                return new DateIndexKey(o);
+            case IndexKeyTypes.TIME:
+                return new TimeIndexKey(o);
+            case IndexKeyTypes.TIMESTAMP:
+                return new TimestampIndexKey(o);
         }
 
-        if (registry.containsKey(keyType))
-            return registry.get(keyType).apply(o);
-
         throw new IgniteException("Failed to wrap value[type=" + keyType + ", 
value=" + o + "]");
     }
 }
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/keys/TimeIndexKey.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/keys/TimeIndexKey.java
new file mode 100644
index 00000000000..34629495f4e
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/keys/TimeIndexKey.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.cache.query.index.sorted.keys;
+
+import java.sql.Time;
+import java.time.LocalTime;
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.internal.cache.query.index.sorted.IndexKeyTypes;
+import 
org.apache.ignite.internal.cache.query.index.sorted.inline.types.DateValueUtils;
+
+/** */
+public class TimeIndexKey implements IndexKey {
+    /** */
+    private final long nanos;
+
+    /** */
+    public TimeIndexKey(Object obj) {
+        if (obj instanceof Date) {
+            long millis = 
DateValueUtils.utcMillisFromDefaultTz(((Date)obj).getTime());
+            millis %= DateValueUtils.MILLIS_PER_DAY;
+
+            if (millis < 0)
+                millis += DateValueUtils.MILLIS_PER_DAY;
+
+            nanos = TimeUnit.MILLISECONDS.toNanos(millis);
+        }
+        else if (obj instanceof LocalTime) {
+            LocalTime locTime = (LocalTime)obj;
+            nanos = locTime.toNanoOfDay();
+        }
+        else {
+            throw new IgniteException("Failed to convert object to time value, 
unexpected class " +
+                obj.getClass().getName());
+        }
+    }
+
+    /** */
+    public TimeIndexKey(long nanos) {
+        this.nanos = nanos;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object key() {
+        long millis = TimeUnit.NANOSECONDS.toMillis(nanos);
+        millis = DateValueUtils.defaultTzMillisFromUtc(millis);
+
+        return new Time(millis);
+    }
+
+    /** @return nanoseconds since midnight. */
+    public long nanos() {
+        return nanos;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int type() {
+        return IndexKeyTypes.TIME;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int compare(IndexKey o) {
+        return Long.compare(nanos, ((TimeIndexKey)o).nanos);
+    }
+}
diff --git 
a/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/keys/TimestampIndexKey.java
 
b/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/keys/TimestampIndexKey.java
new file mode 100644
index 00000000000..a454ab486c6
--- /dev/null
+++ 
b/modules/core/src/main/java/org/apache/ignite/internal/cache/query/index/sorted/keys/TimestampIndexKey.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.cache.query.index.sorted.keys;
+
+import java.sql.Timestamp;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+import org.apache.ignite.IgniteException;
+import org.apache.ignite.internal.cache.query.index.sorted.IndexKeyTypes;
+import 
org.apache.ignite.internal.cache.query.index.sorted.inline.types.DateValueUtils;
+
+/** */
+public class TimestampIndexKey implements IndexKey {
+    /** */
+    private final long dateVal;
+
+    /** */
+    private final long nanos;
+
+    /** */
+    public TimestampIndexKey(Object obj) {
+        if (obj instanceof Date) {
+            long millis = 
DateValueUtils.utcMillisFromDefaultTz(((Date)obj).getTime());
+            dateVal = DateValueUtils.dateValueFromMillis(millis);
+
+            millis %= DateValueUtils.MILLIS_PER_DAY;
+
+            if (millis < 0)
+                millis += DateValueUtils.MILLIS_PER_DAY;
+
+            if (obj instanceof Timestamp)
+                nanos = TimeUnit.MILLISECONDS.toNanos(millis) + 
((Timestamp)obj).getNanos() % 1_000_000L;
+            else
+                nanos = TimeUnit.MILLISECONDS.toNanos(millis);
+        }
+        else if (obj instanceof LocalDateTime) {
+            LocalDateTime locDateTime = ((LocalDateTime)obj);
+            LocalDate locDate = locDateTime.toLocalDate();
+            LocalTime locTime = locDateTime.toLocalTime();
+            dateVal = DateValueUtils.dateValue(locDate.getYear(), 
locDate.getMonthValue(), locDate.getDayOfMonth());
+            nanos = locTime.toNanoOfDay();
+        }
+        else {
+            throw new IgniteException("Failed to convert object to timestamp 
value, unexpected class " +
+                obj.getClass().getName());
+        }
+
+    }
+
+    /** */
+    public TimestampIndexKey(long dateVal, long nanos) {
+        this.dateVal = dateVal;
+        this.nanos = nanos;
+    }
+
+    /** {@inheritDoc} */
+    @Override public Object key() {
+        long millis = DateValueUtils.millisFromDateValue(dateVal) + 
TimeUnit.NANOSECONDS.toMillis(nanos);
+        millis = DateValueUtils.defaultTzMillisFromUtc(millis);
+        return new Timestamp(millis);
+    }
+
+    /** @return a date value {@link DateValueUtils}. */
+    public long dateValue() {
+        return dateVal;
+    }
+
+    /** @return nanoseconds since midnight. */
+    public long nanos() {
+        return nanos;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int type() {
+        return IndexKeyTypes.TIMESTAMP;
+    }
+
+    /** {@inheritDoc} */
+    @Override public int compare(IndexKey o) {
+        TimestampIndexKey other = (TimestampIndexKey)o;
+
+        return dateVal != other.dateVal ? Long.compare(dateVal, other.dateVal) 
: Long.compare(nanos, other.nanos);
+    }
+}
diff --git 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
index c1d01562083..8767475464e 100644
--- 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
+++ 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
@@ -58,11 +58,9 @@ import org.apache.ignite.internal.IgniteInternalFuture;
 import org.apache.ignite.internal.binary.BinaryMarshaller;
 import org.apache.ignite.internal.binary.BinaryUtils;
 import org.apache.ignite.internal.cache.query.index.IndexName;
-import org.apache.ignite.internal.cache.query.index.sorted.IndexKeyTypes;
 import org.apache.ignite.internal.cache.query.index.sorted.inline.InlineIndex;
 import 
org.apache.ignite.internal.cache.query.index.sorted.inline.InlineIndexFactory;
 import 
org.apache.ignite.internal.cache.query.index.sorted.inline.InlineIndexImpl;
-import 
org.apache.ignite.internal.cache.query.index.sorted.keys.IndexKeyFactory;
 import 
org.apache.ignite.internal.cluster.ClusterTopologyServerNotFoundException;
 import org.apache.ignite.internal.managers.IgniteMBeansManager;
 import org.apache.ignite.internal.managers.communication.GridMessageListener;
@@ -128,9 +126,6 @@ import 
org.apache.ignite.internal.processors.query.h2.dml.UpdatePlan;
 import 
org.apache.ignite.internal.processors.query.h2.index.QueryIndexDefinition;
 import 
org.apache.ignite.internal.processors.query.h2.index.client.ClientIndexDefinition;
 import 
org.apache.ignite.internal.processors.query.h2.index.client.ClientIndexFactory;
-import org.apache.ignite.internal.processors.query.h2.index.keys.DateIndexKey;
-import org.apache.ignite.internal.processors.query.h2.index.keys.TimeIndexKey;
-import 
org.apache.ignite.internal.processors.query.h2.index.keys.TimestampIndexKey;
 import 
org.apache.ignite.internal.processors.query.h2.maintenance.RebuildIndexWorkflowCallback;
 import org.apache.ignite.internal.processors.query.h2.opt.GridH2IndexBase;
 import org.apache.ignite.internal.processors.query.h2.opt.GridH2Table;
@@ -240,17 +235,6 @@ public class IgniteH2Indexing implements GridQueryIndexing 
{
     private final boolean updateInTxAllowed =
         
Boolean.getBoolean(IgniteSystemProperties.IGNITE_ALLOW_DML_INSIDE_TRANSACTION);
 
-    static {
-        // Register date/time types there as it contains H2 specific logic for 
storing and comparison those types.
-        IndexKeyFactory.register(IndexKeyTypes.DATE, DateIndexKey::new);
-        IndexKeyFactory.register(IndexKeyTypes.TIME, TimeIndexKey::new);
-        IndexKeyFactory.register(IndexKeyTypes.TIMESTAMP, 
TimestampIndexKey::new);
-
-        IndexKeyFactory.registerDateValueFactory(IndexKeyTypes.DATE, (dv, 
nanos) -> DateIndexKey.fromDateValue(dv));
-        IndexKeyFactory.registerDateValueFactory(IndexKeyTypes.TIME, (dv, 
nanos) -> TimeIndexKey.fromNanos(nanos));
-        IndexKeyFactory.registerDateValueFactory(IndexKeyTypes.TIMESTAMP, 
TimestampIndexKey::fromDateValueAndNanos);
-    }
-
     /** Make it public for test purposes. */
     public static InlineIndexFactory idxFactory = InlineIndexFactory.INSTANCE;
 
diff --git 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/index/keys/DateIndexKey.java
 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/index/keys/DateIndexKey.java
deleted file mode 100644
index 85a40717205..00000000000
--- 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/index/keys/DateIndexKey.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.query.h2.index.keys;
-
-import 
org.apache.ignite.internal.cache.query.index.sorted.keys.AbstractDateIndexKey;
-import org.apache.ignite.internal.cache.query.index.sorted.keys.IndexKey;
-import org.h2.value.ValueDate;
-
-/** */
-public class DateIndexKey extends AbstractDateIndexKey implements 
H2ValueWrapperMixin {
-    /** */
-    private final ValueDate date;
-
-    /** */
-    public DateIndexKey(Object obj) {
-        date = (ValueDate)wrapToValue(obj, type());
-    }
-
-    /** */
-    public static DateIndexKey fromDateValue(long dateVal) {
-        return new DateIndexKey(ValueDate.fromDateValue(dateVal));
-    }
-
-    /** */
-    private DateIndexKey(ValueDate date) {
-        this.date = date;
-    }
-
-    /** {@inheritDoc} */
-    @Override public Object key() {
-        return date.getDate();
-    }
-
-    /** {@inheritDoc} */
-    @Override public int compare(IndexKey o) {
-        return date.compareTo(((DateIndexKey)o).date, null);
-    }
-
-    /** {@inheritDoc} */
-    @Override public long dateValue() {
-        return date.getDateValue();
-    }
-}
diff --git 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/index/keys/H2ValueWrapperMixin.java
 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/index/keys/H2ValueWrapperMixin.java
deleted file mode 100644
index 70c7a6bd4e1..00000000000
--- 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/index/keys/H2ValueWrapperMixin.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.query.h2.index.keys;
-
-import org.apache.ignite.IgniteCheckedException;
-import org.apache.ignite.IgniteException;
-import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
-import org.apache.ignite.internal.processors.query.IgniteSQLException;
-import org.apache.ignite.internal.processors.query.h2.H2Utils;
-import org.h2.value.Value;
-
-/**
- * Mixin provides a method to wrap an object to H2 Value with correct 
exception handling.
- */
-interface H2ValueWrapperMixin {
-    /** */
-    public default Value wrapToValue(Object obj, int type) {
-        try {
-            return H2Utils.wrap(null, obj, type);
-
-        }
-        catch (ClassCastException e) {
-            throw new IgniteSQLException("Failed to wrap object into H2 Value. 
" + e.getMessage(),
-                IgniteQueryErrorCode.FIELD_TYPE_MISMATCH, e);
-
-        }
-        catch (IgniteCheckedException e) {
-            throw new IgniteException("Failed to wrap object into H2 Value.", 
e);
-        }
-    }
-}
diff --git 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/index/keys/TimeIndexKey.java
 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/index/keys/TimeIndexKey.java
deleted file mode 100644
index 2b0f7ae6d6f..00000000000
--- 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/index/keys/TimeIndexKey.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.query.h2.index.keys;
-
-import 
org.apache.ignite.internal.cache.query.index.sorted.keys.AbstractTimeIndexKey;
-import org.apache.ignite.internal.cache.query.index.sorted.keys.IndexKey;
-import org.h2.value.ValueTime;
-
-/** */
-public class TimeIndexKey extends AbstractTimeIndexKey implements 
H2ValueWrapperMixin {
-    /** */
-    private final ValueTime time;
-
-    /** */
-    public TimeIndexKey(Object obj) {
-        time = (ValueTime)wrapToValue(obj, type());
-    }
-
-    /** */
-    public static TimeIndexKey fromNanos(long nanos) {
-        return new TimeIndexKey(ValueTime.fromNanos(nanos));
-    }
-
-    /** */
-    private TimeIndexKey(ValueTime time) {
-        this.time = time;
-    }
-
-    /** {@inheritDoc} */
-    @Override public Object key() {
-        return time.getTime();
-    }
-
-    /** {@inheritDoc} */
-    @Override public long nanos() {
-        return time.getNanos();
-    }
-
-    /** {@inheritDoc} */
-    @Override public int compare(IndexKey o) {
-        return time.compareTo(((TimeIndexKey)o).time, null);
-    }
-}
diff --git 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/index/keys/TimestampIndexKey.java
 
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/index/keys/TimestampIndexKey.java
deleted file mode 100644
index 3bb7553d548..00000000000
--- 
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/index/keys/TimestampIndexKey.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.query.h2.index.keys;
-
-import 
org.apache.ignite.internal.cache.query.index.sorted.keys.AbstractTimestampIndexKey;
-import org.apache.ignite.internal.cache.query.index.sorted.keys.IndexKey;
-import org.h2.value.ValueTimestamp;
-
-/** */
-public class TimestampIndexKey extends AbstractTimestampIndexKey implements 
H2ValueWrapperMixin {
-    /** */
-    private final ValueTimestamp timestamp;
-
-    /** */
-    public TimestampIndexKey(Object obj) {
-        timestamp = (ValueTimestamp)wrapToValue(obj, type());
-    }
-
-    /** */
-    public static TimestampIndexKey fromDateValueAndNanos(long dateVal, long 
nanos) {
-        return new 
TimestampIndexKey(ValueTimestamp.fromDateValueAndNanos(dateVal, nanos));
-    }
-
-    /** */
-    private TimestampIndexKey(ValueTimestamp timestamp) {
-        this.timestamp = timestamp;
-    }
-
-    /** {@inheritDoc} */
-    @Override public Object key() {
-        return timestamp.getTimestamp();
-    }
-
-    /** {@inheritDoc} */
-    @Override public long dateValue() {
-        return timestamp.getDateValue();
-    }
-
-    /** {@inheritDoc} */
-    @Override public long nanos() {
-        return timestamp.getTimeNanos();
-    }
-
-    /** {@inheritDoc} */
-    @Override public int compare(IndexKey o) {
-        return timestamp.compareTo(((TimestampIndexKey)o).timestamp, null);
-    }
-}
diff --git 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DateIndexKeyTypeTest.java
 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DateIndexKeyTypeTest.java
new file mode 100644
index 00000000000..e111f63aa81
--- /dev/null
+++ 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DateIndexKeyTypeTest.java
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.cache.index;
+
+import java.sql.Date;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneOffset;
+import java.util.concurrent.TimeUnit;
+import org.apache.ignite.internal.cache.query.index.sorted.keys.DateIndexKey;
+import org.apache.ignite.internal.cache.query.index.sorted.keys.TimeIndexKey;
+import 
org.apache.ignite.internal.cache.query.index.sorted.keys.TimestampIndexKey;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.h2.util.LocalDateTimeUtils;
+import org.h2.value.ValueDate;
+import org.h2.value.ValueTime;
+import org.h2.value.ValueTimestamp;
+import org.junit.Test;
+
+/**
+ * Tests that core IndexKey values calculation compatible with H2 date/time 
values calculation.
+ */
+public class DateIndexKeyTypeTest extends GridCommonAbstractTest {
+    /** */
+    private final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
+
+    /** */
+    private final DateFormat timeFormat = new SimpleDateFormat("HH:mm:ss.SSS");
+
+    /** */
+    private final DateFormat tsFormat = new SimpleDateFormat("yyyy-MM-dd 
HH:mm:ss.SSS");
+
+    /** */
+    private void checkDate(long millis) {
+        Date date = new Date(millis);
+        DateIndexKey key = new DateIndexKey(date);
+        ValueDate v = ValueDate.get(date);
+
+        assertEquals(v.getDateValue(), key.dateValue());
+
+        assertEquals(dateFormat.format(date), 
dateFormat.format((java.util.Date)key.key()));
+    }
+
+    /** */
+    private void checkLocalDate(long seconds, int nanos) {
+        LocalDate locDate = LocalDateTime.ofEpochSecond(seconds, nanos, 
ZoneOffset.UTC).toLocalDate();
+
+        ValueDate locV = 
(ValueDate)LocalDateTimeUtils.localDateToDateValue(locDate);
+        DateIndexKey locKey = new DateIndexKey(locDate);
+
+        assertEquals(locV.getDateValue(), locKey.dateValue());
+    }
+
+    /** */
+    private void checkTimestamp(long millis, int nanos) {
+        Timestamp ts = new Timestamp(millis);
+        ts.setNanos(nanos);
+        TimestampIndexKey key = new TimestampIndexKey(ts);
+        ValueTimestamp v = ValueTimestamp.get(ts);
+
+        assertEquals(v.getDateValue(), key.dateValue());
+        assertEquals(v.getTimeNanos(), key.nanos());
+
+        assertEquals(tsFormat.format(ts), 
tsFormat.format((java.util.Date)key.key()));
+    }
+
+    /** */
+    private void checkLocalDateTime(long seconds, int nanos) {
+        LocalDateTime locDateTime = LocalDateTime.ofEpochSecond(seconds, 
nanos, ZoneOffset.UTC);
+
+        ValueTimestamp locV = 
(ValueTimestamp)LocalDateTimeUtils.localDateTimeToValue(locDateTime);
+        TimestampIndexKey locKey = new TimestampIndexKey(locDateTime);
+
+        assertEquals(locV.getDateValue(), locKey.dateValue());
+        assertEquals(locV.getTimeNanos(), locKey.nanos());
+    }
+
+    /** */
+    private void checkTime(long millis) {
+        Time t = new Time(millis);
+        TimeIndexKey key = new TimeIndexKey(t);
+        ValueTime v = ValueTime.get(t);
+
+        assertEquals(v.getNanos(), key.nanos());
+
+        assertEquals(timeFormat.format(t), 
timeFormat.format((java.util.Date)key.key()));
+    }
+
+    /** */
+    private void checkLocalTime(long seconds, int nanos) {
+        LocalTime locTime = LocalDateTime.ofEpochSecond(seconds, nanos, 
ZoneOffset.UTC).toLocalTime();
+
+        ValueTime locV = 
(ValueTime)LocalDateTimeUtils.localTimeToTimeValue(locTime);
+        TimeIndexKey locKey = new TimeIndexKey(locTime);
+
+        assertEquals(locV.getNanos(), locKey.nanos());
+    }
+
+    /** */
+    private void checkAllTypes(long tsStart, long tsEnd, long increment) {
+        for (long millis = tsStart; millis <= tsEnd; millis += increment) {
+            checkDate(millis);
+            checkTimestamp(millis, 0);
+            checkTimestamp(millis, 1);
+            checkTime(millis);
+
+            long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
+
+            checkLocalDate(seconds, 0);
+            checkLocalDateTime(seconds, 0);
+            checkLocalTime(seconds, 0);
+        }
+    }
+
+    /** */
+    @Test
+    public void testIndexKeyTypes() throws Exception {
+        // Check every half a day since -1000-01-01 to 3000-01-01.
+        checkAllTypes(
+            dateFormat.parse("-1000-01-01").getTime(),
+            dateFormat.parse("3000-01-01").getTime(),
+            TimeUnit.HOURS.toMillis(12)
+        );
+
+        // Check every half an hour since 1970-01-01 to 2023-01-01.
+        checkAllTypes(
+            0,
+            dateFormat.parse("2023-01-01").getTime(),
+            TimeUnit.MINUTES.toMillis(30)
+        );
+
+        // Check local date types with nanoseconds.
+        for (String date : new String[] {"-1000-01-01", "1960-01-01", 
"2023-01-01"}) {
+            long seconds = 
TimeUnit.MILLISECONDS.toSeconds(dateFormat.parse(date).getTime());
+            for (int nanos : new int[] {1, 1_000, 1_000_000}) {
+                checkLocalDate(seconds, nanos);
+                checkLocalDateTime(seconds, nanos);
+                checkLocalTime(seconds, nanos);
+            }
+        }
+    }
+}
diff --git 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/CreateIndexOnInvalidDataTypeTest.java
 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/CreateIndexOnInvalidDataTypeTest.java
index da1935f2c8e..e92e609d976 100644
--- 
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/CreateIndexOnInvalidDataTypeTest.java
+++ 
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/CreateIndexOnInvalidDataTypeTest.java
@@ -114,7 +114,7 @@ public class CreateIndexOnInvalidDataTypeTest extends 
AbstractIndexingCommonTest
             sql("CREATE INDEX TEST_VAL_DATE_IDX ON TEST(VAL_DATE)");
 
             return null;
-        }, IgniteSQLException.class, "java.util.Date cannot be cast to 
java.sql.Date");
+        }, IgniteSQLException.class, "unexpected class");
 
         // Wait for node stop if it is initiated by FailureHandler
         U.sleep(1000);
diff --git 
a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite3.java
 
b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite3.java
index 8d53763a233..10905a573fa 100644
--- 
a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite3.java
+++ 
b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite3.java
@@ -83,6 +83,7 @@ import 
org.apache.ignite.internal.processors.cache.encryption.EncryptedSqlTableT
 import 
org.apache.ignite.internal.processors.cache.encryption.EncryptedSqlTemplateTableTest;
 import 
org.apache.ignite.internal.processors.cache.index.BasicJavaTypesIndexTest;
 import 
org.apache.ignite.internal.processors.cache.index.BasicSqlTypesIndexTest;
+import org.apache.ignite.internal.processors.cache.index.DateIndexKeyTypeTest;
 import 
org.apache.ignite.internal.processors.cache.index.H2ConnectionLeaksSelfTest;
 import 
org.apache.ignite.internal.processors.cache.index.H2RowCachePageEvictionTest;
 import org.apache.ignite.internal.processors.cache.index.H2RowCacheSelfTest;
@@ -347,6 +348,7 @@ import org.junit.runners.Suite;
     BasicSqlTypesIndexTest.class,
     BasicJavaTypesIndexTest.class,
     PojoIndexLocalQueryTest.class,
+    DateIndexKeyTypeTest.class,
 
     //Cancellation of queries.
     KillQueryTest.class,

Reply via email to