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

net.snowflake.common.core.SFTime Maven / Gradle / Ivy

There is a newer version: 5.1.4
Show newest version
package net.snowflake.common.core;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;

/**
 * Represents times without date.
 *
 * 

Stores fractional seconds since midnight, with nanosecond precision. * *

Instances of this class are immutable. * * @author mkember */ public class SFTime extends SFInstant implements Comparable { // The java.sql.Time class is too cumbersome to use (it only supports // millisecond precision), so we store nanoseconds since midnight directly. private final long nanos; // Used for unit conversions. private static final long NS_IN_SECOND = 1000000000; private static final long NS_IN_MILLIS = 1000000; private static final long NS_IN_DAY = 86400 * NS_IN_SECOND; // min/max values public static final SFTime MIN_VALID_VALUE = SFTime.fromNanoseconds(0); public static final SFTime MAX_VALID_VALUE = SFTime.fromNanoseconds(NS_IN_DAY - 1); /** * Constructs an SFTime given nanoseconds since midnight. * * @param nanos nanoseconds * @return SFTime instance */ public static SFTime fromNanoseconds(long nanos) { return new SFTime(nanos); } /** * Constructs an SFTime from fractional seconds at a particular scale. * * @param value Fractional seconds since midnight. * @param scale The scale for interpreting {@code value}. A scale of 0 means seconds, and a scale * of 9 means nanoseconds. * @return A new SFTime object. */ public static SFTime fromFractionalSeconds(long value, int scale) { assert scale >= 0 && scale <= 9; int powerOfTen = SFInstant.POWERS_OF_TEN[9 - scale]; return new SFTime(value * powerOfTen); } /** * Constructs an SFTime from an SFTimestamp. * *

The resulting SFTime contains the time of day * * @param ts SFTimestamp * @return SFTime */ public static SFTime fromTimestamp(SFTimestamp ts) { long secondsSinceMidnight = ts.extract(Calendar.HOUR_OF_DAY) * 3600L + ts.extract(Calendar.MINUTE) * 60 + ts.extract(Calendar.SECOND); long nsSinceMidnight = secondsSinceMidnight * NS_IN_SECOND; long additionalNs = ts.getNanos(); return new SFTime(nsSinceMidnight + additionalNs); } private SFTime(long nanos) { assert nanos >= 0 && nanos < 86400 * NS_IN_SECOND; this.nanos = nanos; } /** * Returns nanoseconds since midnight. * * @return nanoseconds */ public long getNanoseconds() { return nanos; } /** * Returns nanoseconds since the last whole-number second. * * @return nanoseconds */ public int getNanosecondsWithinSecond() { return (int) (nanos % SFInstant.POWERS_OF_TEN[9]); } /** * Returns fractional seconds since midnight at the given scale, truncated from the internal * nanosecond representation. * * @param scale scale * @return fractional seconds * @see #fromFractionalSeconds(long, int) */ public long getFractionalSeconds(int scale) { assert scale >= 0 && scale <= 9; return nanos / SFInstant.POWERS_OF_TEN[9 - scale]; } /** * Create an SFTime by adding hours, minutes, seconds, or milliseconds. * *

Performs the addition modulo 24 hours so that the result stays in range. * * @param component The time component from the Calendar class. * @param increment Number of hours/minutes/etc. to add. * @return A new SFTime with the result of the addition. */ public SFTime addComponent(int component, long increment) { // Reduce increment mod 24h and convert to nanoseconds. switch (component) { case Calendar.HOUR_OF_DAY: increment = 3600 * NS_IN_SECOND * (increment % 24); break; case Calendar.MINUTE: increment = 60 * NS_IN_SECOND * (increment % (24 * 60)); break; case Calendar.SECOND: increment = NS_IN_SECOND * (increment % (24 * 60 * 60)); break; case Calendar.MILLISECOND: increment = NS_IN_MILLIS * (increment % (24 * 60 * 60 * 1000)); break; default: throw new IllegalArgumentException("invalid component " + component); } // Get the positive remainder. // TODO(mkember): Use Math.floorMod when GSCommon is on Java 1.8. long newNanos = ((nanos + increment) % NS_IN_DAY + NS_IN_DAY) % NS_IN_DAY; return new SFTime(newNanos); } /** * Create an SFTime with an adjusted scale. * * @param scale The desired scale. * @return Returns a new SFTime if changing the scale would result in a different (less precise) * time. Returns this object otherwise. */ public SFTime adjustScale(int scale) { long powerOfTen = SFInstant.POWERS_OF_TEN[9 - scale]; long extraDigits = nanos % powerOfTen; return extraDigits == 0 ? this : new SFTime(nanos - extraDigits); } /** * Constructs a string that can be safely passed to XP. * * @return a UTC string */ public String toUTCString() { long nanoPart = nanos % NS_IN_SECOND; String nanoStr = String.format(".%1$09d", nanoPart); DateFormat df = new SimpleDateFormat("HH:mm:ss" + nanoStr); df.setCalendar(CalendarCache.get(SFInstant.GMT)); return df.format(nanos / NS_IN_MILLIS); } /** * Constructs a string containing the number of seconds since midnight with the given number of * decimal places. * * @param decimalPlaces decimal places * @return seconds in a string */ public String toSecondsString(int decimalPlaces) { StringBuilder result = new StringBuilder(); result.append(nanos / NS_IN_SECOND); if (decimalPlaces > 0) { long nanoPart = nanos % NS_IN_SECOND; long powerOfTen = SFInstant.POWERS_OF_TEN[9 - decimalPlaces]; long afterDecimal = nanoPart / powerOfTen; result.append('.'); String fmt = "%0" + decimalPlaces + "d"; result.append(String.format(fmt, afterDecimal)); } return result.toString(); } /** * Compares with other SFTime * * @param other target SFTime * @return 1 if larger, 0 if equal otherwise -1 */ public int compareTo(SFTime other) { return Long.compare(nanos, other.nanos); } /** {@inheritDoc} */ @Override public int extract(int field, Integer optWeekStart, Integer optWoyPolicy) { return extract(field, SFInstant.GMT, nanos / NS_IN_MILLIS, optWeekStart, optWoyPolicy); } /** {@inheritDoc} */ @Override public int hashCode() { return (int) (nanos % Integer.MAX_VALUE); } /** {@inheritDoc} */ @Override public boolean equals(Object other) { return other instanceof SFTime && nanos == ((SFTime) other).nanos; } /** {@inheritDoc} */ @Override public String toString() { return "SFTime(nanos=" + nanos + ")"; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy