package org.apache.hadoop.hive.ql.io.parquet.timestamp;

import org.apache.hadoop.hive.common.type.Timestamp;

import static java.lang.Math.toIntExact;
import static java.util.concurrent.TimeUnit.SECONDS;

public final class NanoTimeUtils
{
    private NanoTimeUtils() {}

    private static final int JULIAN_EPOCH_OFFSET_DAYS = 2_440_588;

    public static NanoTime getNanoTime(Timestamp timestamp, @SuppressWarnings("unused") boolean ignored)
    {
        int epochDay = toIntExact(SECONDS.toDays(timestamp.toEpochSecond()));
        int julianDay = JULIAN_EPOCH_OFFSET_DAYS + epochDay;

        long timeOfDaySeconds = timestamp.toEpochSecond() % 86400;
        long timeOfDayNanos = SECONDS.toNanos(timeOfDaySeconds) + timestamp.getNanos();

        return new NanoTime(julianDay, timeOfDayNanos);
    }
}

@@ -100,24 +100,102 @@
 Timestamp;%0A%0A
+import static java.lang.Math.floorDiv;%0Aimport static java.lang.Math.floorMod;%0A
 import stati
@@ -410,16 +410,72 @@
 440_588;
+%0A    private static final long SECONDS_PER_DAY = 86400L;
 %0A%0A    pu
@@ -591,74 +591,127 @@
     
-int epochDay = toIntExact(SECONDS.toDays(timestamp.toEpochSecond()
+long epochSeconds = timestamp.toEpochSecond();%0A        int epochDay = toIntExact(floorDiv(epochSeconds, SECONDS_PER_DAY
 ));%0A
@@ -808,41 +808,47 @@
 s = 
-timestamp.toEpochSecond() %25 86400
+floorMod(epochSeconds, SECONDS_PER_DAY)
 ;%0A  

Fix Parquet encoding for timestamps before epoch