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

net.quasardb.qdb.ts.Timespec Maven / Gradle / Ivy

Go to download

API for the JNI components of the QuasarDB API for Java. Should not be included directly.

There is a newer version: 3.14.1
Show newest version
package net.quasardb.qdb.ts;

import java.io.Serializable;
import java.sql.Timestamp;
import java.time.ZoneId;
import java.time.LocalDateTime;
import java.time.Instant;
import java.time.Clock;

import net.quasardb.qdb.jni.*;
import net.quasardb.qdb.exception.InvalidArgumentException;

/**
 * Nanosecond precision time specification for QuasarDB. Allows construction from
 * multiple different clock sources, and interaction with the QuasarDB backend.
 *
 * @see Value
 * @see Row
 */
public class Timespec implements Serializable {
    /**
     * Lowest possible representable time (identical to epoch).
     */
    public static final Timespec MIN_VALUE = new Timespec(0, 0);
    /**
     * Largest possible representable time.
     */
    public static final Timespec MAX_VALUE = new Timespec(Long.MAX_VALUE, Long.MAX_VALUE);


    private static Clock clock = new NanoClock();
    protected long sec;
    protected long nsec;

    /**
     * Construct a new Timespec null value. Constants align with what is used by QuasarDB
     * in the backend.
     */
    public Timespec(){
        this.sec = Constants.minTime;
        this.nsec = Constants.minTime;
    }

    /**
     * Construct a new timespec from milliseconds.
     */
    public Timespec(long msec) {
        assert(msec >= 0);

        this.sec = msec / 1000;
        this.nsec = (msec % 1000) * 1000000;
    }

    public Timespec(long sec, long nsec){
        assert (sec >= 0);
        assert (nsec >= 0);

        this.sec = sec;
        this.nsec = nsec;
    }

    public Timespec (LocalDateTime value) {
        this(value.atZone(ZoneId.systemDefault()).toEpochSecond(),
             value.getNano());
    }

    public Timespec (Timestamp value) {
        this(value.toLocalDateTime());
    }

    public Timespec (Instant value) {
        this(value.getEpochSecond(),
             value.getNano());
    }

    public long getSec() {
        return this.sec;
    }

    public long getNano() {
        return this.nsec;
    }

    public boolean isBefore(Timespec rhs) {
        if (this.sec < rhs.sec) {
            return true;
        } else if (this.sec == rhs.sec &&
            this.nsec < rhs.nsec) {
            return true;
        }

        return false;
    }

    public boolean isEmpty() {
        return this.sec == Constants.minTime && this.nsec == Constants.minTime;
    }

    /**
     * Construct a new Timespec based on a {@link NanoClock} that provides nanosecond
     * precision.
     *
     * @see NanoClock
     */
    public static Timespec now() {
        return new Timespec(Instant.now(Timespec.clock));
    }

    /**
     * Construct a new Timespec using your own custom Clock.
     */
    public static Timespec now(Clock clock) {
        return new Timespec(Instant.now(clock));
    }

    /**
     * Returns copy of this instance with the specified duration in seconds added.
     */
    public Timespec plusSeconds(long secondsToAdd) {
        return new Timespec(this.sec + secondsToAdd,
                            this.nsec);
    }

    /**
     * Returns copy of this instance with the specified duration in nanoseconds added.
     */
    public Timespec plusNanos(long nanosToAdd) {
        return new Timespec(this.sec,
                            this.nsec + nanosToAdd);
    }

    /**
     * Returns copy of this instance with the specified duration in seconds deducted.
     */
    public Timespec minusSeconds(long secondsToDeduct) {
        return new Timespec(this.sec - secondsToDeduct,
                            this.nsec);
    }

    /**
     * Returns copy of this instance with the specified duration in nanoseconds deducted.
     */
    public Timespec minusNanos(long nanosToDeduct) {
        return new Timespec(this.sec,
                            this.nsec - nanosToDeduct);
    }


    /**
     * Converts this Timespec into an {@link Instant}.
     */
    public Instant asInstant() {
        return Instant.ofEpochSecond(this.sec,
                                     this.nsec);
    }

    /**
     * Converts this Timespec into an {@link LocalDateTime}.
     */
    public LocalDateTime asLocalDateTime() {
        return LocalDateTime.ofInstant(this.asInstant(),
                                       ZoneId.systemDefault());
    }

    /**
     * Converts this Timespec into an sql {@link Timestamp}.
     */
    public Timestamp asTimestamp() {
        return Timestamp.valueOf(this.asLocalDateTime());
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Timespec)) return false;
        Timespec rhs = (Timespec)obj;

        return rhs.getSec() == this.sec && rhs.getNano() == this.nsec;
    }

    public String toString() {
        return "Timespec (" + this.asInstant().toString() + ")";
    }

    /**
     * Converts this timespec to the number of milliseconds from the epoch of 1970-01-01
     */
    public long toEpochMillis() {
        return (long)(this.sec * 1000) + (long)(this.nsec / 1000000);
    }

    /**
     * Converts this timespec to the number of nanoseconds from the epoch of 1970-01-01
     */
    public long toEpochNanos() {
        return (this.sec * 1000000000) + this.nsec;
    }


    /**
     * Returns the smallest timespec between the two, that is, the time that is pointing
     * towards the earliest point in time.
     */
    public static Timespec min(Timespec lhs, Timespec rhs) {
        if (lhs.sec == Constants.minTime && rhs.sec != Constants.minTime) {
            return rhs;
        }
        if (rhs.sec == Constants.minTime && lhs.sec != Constants.minTime) {
            return lhs;
        }

        if (rhs.sec == Constants.minTime && lhs.sec == Constants.minTime) {
            throw new InvalidArgumentException("Both time ranges are null.");
        }

        if (lhs.sec < rhs.sec) {
            return lhs;
        }

        if (rhs.sec < lhs.sec) {
            return rhs;
        }

        // lhs.sec == rhs.sec
        if (lhs.nsec < rhs.nsec) {
            return lhs;
        }

        return rhs;
    }

    /**
     * Returns the smallest timespec between the two, that is, the time that is pointing
     * towards the latest point in time.
     */
    public static Timespec max(Timespec lhs, Timespec rhs) {
        if (lhs.sec == Constants.minTime && rhs.sec != Constants.minTime) {
            return rhs;
        }
        if (rhs.sec == Constants.minTime && lhs.sec != Constants.minTime) {
            return lhs;
        }

        if (rhs.sec == Constants.minTime && lhs.sec == Constants.minTime) {
            throw new InvalidArgumentException("Both time ranges are null.");
        }

        if (lhs.sec > rhs.sec) {
            return lhs;
        }
        if (rhs.sec > lhs.sec) {
            return rhs;
        }

        // lhs.sec == rhs.sec
        if (lhs.nsec > rhs.nsec) {
            return lhs;
        }

        return rhs;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy