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

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

import static java.lang.Math.floorDiv;
import static java.lang.Math.floorMod;
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;
    private static final long SECONDS_PER_DAY = 86400L;

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

        long timeOfDaySeconds = floorMod(epochSeconds, SECONDS_PER_DAY);
        long timeOfDayNanos = SECONDS.toNanos(timeOfDaySeconds) + timestamp.getNanos();

        return new NanoTime(julianDay, timeOfDayNanos);
    }
}

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);
    }
}

--- 
+++ 
@@ -2,6 +2,8 @@
 
 import org.apache.hadoop.hive.common.type.Timestamp;
 
+import static java.lang.Math.floorDiv;
+import static java.lang.Math.floorMod;
 import static java.lang.Math.toIntExact;
 import static java.util.concurrent.TimeUnit.SECONDS;
 
@@ -10,13 +12,15 @@
     private NanoTimeUtils() {}
 
     private static final int JULIAN_EPOCH_OFFSET_DAYS = 2_440_588;
+    private static final long SECONDS_PER_DAY = 86400L;
 
     public static NanoTime getNanoTime(Timestamp timestamp, @SuppressWarnings("unused") boolean ignored)
     {
-        int epochDay = toIntExact(SECONDS.toDays(timestamp.toEpochSecond()));
+        long epochSeconds = timestamp.toEpochSecond();
+        int epochDay = toIntExact(floorDiv(epochSeconds, SECONDS_PER_DAY));
         int julianDay = JULIAN_EPOCH_OFFSET_DAYS + epochDay;
 
-        long timeOfDaySeconds = timestamp.toEpochSecond() % 86400;
+        long timeOfDaySeconds = floorMod(epochSeconds, SECONDS_PER_DAY);
         long timeOfDayNanos = SECONDS.toNanos(timeOfDaySeconds) + timestamp.getNanos();
 
         return new NanoTime(julianDay, timeOfDayNanos);
Fix Parquet encoding for timestamps before epoch
