001/*
002 * Units of Measurement Reference Implementation
003 * Copyright (c) 2005-2020, Units of Measurement project.
004 *
005 * All rights reserved.
006 *
007 * Redistribution and use in source and binary forms, with or without modification,
008 * are permitted provided that the following conditions are met:
009 *
010 * 1. Redistributions of source code must retain the above copyright notice,
011 *    this list of conditions and the following disclaimer.
012 *
013 * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions
014 *    and the following disclaimer in the documentation and/or other materials provided with the distribution.
015 *
016 * 3. Neither the name of JSR-385, Indriya nor the names of their contributors may be used to endorse or promote products
017 *    derived from this software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
021 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
022 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
023 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
026 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030package tech.units.indriya.quantity.time;
031
032import static tech.units.indriya.unit.Units.DAY;
033import static tech.units.indriya.unit.Units.HOUR;
034import static tech.units.indriya.unit.Units.SECOND;
035
036import java.time.LocalTime;
037import java.time.temporal.ChronoUnit;
038import java.time.temporal.Temporal;
039import java.time.temporal.TemporalAdjuster;
040import java.time.temporal.TemporalUnit;
041import java.util.Objects;
042import java.util.concurrent.TimeUnit;
043import java.util.function.Supplier;
044
045import javax.measure.MetricPrefix;
046import javax.measure.Quantity;
047import javax.measure.Unit;
048import javax.measure.quantity.Time;
049
050import tech.units.indriya.function.MultiplyConverter;
051import tech.units.indriya.quantity.Quantities;
052import tech.units.indriya.unit.TransformedUnit;
053import tech.units.indriya.unit.Units;
054
055/**
056 * @author Otavio
057 * @author Werner
058 * @author Andi Huber
059 * @version 1.1
060 * @since 1.0
061 */
062public final class TimeQuantities {
063
064        private TimeQuantities() {
065        }
066
067        // Convenience constants outside the unit system (multiples are not held there)
068
069        public static final Unit<Time> MICROSECOND = new TransformedUnit<>("μs", SECOND, SECOND,
070                        MultiplyConverter.ofPrefix(MetricPrefix.MICRO));
071
072        public static final TransformedUnit<Time> MILLISECOND = new TransformedUnit<>("ms", SECOND, SECOND,
073                MultiplyConverter.ofPrefix(MetricPrefix.MILLI));
074
075        public static final TransformedUnit<Time> NANOSECOND = new TransformedUnit<>("ns", SECOND, SECOND,
076                MultiplyConverter.ofPrefix(MetricPrefix.NANO));
077
078        /**
079         * Creates the {@link Quantity<Time>} based in the difference of the two
080         * {@link Temporal}
081         * 
082         * @param temporalA
083         *            - First parameter to range, inclusive
084         * @param temporalB
085         *            - second parameter to range, exclusive
086         * @return the Quantity difference based in {@link Units#DAY}.
087         * @throws java.time.temporal.UnsupportedTemporalTypeException
088         *             if some temporal doesn't support {@link ChronoUnit#DAYS}
089         */
090        public static Quantity<Time> getQuantity(Temporal temporalA, Temporal temporalB) {
091                long days = ChronoUnit.DAYS.between(temporalA, temporalB);
092                return Quantities.getQuantity(days, DAY);
093        }
094
095        /**
096         * Creates the {@link Quantity<Time>} based in the difference of the two
097         * {@link LocalTime}
098         * 
099         * @param localTimeA
100         *            - First parameter to range, inclusive
101         * @param localTimeB
102         *            - second parameter to range, exclusive
103         * @return the Quantity difference based in {@link Units#HOUR}.
104         * @throws java.time.temporal.UnsupportedTemporalTypeException
105         *             if some temporal doesn't support {@link ChronoUnit#DAYS}
106         */
107        public static Quantity<Time> getQuantity(LocalTime localTimeA, LocalTime localTimeB) {
108                long hours = ChronoUnit.HOURS.between(localTimeA, localTimeB);
109                return Quantities.getQuantity(hours, HOUR);
110        }
111
112        /**
113         * Creates the {@link Quantity<Time>} based in the {@link Temporal} with
114         * {@link TemporalAdjuster}
115         * 
116         * @param temporalA
117         *            - temporal
118         * @param supplier
119         *            the adjust @see {@link TemporalAdjuster}
120         * @return The Quantity based in Temporal with TemporalAdjuster in
121         *         {@link Units#DAY}.
122         * @throws java.time.temporal.UnsupportedTemporalTypeException
123         *             if some temporal doesn't support {@link ChronoUnit#DAYS}
124         */
125        public static Quantity<Time> getQuantity(Temporal temporalA, Supplier<TemporalAdjuster> supplier) {
126                Temporal temporalB = temporalA.with(supplier.get());
127                return getQuantity(temporalA, temporalB);
128        }
129
130        /**
131         * Creates the {@link Quantity<Time>} based in the {@link Temporal} with
132         * {@link Supplier<TemporalAdjuster>}
133         * 
134         * @param localTimeA
135         * @see {@link LocalTime}
136         * @param supplier
137         *            he adjust @see {@link TemporalAdjuster}
138         * @return The Quantity based in Temporal with TemporalAdjuster in
139         *         {@link Units#DAY}.
140         * @throws java.time.temporal.UnsupportedTemporalTypeException
141         *             if some temporal doesn't support {@link ChronoUnit#DAYS}
142         */
143        public static Quantity<Time> getQuantity(LocalTime localTimeA, Supplier<TemporalAdjuster> supplier) {
144                LocalTime localTimeB = localTimeA.with(supplier.get());
145                return getQuantity(localTimeA, localTimeB);
146        }
147
148        /**
149         * creates the {@link TimeUnitQuantity} using {@link TimeUnit} and
150         * {@link Integer}
151         * 
152         * @param value
153         *            - value to be used
154         * @param timeUnit
155         *            - time to be used
156         */
157        public static TimeUnitQuantity getQuantity(Long number, TimeUnit timeUnit) {
158                return new TimeUnitQuantity(Objects.requireNonNull(timeUnit), Objects.requireNonNull(number));
159        }
160
161        /**
162         * creates the {@link TemporalQuantity} using {@link TemporalUnit} and
163         * {@link Long}
164         * 
165         * @param value
166         *            - value to be used
167         * @param timeUnit
168         *            - time to be used
169         */
170        public static TemporalQuantity getQuantity(Long number, TemporalUnit temporalUnit) {
171                return new TemporalQuantity(Objects.requireNonNull(number), Objects.requireNonNull(temporalUnit));
172        }
173
174        /**
175         * Creates a {@link TimeUnitQuantity} based a {@link Quantity<Time>} converted
176         * to {@link Units#SECOND}.
177         * 
178         * @param quantity
179         *            - quantity to be used
180         * @return the {@link TimeUnitQuantity} converted be quantity in seconds.
181         */
182        public static TimeUnitQuantity toTimeUnitSeconds(Quantity<Time> quantity) {
183                Quantity<Time> seconds = Objects.requireNonNull(quantity).to(SECOND);
184                return new TimeUnitQuantity(TimeUnit.SECONDS, seconds.getValue().longValue());
185        }
186
187        /**
188         * Creates a {@link TemporalQuantity} based a {@link Quantity<Time>} converted
189         * to {@link Units#SECOND}.
190         * 
191         * @param quantity
192         *            - quantity to be used
193         * @return the {@link TemporalQuantity} converted be quantity in seconds.
194         */
195        public static TemporalQuantity toTemporalSeconds(Quantity<Time> quantity) {
196                Quantity<Time> seconds = Objects.requireNonNull(quantity).to(SECOND);
197                return TemporalQuantity.of(seconds);
198        }
199}