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

io.prestosql.operator.scalar.timetz.TimeWithTimeZoneOperators Maven / Gradle / Ivy

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.prestosql.operator.scalar.timetz;

import io.prestosql.operator.scalar.time.TimeOperators;
import io.prestosql.spi.function.LiteralParameters;
import io.prestosql.spi.function.ScalarOperator;
import io.prestosql.spi.function.SqlType;
import io.prestosql.spi.type.LongTimeWithTimeZone;
import io.prestosql.spi.type.StandardTypes;
import io.prestosql.type.Constraint;

import static io.prestosql.spi.function.OperatorType.ADD;
import static io.prestosql.spi.function.OperatorType.SUBTRACT;
import static io.prestosql.spi.type.DateTimeEncoding.packTimeWithTimeZone;
import static io.prestosql.spi.type.DateTimeEncoding.unpackOffsetMinutes;
import static io.prestosql.spi.type.DateTimeEncoding.unpackTimeNanos;
import static io.prestosql.type.DateTimes.NANOSECONDS_PER_DAY;
import static io.prestosql.type.DateTimes.NANOSECONDS_PER_MINUTE;
import static io.prestosql.type.DateTimes.PICOSECONDS_PER_DAY;
import static io.prestosql.type.DateTimes.PICOSECONDS_PER_MILLISECOND;
import static io.prestosql.type.DateTimes.PICOSECONDS_PER_MINUTE;
import static io.prestosql.type.DateTimes.PICOSECONDS_PER_NANOSECOND;
import static io.prestosql.type.DateTimes.rescaleWithRounding;
import static java.lang.Math.floorMod;

@SuppressWarnings("UtilityClassWithoutPrivateConstructor")
public final class TimeWithTimeZoneOperators
{
    private TimeWithTimeZoneOperators() {}

    /**
     * Normalize to offset +00:00. The calculation is done modulo 24h
     *
     * @return the time in nanoseconds
     */
    static long normalize(long packedTime)
    {
        long nanos = unpackTimeNanos(packedTime);
        int offsetMinutes = unpackOffsetMinutes(packedTime);
        return floorMod(nanos - offsetMinutes * NANOSECONDS_PER_MINUTE, NANOSECONDS_PER_DAY);
    }

    /**
     * Normalize to offset +00:00. The calculation is done modulo 24h
     *
     * @return the time in picoseconds
     */
    static long normalize(LongTimeWithTimeZone time)
    {
        return floorMod(time.getPicoseconds() - time.getOffsetMinutes() * PICOSECONDS_PER_MINUTE, PICOSECONDS_PER_DAY);
    }

    @ScalarOperator(ADD)
    public static final class TimePlusIntervalDayToSecond
    {
        @LiteralParameters({"p", "u"})
        @SqlType("time(u) with time zone")
        @Constraint(variable = "u", expression = "max(3, p)") // Interval is currently p = 3, so the minimum result precision is 3.
        public static long add(
                @SqlType("time(p) with time zone") long packedTime,
                @SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND) long interval)
        {
            long picos = unpackTimeNanos(packedTime) * PICOSECONDS_PER_NANOSECOND;
            long nanos = TimeOperators.add(picos, interval * PICOSECONDS_PER_MILLISECOND) / PICOSECONDS_PER_NANOSECOND;

            return packTimeWithTimeZone(nanos, unpackOffsetMinutes(packedTime));
        }

        @LiteralParameters({"p", "u"})
        @SqlType("time(u) with time zone")
        @Constraint(variable = "u", expression = "max(3, p)") // Interval is currently p = 3, so the minimum result precision is 3.
        public static LongTimeWithTimeZone add(
                @SqlType("time(p) with time zone") LongTimeWithTimeZone time,
                @SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND) long interval)
        {
            long picos = TimeOperators.add(time.getPicoseconds(), interval * PICOSECONDS_PER_MILLISECOND);
            return new LongTimeWithTimeZone(picos, time.getOffsetMinutes());
        }
    }

    @ScalarOperator(ADD)
    public static final class IntervalDayToSecondPlusTime
    {
        @LiteralParameters({"p", "u"})
        @SqlType("time(u) with time zone")
        @Constraint(variable = "u", expression = "max(3, p)") // Interval is currently p = 3, so the minimum result precision is 3.
        public static long add(
                @SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND) long interval,
                @SqlType("time(p) with time zone") long time)
        {
            return TimePlusIntervalDayToSecond.add(time, interval);
        }

        @LiteralParameters({"p", "u"})
        @SqlType("time(u) with time zone")
        @Constraint(variable = "u", expression = "max(3, p)") // Interval is currently p = 3, so the minimum result precision is 3.
        public static LongTimeWithTimeZone add(
                @SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND) long interval,
                @SqlType("time(p) with time zone") LongTimeWithTimeZone time)
        {
            return TimePlusIntervalDayToSecond.add(time, interval);
        }
    }

    @ScalarOperator(SUBTRACT)
    public static final class TimeMinusIntervalDayToSecond
    {
        @LiteralParameters({"p", "u"})
        @SqlType("time(u) with time zone")
        @Constraint(variable = "u", expression = "max(3, p)") // Interval is currently p = 3, so the minimum result precision is 3.
        public static long subtract(
                @SqlType("time(p) with time zone") long packedTime,
                @SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND) long interval)
        {
            return TimePlusIntervalDayToSecond.add(packedTime, -interval);
        }

        @LiteralParameters({"p", "u"})
        @SqlType("time(u) with time zone")
        @Constraint(variable = "u", expression = "max(3, p)") // Interval is currently p = 3, so the minimum result precision is 3.
        public static LongTimeWithTimeZone subtract(
                @SqlType("time(p) with time zone") LongTimeWithTimeZone time,
                @SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND) long interval)
        {
            return TimePlusIntervalDayToSecond.add(time, -interval);
        }
    }

    @ScalarOperator(SUBTRACT)
    public static final class TimeMinusTime
    {
        @LiteralParameters("p")
        @SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND)
        public static long subtract(
                @SqlType("time(p) with time zone") long left,
                @SqlType("time(p) with time zone") long right)
        {
            long nanos = normalize(left) - normalize(right);
            return rescaleWithRounding(nanos, 9, 3);
        }

        @LiteralParameters("p")
        @SqlType(StandardTypes.INTERVAL_DAY_TO_SECOND)
        public static long subtract(
                @SqlType("time(p) with time zone") LongTimeWithTimeZone left,
                @SqlType("time(p) with time zone") LongTimeWithTimeZone right)
        {
            long picos = normalize(left) - normalize(right);
            return rescaleWithRounding(picos, 12, 3);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy