001/*
002 * Units of Measurement Reference Implementation
003 * Copyright (c) 2005-2018, Jean-Marie Dautelle, Werner Keil, Otavio Santana.
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.PowerOfIntConverter;
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 * @version 1.0
059 * @since 1.0
060 */
061public final class TimeQuantities {
062
063        private TimeQuantities() {
064        }
065
066        // Convenience constants outside the unit system (multiples are not held there)
067
068        public static final Unit<Time> MICROSECOND = new TransformedUnit<>("μs", SECOND, SECOND,
069                        PowerOfIntConverter.of(MetricPrefix.MICRO));
070
071        public static final TransformedUnit<Time> MILLISECOND = new TransformedUnit<>("ms", SECOND, SECOND,
072                        PowerOfIntConverter.of(MetricPrefix.MILLI));
073
074        public static final TransformedUnit<Time> NANOSECOND = new TransformedUnit<>("ns", SECOND, SECOND,
075                        PowerOfIntConverter.of(MetricPrefix.NANO));
076
077        /**
078         * Creates the {@link Quantity<Time>} based in the difference of the two
079         * {@link Temporal}
080         * 
081         * @param temporalA
082         *            - First parameter to range, inclusive
083         * @param temporalB
084         *            - second parameter to range, exclusive
085         * @return the Quantity difference based in {@link Units#DAY}.
086         * @throws java.time.temporal.UnsupportedTemporalTypeException
087         *             if some temporal doesn't support {@link ChronoUnit#DAYS}
088         */
089        public static Quantity<Time> getQuantity(Temporal temporalA, Temporal temporalB) {
090                long days = ChronoUnit.DAYS.between(temporalA, temporalB);
091                return Quantities.getQuantity(days, DAY);
092        }
093
094        /**
095         * Creates the {@link Quantity<Time>} based in the difference of the two
096         * {@link LocalTime}
097         * 
098         * @param localTimeA
099         *            - First parameter to range, inclusive
100         * @param localTimeB
101         *            - second parameter to range, exclusive
102         * @return the Quantity difference based in {@link Units#HOUR}.
103         * @throws java.time.temporal.UnsupportedTemporalTypeException
104         *             if some temporal doesn't support {@link ChronoUnit#DAYS}
105         */
106        public static Quantity<Time> getQuantity(LocalTime localTimeA, LocalTime localTimeB) {
107                long hours = ChronoUnit.HOURS.between(localTimeA, localTimeB);
108                return Quantities.getQuantity(hours, HOUR);
109        }
110
111        /**
112         * Creates the {@link Quantity<Time>} based in the {@link Temporal} with
113         * {@link TemporalAdjuster}
114         * 
115         * @param temporalA
116         *            - temporal
117         * @param supplier
118         *            the adjust @see {@link TemporalAdjuster}
119         * @return The Quantity based in Temporal with TemporalAdjuster in
120         *         {@link Units#DAY}.
121         * @throws java.time.temporal.UnsupportedTemporalTypeException
122         *             if some temporal doesn't support {@link ChronoUnit#DAYS}
123         */
124        public static Quantity<Time> getQuantity(Temporal temporalA, Supplier<TemporalAdjuster> supplier) {
125                Temporal temporalB = temporalA.with(supplier.get());
126                return getQuantity(temporalA, temporalB);
127        }
128
129        /**
130         * Creates the {@link Quantity<Time>} based in the {@link Temporal} with
131         * {@link Supplier<TemporalAdjuster>}
132         * 
133         * @param localTimeA
134         * @see {@link LocalTime}
135         * @param supplier
136         *            he adjust @see {@link TemporalAdjuster}
137         * @return The Quantity based in Temporal with TemporalAdjuster in
138         *         {@link Units#DAY}.
139         * @throws java.time.temporal.UnsupportedTemporalTypeException
140         *             if some temporal doesn't support {@link ChronoUnit#DAYS}
141         */
142        public static Quantity<Time> getQuantity(LocalTime localTimeA, Supplier<TemporalAdjuster> supplier) {
143                LocalTime localTimeB = localTimeA.with(supplier.get());
144                return getQuantity(localTimeA, localTimeB);
145        }
146
147        /**
148         * creates the {@link TimeUnitQuantity} using {@link TimeUnit} and
149         * {@link Integer}
150         * 
151         * @param value
152         *            - value to be used
153         * @param timeUnit
154         *            - time to be used
155         */
156        public static TimeUnitQuantity getQuantity(Integer number, TimeUnit timeUnit) {
157                return new TimeUnitQuantity(Objects.requireNonNull(timeUnit), Objects.requireNonNull(number));
158        }
159
160        /**
161         * creates the {@link TemporalQuantity} using {@link TemporalUnit} and
162         * {@link Integer}
163         * 
164         * @param value
165         *            - value to be used
166         * @param timeUnit
167         *            - time to be used
168         */
169        public static TemporalQuantity getQuantity(Integer number, TemporalUnit temporalUnit) {
170                return new TemporalQuantity(Objects.requireNonNull(number), Objects.requireNonNull(temporalUnit));
171        }
172
173        /**
174         * Creates a {@link TimeUnitQuantity} based a {@link Quantity<Time>} converted
175         * to {@link Units#SECOND}.
176         * 
177         * @param quantity
178         *            - quantity to be used
179         * @return the {@link TimeUnitQuantity} converted be quantity in seconds.
180         */
181        public static TimeUnitQuantity toTimeUnitSeconds(Quantity<Time> quantity) {
182                Quantity<Time> seconds = Objects.requireNonNull(quantity).to(SECOND);
183                return new TimeUnitQuantity(TimeUnit.SECONDS, seconds.getValue().intValue());
184        }
185
186        /**
187         * Creates a {@link TemporalQuantity} based a {@link Quantity<Time>} converted
188         * to {@link Units#SECOND}.
189         * 
190         * @param quantity
191         *            - quantity to be used
192         * @return the {@link TemporalQuantity} converted be quantity in seconds.
193         */
194        public static TemporalQuantity toTemporalSeconds(Quantity<Time> quantity) {
195                Quantity<Time> seconds = Objects.requireNonNull(quantity).to(SECOND);
196                return TemporalQuantity.of(seconds);
197        }
198}