Skip to content

Commit

Permalink
Moved Parquet specific methods out of DateTimeUtils (#4819)
Browse files Browse the repository at this point in the history
  • Loading branch information
malhotrashivam authored Nov 14, 2023
1 parent a61a8ef commit df45e1c
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 80 deletions.
52 changes: 0 additions & 52 deletions engine/time/src/main/java/io/deephaven/time/DateTimeUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -982,21 +982,6 @@ public static long epochNanos(@Nullable final ZonedDateTime dateTime) {
return safeComputeNanos(dateTime.toEpochSecond(), dateTime.getNano());
}

/**
* Returns nanoseconds from the Epoch for a {@link LocalDateTime} value in UTC timezone.
*
* @param localDateTime the local date time to compute the Epoch offset for
* @return nanoseconds since Epoch, or a NULL_LONG value if the local date time is null
*/
@ScriptApi
public static long epochNanosUTC(@Nullable final LocalDateTime localDateTime) {
if (localDateTime == null) {
return NULL_LONG;
}
return TimeUnit.SECONDS.toNanos(localDateTime.toEpochSecond(ZoneOffset.UTC))
+ localDateTime.toLocalTime().getNano();
}

/**
* Returns microseconds from the Epoch for an {@link Instant} value.
*
Expand Down Expand Up @@ -1415,43 +1400,6 @@ public static ZonedDateTime excelToZonedDateTime(final double excel, @Nullable f
return epochMillisToZonedDateTime(excelTimeToEpochMillis(excel, timeZone), timeZone);
}

/**
* Converts nanoseconds from the Epoch to a {@link LocalDateTime} in UTC timezone.
*
* @param nanos nanoseconds since Epoch
* @return {@code null} if the input is {@link QueryConstants#NULL_LONG}; otherwise the input nanoseconds from the
* Epoch converted to a {@link LocalDateTime} in UTC timezone
*/
public static @Nullable LocalDateTime epochNanosToLocalDateTimeUTC(final long nanos) {
return nanos == NULL_LONG ? null
: LocalDateTime.ofEpochSecond(nanos / 1_000_000_000L, (int) (nanos % 1_000_000_000L), ZoneOffset.UTC);
}

/**
* Converts microseconds from the Epoch to a {@link LocalDateTime} in UTC timezone.
*
* @param micros microseconds since Epoch
* @return {@code null} if the input is {@link QueryConstants#NULL_LONG}; otherwise the input microseconds from the
* Epoch converted to a {@link LocalDateTime} in UTC timezone
*/
public static @Nullable LocalDateTime epochMicrosToLocalDateTimeUTC(final long micros) {
return micros == NULL_LONG ? null
: LocalDateTime.ofEpochSecond(micros / 1_000_000L, (int) ((micros % 1_000_000L) * MICRO),
ZoneOffset.UTC);
}

/**
* Converts milliseconds from the Epoch to a {@link LocalDateTime} in UTC timezone.
*
* @param millis milliseconds since Epoch
* @return {@code null} if the input is {@link QueryConstants#NULL_LONG}; otherwise the input milliseconds from the
* Epoch converted to a {@link LocalDateTime} in UTC timezone
*/
public static @Nullable LocalDateTime epochMillisToLocalDateTimeUTC(final long millis) {
return millis == NULL_LONG ? null
: LocalDateTime.ofEpochSecond(millis / 1_000L, (int) ((millis % 1_000L) * MILLI), ZoneOffset.UTC);
}

// endregion

// region Arithmetic
Expand Down
16 changes: 0 additions & 16 deletions engine/time/src/test/java/io/deephaven/time/TestDateTimeUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -1391,10 +1391,6 @@ public void testEpochNanos() {

TestCase.assertEquals(nanos, DateTimeUtils.epochNanos(dt3));
TestCase.assertEquals(NULL_LONG, DateTimeUtils.epochNanos((ZonedDateTime) null));

final LocalDateTime ldt = LocalDateTime.ofInstant(dt2, ZoneId.of("UTC"));
TestCase.assertEquals(nanos, DateTimeUtils.epochNanosUTC(ldt));
TestCase.assertEquals(NULL_LONG, DateTimeUtils.epochNanosUTC(null));
}

public void testEpochMicros() {
Expand Down Expand Up @@ -1460,10 +1456,6 @@ public void testEpochNanosTo() {
TestCase.assertEquals(dt3, DateTimeUtils.epochNanosToZonedDateTime(nanos, TZ_JP));
TestCase.assertNull(DateTimeUtils.epochNanosToZonedDateTime(NULL_LONG, TZ_JP));
TestCase.assertNull(DateTimeUtils.epochNanosToZonedDateTime(nanos, null));

final LocalDateTime ldt = LocalDateTime.ofInstant(dt2, ZoneId.of("UTC"));
TestCase.assertEquals(ldt, DateTimeUtils.epochNanosToLocalDateTimeUTC(nanos));
TestCase.assertNull(DateTimeUtils.epochNanosToLocalDateTimeUTC(NULL_LONG));
}

public void testEpochMicrosTo() {
Expand All @@ -1479,10 +1471,6 @@ public void testEpochMicrosTo() {
TestCase.assertEquals(dt3, DateTimeUtils.epochMicrosToZonedDateTime(micros, TZ_JP));
TestCase.assertNull(DateTimeUtils.epochMicrosToZonedDateTime(NULL_LONG, TZ_JP));
TestCase.assertNull(DateTimeUtils.epochMicrosToZonedDateTime(micros, null));

final LocalDateTime ldt = LocalDateTime.ofInstant(dt2, ZoneId.of("UTC"));
TestCase.assertEquals(ldt, DateTimeUtils.epochMicrosToLocalDateTimeUTC(micros));
TestCase.assertNull(DateTimeUtils.epochMicrosToLocalDateTimeUTC(NULL_LONG));
}

public void testEpochMillisTo() {
Expand All @@ -1498,10 +1486,6 @@ public void testEpochMillisTo() {
TestCase.assertEquals(dt3, DateTimeUtils.epochMillisToZonedDateTime(millis, TZ_JP));
TestCase.assertNull(DateTimeUtils.epochMillisToZonedDateTime(NULL_LONG, TZ_JP));
TestCase.assertNull(DateTimeUtils.epochMillisToZonedDateTime(millis, null));

final LocalDateTime ldt = LocalDateTime.ofInstant(dt2, ZoneId.of("UTC"));
TestCase.assertEquals(ldt, DateTimeUtils.epochMillisToLocalDateTimeUTC(millis));
TestCase.assertNull(DateTimeUtils.epochMillisToLocalDateTimeUTC(NULL_LONG));
}

public void testEpochSecondsTo() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import io.deephaven.chunk.ChunkType;
import io.deephaven.chunk.attributes.Any;
import io.deephaven.time.DateTimeUtils;
import io.deephaven.parquet.table.util.TransferUtils;
import io.deephaven.util.QueryConstants;
import org.apache.parquet.schema.LogicalTypeAnnotation;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -79,21 +79,21 @@ private static LocalDateTime[] convertResultHelper(@NotNull final Object result,
private static final class ToLocalDateTimePageFromMillis<ATTR extends Any> extends ToLocalDateTimePage<ATTR> {
@Override
public LocalDateTime[] convertResult(@NotNull final Object result) {
return convertResultHelper(result, DateTimeUtils::epochMillisToLocalDateTimeUTC);
return convertResultHelper(result, TransferUtils::epochMillisToLocalDateTimeUTC);
}
}

private static final class ToLocalDateTimePageFromMicros<ATTR extends Any> extends ToLocalDateTimePage<ATTR> {
@Override
public LocalDateTime[] convertResult(@NotNull final Object result) {
return convertResultHelper(result, DateTimeUtils::epochMicrosToLocalDateTimeUTC);
return convertResultHelper(result, TransferUtils::epochMicrosToLocalDateTimeUTC);
}
}

private static final class ToLocalDateTimePageFromNanos<ATTR extends Any> extends ToLocalDateTimePage<ATTR> {
@Override
public LocalDateTime[] convertResult(@NotNull final Object result) {
return convertResultHelper(result, DateTimeUtils::epochNanosToLocalDateTimeUTC);
return convertResultHelper(result, TransferUtils::epochNanosToLocalDateTimeUTC);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

import io.deephaven.engine.rowset.RowSequence;
import io.deephaven.engine.table.ColumnSource;
import io.deephaven.time.DateTimeUtils;
import io.deephaven.parquet.table.util.TransferUtils;
import org.jetbrains.annotations.NotNull;

import java.nio.LongBuffer;
Expand Down Expand Up @@ -38,7 +38,7 @@ void resizeBuffer(final int length) {
@Override
void copyToBuffer(@NotNull final EncodedData<LocalDateTime[]> data) {
for (final LocalDateTime t : data.encodedValues) {
buffer.put(DateTimeUtils.epochNanosUTC(t));
buffer.put(TransferUtils.epochNanosUTC(t));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import io.deephaven.chunk.attributes.Values;
import io.deephaven.engine.rowset.RowSequence;
import io.deephaven.engine.table.ColumnSource;
import io.deephaven.time.DateTimeUtils;
import io.deephaven.parquet.table.util.TransferUtils;
import org.jetbrains.annotations.NotNull;

import java.nio.LongBuffer;
Expand All @@ -31,7 +31,7 @@ final class LocalDateTimeTransfer extends GettingPrimitiveTransfer<ObjectChunk<L
void copyAllFromChunkToBuffer() {
final int chunkSize = chunk.size();
for (int chunkIdx = 0; chunkIdx < chunkSize; ++chunkIdx) {
buffer.put(DateTimeUtils.epochNanosUTC(chunk.get(chunkIdx)));
buffer.put(TransferUtils.epochNanosUTC(chunk.get(chunkIdx)));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import io.deephaven.engine.primitive.iterator.CloseableIterator;
import io.deephaven.engine.rowset.RowSequence;
import io.deephaven.engine.table.ColumnSource;
import io.deephaven.time.DateTimeUtils;
import io.deephaven.parquet.table.util.TransferUtils;
import io.deephaven.vector.ObjectVector;
import org.jetbrains.annotations.NotNull;

Expand All @@ -34,7 +34,7 @@ void resizeBuffer(final int length) {
@Override
void copyToBuffer(@NotNull final EncodedData<ObjectVector<LocalDateTime>> data) {
try (final CloseableIterator<LocalDateTime> dataIterator = data.encodedValues.iterator()) {
dataIterator.forEachRemaining((LocalDateTime t) -> buffer.put(DateTimeUtils.epochNanosUTC(t)));
dataIterator.forEachRemaining((LocalDateTime t) -> buffer.put(TransferUtils.epochNanosUTC(t)));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package io.deephaven.parquet.table.util;

import io.deephaven.time.DateTimeUtils;
import io.deephaven.util.QueryConstants;
import org.jetbrains.annotations.Nullable;

import java.time.LocalDateTime;
import java.time.ZoneOffset;

/**
* Internal library with utility methods for converting data between Deephaven and Parquet.
*/
public class TransferUtils {
/**
* Returns nanoseconds from the Epoch for a {@link LocalDateTime} value in UTC timezone.
*
* @param localDateTime the local date time to compute the Epoch offset for
* @return nanoseconds since Epoch, or a NULL_LONG value if the local date time is null
*/
public static long epochNanosUTC(@Nullable final LocalDateTime localDateTime) {
if (localDateTime == null) {
return QueryConstants.NULL_LONG;
}
return DateTimeUtils.secondsToNanos(localDateTime.toEpochSecond(ZoneOffset.UTC))
+ localDateTime.toLocalTime().getNano();
}

/**
* Converts nanoseconds from the Epoch to a {@link LocalDateTime} in UTC timezone.
*
* @param nanos nanoseconds since Epoch
* @return {@code null} if the input is {@link QueryConstants#NULL_LONG}; otherwise the input nanoseconds from the
* Epoch converted to a {@link LocalDateTime} in UTC timezone
*/
public static @Nullable LocalDateTime epochNanosToLocalDateTimeUTC(final long nanos) {
return nanos == QueryConstants.NULL_LONG ? null
: LocalDateTime.ofEpochSecond(nanos / 1_000_000_000L, (int) (nanos % 1_000_000_000L), ZoneOffset.UTC);
}

/**
* Converts microseconds from the Epoch to a {@link LocalDateTime} in UTC timezone.
*
* @param micros microseconds since Epoch
* @return {@code null} if the input is {@link QueryConstants#NULL_LONG}; otherwise the input microseconds from the
* Epoch converted to a {@link LocalDateTime} in UTC timezone
*/
public static @Nullable LocalDateTime epochMicrosToLocalDateTimeUTC(final long micros) {
return micros == QueryConstants.NULL_LONG ? null
: LocalDateTime.ofEpochSecond(micros / 1_000_000L, (int) ((micros % 1_000_000L) * DateTimeUtils.MICRO),
ZoneOffset.UTC);
}

/**
* Converts milliseconds from the Epoch to a {@link LocalDateTime} in UTC timezone.
*
* @param millis milliseconds since Epoch
* @return {@code null} if the input is {@link QueryConstants#NULL_LONG}; otherwise the input milliseconds from the
* Epoch converted to a {@link LocalDateTime} in UTC timezone
*/
public static @Nullable LocalDateTime epochMillisToLocalDateTimeUTC(final long millis) {
return millis == QueryConstants.NULL_LONG ? null
: LocalDateTime.ofEpochSecond(millis / 1_000L, (int) ((millis % 1_000L) * DateTimeUtils.MILLI),
ZoneOffset.UTC);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending
*/
package io.deephaven.parquet.table;

import io.deephaven.parquet.table.util.TransferUtils;
import io.deephaven.time.DateTimeUtils;
import io.deephaven.util.QueryConstants;
import junit.framework.TestCase;
import org.junit.Test;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;

final public class TestTransferUtils {

@Test
public void testEpochNanosUTC() {
final long nanos = 123456789123456789L;
final Instant dt2 = Instant.ofEpochSecond(0, nanos);
final LocalDateTime ldt = LocalDateTime.ofInstant(dt2, ZoneId.of("UTC"));
TestCase.assertEquals(nanos, TransferUtils.epochNanosUTC(ldt));
TestCase.assertEquals(QueryConstants.NULL_LONG, TransferUtils.epochNanosUTC(null));
}

@Test
public void testEpochNanosTo() {
final long nanos = 123456789123456789L;
final Instant dt2 = Instant.ofEpochSecond(0, nanos);
final LocalDateTime ldt = LocalDateTime.ofInstant(dt2, ZoneId.of("UTC"));
TestCase.assertEquals(ldt, TransferUtils.epochNanosToLocalDateTimeUTC(nanos));
TestCase.assertNull(TransferUtils.epochNanosToLocalDateTimeUTC(QueryConstants.NULL_LONG));
}

@Test
public void testEpochMicrosTo() {
long nanos = 123456789123456789L;
final long micros = DateTimeUtils.nanosToMicros(nanos);
nanos = DateTimeUtils.microsToNanos(micros);
final Instant dt2 = Instant.ofEpochSecond(0, nanos);
final LocalDateTime ldt = LocalDateTime.ofInstant(dt2, ZoneId.of("UTC"));
TestCase.assertEquals(ldt, TransferUtils.epochMicrosToLocalDateTimeUTC(micros));
TestCase.assertNull(TransferUtils.epochMicrosToLocalDateTimeUTC(QueryConstants.NULL_LONG));
}

@Test
public void testEpochMillisTo() {
long nanos = 123456789123456789L;
final long millis = DateTimeUtils.nanosToMillis(nanos);
nanos = DateTimeUtils.millisToNanos(millis);
final Instant dt2 = Instant.ofEpochSecond(0, nanos);
final LocalDateTime ldt = LocalDateTime.ofInstant(dt2, ZoneId.of("UTC"));
TestCase.assertEquals(ldt, TransferUtils.epochMillisToLocalDateTimeUTC(millis));
TestCase.assertNull(TransferUtils.epochMillisToLocalDateTimeUTC(QueryConstants.NULL_LONG));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,10 @@ public static void main(String[] args) throws IOException {
replaceAll(PARQUET_INSTANT_VECTOR_TRANSFER_PATH, PARQUET_TIME_VECTOR_TRANSFER_PATH, null, NO_EXCEPTIONS, pairs);

pairs = new String[][] {
{"io.deephaven.time.DateTimeUtils", "io.deephaven.parquet.table.util.TransferUtils"},
{"InstantArrayTransfer", "LocalDateTimeArrayTransfer"},
{"InstantVectorTransfer", "LocalDateTimeVectorTransfer"},
{"DateTimeUtils.epochNanos", "DateTimeUtils.epochNanosUTC"},
{"DateTimeUtils.epochNanos", "TransferUtils.epochNanosUTC"},
{"Instant", "LocalDateTime"}
};
replaceAll(PARQUET_INSTANT_ARRAY_TRANSFER_PATH, PARQUET_LOCAL_DATE_TIME_ARRAY_TRANSFER_PATH, null,
Expand All @@ -80,9 +81,10 @@ public static void main(String[] args) throws IOException {
NO_EXCEPTIONS, pairs);

pairs = new String[][] {
{"io.deephaven.time.DateTimeUtils", "io.deephaven.parquet.table.util.TransferUtils"},
{"TimeTransfer", "LocalDateTimeTransfer"},
{"LocalTime", "LocalDateTime"},
{"DateTimeUtils.nanosOfDay", "DateTimeUtils.epochNanosUTC"}
{"DateTimeUtils.nanosOfDay", "TransferUtils.epochNanosUTC"}
};
replaceAll(PARQUET_TIME_TRANSFER_PATH, PARQUET_LOCAL_DATE_TIME_TRANSFER_PATH, null, NO_EXCEPTIONS, pairs);

Expand Down

0 comments on commit df45e1c

Please sign in to comment.