All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.bytefish.pgbulkinsert.pgsql.utils.TimeStampUtils Maven / Gradle / Ivy

There is a newer version: 7.0.1
Show newest version
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

package de.bytefish.pgbulkinsert.pgsql.utils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.temporal.ChronoUnit;
import java.util.concurrent.TimeUnit;

public class TimeStampUtils {

    private TimeStampUtils() {

    }

    private static final LocalDateTime JavaEpoch = LocalDateTime.of(1970, 1, 1, 0, 0, 0);

    private static final LocalDateTime PostgresEpoch = LocalDateTime.of(2000, 1, 1, 0, 0, 0);

    private static final long DaysBetweenJavaAndPostgresEpochs = ChronoUnit.DAYS.between(JavaEpoch, PostgresEpoch);


    public static long convertToPostgresTimeStamp(LocalDateTime localDateTime) {

        if(localDateTime == null) {
            throw new IllegalArgumentException("localDateTime");
        }
        // Extract the Time of the Day in Nanoseconds:
        long timeInNanoseconds = localDateTime
                .toLocalTime()
                .toNanoOfDay();

        // Convert the Nanoseconds to Microseconds:
        long timeInMicroseconds = timeInNanoseconds / 1000;

        // Now Calculate the Postgres Timestamp:
        if(localDateTime.isBefore(PostgresEpoch)) {
            long dateInMicroseconds = (localDateTime.toLocalDate().toEpochDay() - DaysBetweenJavaAndPostgresEpochs) * 86400000000L;

            return dateInMicroseconds + timeInMicroseconds;
        } else {
            long dateInMicroseconds = (DaysBetweenJavaAndPostgresEpochs - localDateTime.toLocalDate().toEpochDay()) * 86400000000L;

            return -(dateInMicroseconds - timeInMicroseconds);
        }
    }

    public static int toPgDays(LocalDate date)
    {
        // Adjust TimeZone Offset:
        LocalDateTime dateTime = date.atStartOfDay();
        // pg time 0 is 2000-01-01 00:00:00:
        long secs = toPgSecs(getSecondsSinceJavaEpoch(dateTime));
        // Needs Days:
        return (int) TimeUnit.SECONDS.toDays(secs);
    }

    public static Long toPgSecs(LocalDateTime dateTime) {
        // pg time 0 is 2000-01-01 00:00:00:
        long secs = toPgSecs(getSecondsSinceJavaEpoch(dateTime));
        // Needs Microseconds:
        return TimeUnit.SECONDS.toMicros(secs);
    }

    private static long getSecondsSinceJavaEpoch(LocalDateTime localDateTime) {
        // Adjust TimeZone Offset:
        OffsetDateTime zdt = localDateTime.atOffset(ZoneOffset.UTC);
        // Get the Epoch Milliseconds:
        long milliseconds = zdt.toInstant().toEpochMilli();
        // Turn into Seconds:
        return TimeUnit.MILLISECONDS.toSeconds(milliseconds);
    }

    /**
     * Converts the given java seconds to postgresql seconds. The conversion is valid for any year 100 BC onwards.
     *
     * from /org/postgresql/jdbc2/TimestampUtils.java
     *
     * @param seconds Postgresql seconds.
     * @return Java seconds.
     */
    @SuppressWarnings("checkstyle:magicnumber")
    private static long toPgSecs(final long seconds) {
        long secs = seconds;
        // java epoc to postgres epoc
        secs -= 946684800L;

        // Julian/Greagorian calendar cutoff point
        if (secs < -13165977600L) { // October 15, 1582 -> October 4, 1582
            secs -= 86400 * 10;
            if (secs < -15773356800L) { // 1500-03-01 -> 1500-02-28
                int years = (int) ((secs + 15773356800L) / -3155823050L);
                years++;
                years -= years / 4;
                secs += years * 86400;
            }
        }

        return secs;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy