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.MINUTE; 035import static tech.units.indriya.unit.Units.SECOND; 036 037import java.math.BigDecimal; 038import java.time.Duration; 039import java.time.temporal.ChronoUnit; 040import java.time.temporal.TemporalAmount; 041import java.time.temporal.TemporalUnit; 042import java.util.Objects; 043 044import javax.measure.IncommensurableException; 045import javax.measure.Quantity; 046import javax.measure.UnconvertibleException; 047import javax.measure.Unit; 048import javax.measure.UnitConverter; 049import javax.measure.quantity.Frequency; 050import javax.measure.quantity.Time; 051 052import tech.units.indriya.AbstractQuantity; 053import tech.units.indriya.ComparableQuantity; 054import tech.units.indriya.quantity.Quantities; 055import tech.units.indriya.unit.Units; 056 057/** 058 * Class that represents {@link TemporalUnit} in Unit-API 059 * 060 * @author keilw 061 * @since 1.0 062 */ 063public final class TemporalQuantity extends AbstractQuantity<Time> { 064 /** 065 * 066 */ 067 private static final long serialVersionUID = 6835738653744691425L; 068 069 private final TemporalUnit timeUnit; 070 private final Integer value; 071 private final TemporalAmount amount; 072 073 /** 074 * creates the {@link TemporalQuantity} using {@link TemporalUnit} and {@link Integer} 075 * 076 * @param timeUnit 077 * - time to be used 078 * @param value 079 * - value to be used 080 */ 081 TemporalQuantity(Integer value, TemporalUnit timeUnit) { 082 super(toUnit(timeUnit)); 083 this.timeUnit = timeUnit; 084 this.amount = Duration.of(value, timeUnit); 085 this.value = value; 086 } 087 088 /** 089 * creates the {@link TemporalQuantity} using {@link TemporalUnit} and {@link Integer} 090 * 091 * @param value 092 * - value to be used 093 * @param timeUnit 094 * - time to be used 095 */ 096 public static TemporalQuantity of(Integer number, TemporalUnit timeUnit) { 097 return new TemporalQuantity(Objects.requireNonNull(number), Objects.requireNonNull(timeUnit)); 098 } 099 100 /** 101 * Creates a {@link TemporalQuantity} based a {@link Quantity<Time>} converted to {@link Units#SECOND}. 102 * 103 * @param quantity 104 * - quantity to be used 105 * @return the {@link TemporalQuantity} converted be quantity in seconds. 106 */ 107 public static TemporalQuantity of(Quantity<Time> quantity) { 108 Quantity<Time> seconds = Objects.requireNonNull(quantity).to(SECOND); 109 return new TemporalQuantity(seconds.getValue().intValue(), ChronoUnit.SECONDS); 110 } 111 112 /** 113 * get to {@link TemporalAmount} 114 * 115 * @return the TemporalAmount 116 */ 117 public TemporalAmount getTemporalAmount() { 118 return amount; 119 } 120 121 /** 122 * get to {@link TemporalUnit} 123 * 124 * @return the TemporalUnit 125 */ 126 public TemporalUnit getTemporalUnit() { 127 return timeUnit; 128 } 129 130 /** 131 * get value expressed in {@link Integer} 132 * 133 * @return the value 134 */ 135 public Integer getValue() { 136 return value; 137 } 138 139 /** 140 * converts the {@link TemporalUnit} to {@link Unit} 141 * 142 * @return the {@link TemporalQuantity#getTemporalUnit()} converted to Unit 143 */ 144 public Unit<Time> toUnit() { 145 return toUnit(timeUnit); 146 } 147 148 /** 149 * Converts the {@link TemporalQuantity} to {@link Quantity<Time>} 150 * 151 * @return this class converted to Quantity 152 */ 153 public Quantity<Time> toQuantity() { 154 return Quantities.getQuantity(value, toUnit()); 155 } 156 157 public TemporalQuantity to(TemporalUnit timeUnit) { 158 Quantity<Time> time = toQuantity().to(toUnit(timeUnit)); 159 return new TemporalQuantity(time.getValue().intValue(), timeUnit); 160 } 161 162 private static Unit<Time> toUnit(TemporalUnit timeUnit) { 163 if (timeUnit instanceof ChronoUnit) { 164 ChronoUnit chronoUnit = (ChronoUnit) timeUnit; 165 switch (chronoUnit) { 166 case MICROS: 167 return TimeQuantities.MICROSECOND; 168 case MILLIS: 169 return TimeQuantities.MILLISECOND; 170 case NANOS: 171 return TimeQuantities.NANOSECOND; 172 case SECONDS: 173 return SECOND; 174 case MINUTES: 175 return MINUTE; 176 case HOURS: 177 return HOUR; 178 case DAYS: 179 return DAY; 180 default: 181 throw new IllegalArgumentException("TemporalQuantity only supports DAYS, HOURS, MICROS, MILLIS, MINUTES, NANOS, SECONDS "); 182 } 183 } else { 184 throw new IllegalArgumentException("TemporalQuantity only supports temporal units of type ChronoUnit"); 185 186 } 187 } 188 189 @Override 190 public int hashCode() { 191 return Objects.hash(timeUnit, value); 192 } 193 194 @Override 195 public boolean equals(Object obj) { 196 if (this == obj) { 197 return true; 198 } 199 if (TemporalQuantity.class.isInstance(obj)) { 200 TemporalQuantity other = TemporalQuantity.class.cast(obj); 201 return Objects.equals(timeUnit, other.timeUnit) && Objects.equals(value, other.value); 202 } 203 if (obj instanceof Quantity<?>) { 204 Quantity<?> that = (Quantity<?>) obj; 205 return Objects.equals(getUnit(), that.getUnit()) && Equalizer.hasEquality(value, that.getValue()); 206 } 207 return super.equals(obj); 208 } 209 210 @Override 211 public String toString() { 212 return "Temporal unit:" + timeUnit + " value: " + value; 213 } 214 215 @Override 216 public ComparableQuantity<Time> add(Quantity<Time> that) { 217 if (getUnit().equals(that.getUnit())) { 218 return TimeQuantities.getQuantity(value + that.getValue().intValue(), timeUnit); 219 } 220 Quantity<Time> converted = that.to(getUnit()); 221 return TimeQuantities.getQuantity(value + converted.getValue().intValue(), timeUnit); 222 } 223 224 @Override 225 public ComparableQuantity<Time> subtract(Quantity<Time> that) { 226 if (getUnit().equals(that.getUnit())) { 227 return TimeQuantities.getQuantity(value - that.getValue().intValue(), timeUnit); 228 } 229 Quantity<Time> converted = that.to(getUnit()); 230 return TimeQuantities.getQuantity(value - converted.getValue().intValue(), timeUnit); 231 } 232 233 @Override 234 public ComparableQuantity<?> divide(Quantity<?> that) { 235 if (getUnit().equals(that.getUnit())) { 236 return TimeQuantities.getQuantity(value / that.getValue().intValue(), timeUnit); 237 } 238 Unit<?> divUnit = getUnit().divide(that.getUnit()); 239 UnitConverter conv; 240 try { 241 conv = getUnit().getConverterToAny(divUnit); 242 return TimeQuantities.getQuantity(value / conv.convert(that.getValue()).intValue(), timeUnit); 243 } catch (UnconvertibleException e) { 244 // TODO Auto-generated catch block 245 e.printStackTrace(); 246 return TimeQuantities.getQuantity(value / that.getValue().intValue(), timeUnit); 247 } catch (IncommensurableException e) { 248 // TODO Auto-generated catch block 249 e.printStackTrace(); 250 return TimeQuantities.getQuantity(value / that.getValue().intValue(), timeUnit); 251 } 252 } 253 254 @Override 255 public ComparableQuantity<Time> divide(Number that) { 256 return TimeQuantities.getQuantity(value / that.intValue(), timeUnit); 257 } 258 259 @Override 260 public ComparableQuantity<?> multiply(Quantity<?> multiplier) { 261 if (getUnit().equals(multiplier.getUnit())) { 262 return TimeQuantities.getQuantity(value * multiplier.getValue().intValue(), timeUnit); 263 } 264 Unit<?> mulUnit = getUnit().multiply(multiplier.getUnit()); 265 UnitConverter conv; 266 try { 267 conv = getUnit().getConverterToAny(mulUnit); 268 return TimeQuantities.getQuantity(value * conv.convert(multiplier.getValue()).intValue(), timeUnit); 269 } catch (UnconvertibleException e) { 270 // TODO Auto-generated catch block 271 e.printStackTrace(); 272 return TimeQuantities.getQuantity(value * multiplier.getValue().intValue(), timeUnit); 273 } catch (IncommensurableException e) { 274 // TODO Auto-generated catch block 275 e.printStackTrace(); 276 return TimeQuantities.getQuantity(value * multiplier.getValue().intValue(), timeUnit); 277 } 278 } 279 280 @Override 281 public ComparableQuantity<Time> multiply(Number multiplier) { 282 return TimeQuantities.getQuantity(value * multiplier.intValue(), timeUnit); 283 } 284 285 @Override 286 public ComparableQuantity<Frequency> inverse() { 287 return Quantities.getQuantity(1d / value.doubleValue(), toUnit(timeUnit).inverse()).asType(Frequency.class); 288 } 289 290 @Override 291 public boolean isBig() { 292 return true; // Duration backed by BigDecimal/BigInteger 293 } 294 295 @Override 296 public BigDecimal decimalValue(Unit<Time> unit) throws ArithmeticException { 297 return BigDecimal.valueOf(value.doubleValue()); 298 } 299 300 @Override 301 public double doubleValue(Unit<Time> unit) throws ArithmeticException { 302 return value.doubleValue(); 303 } 304}