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 Werner Keil 061 * @version 1.0.2 062 * @since 1.0 063 */ 064public final class TemporalQuantity extends AbstractQuantity<Time> { 065 /** 066 * 067 */ 068 private static final long serialVersionUID = 6835738653744691425L; 069 070 private final TemporalUnit timeUnit; 071 private final Integer value; 072 private final TemporalAmount amount; 073 074 /** 075 * creates the {@link TemporalQuantity} using {@link TemporalUnit} and 076 * {@link Integer} 077 * 078 * @param timeUnit - time to be used 079 * @param value - 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 090 * {@link Integer} 091 * 092 * @param value - value to be used 093 * @param timeUnit - time to be used 094 */ 095 public static TemporalQuantity of(Integer number, TemporalUnit timeUnit) { 096 return new TemporalQuantity(Objects.requireNonNull(number), Objects.requireNonNull(timeUnit)); 097 } 098 099 /** 100 * Creates a {@link TemporalQuantity} based a {@link Quantity<Time>} converted 101 * to {@link Units#SECOND}. 102 * 103 * @param quantity - quantity to be used 104 * @return the {@link TemporalQuantity} converted be quantity in seconds. 105 */ 106 public static TemporalQuantity of(Quantity<Time> quantity) { 107 Quantity<Time> seconds = Objects.requireNonNull(quantity).to(SECOND); 108 return new TemporalQuantity(seconds.getValue().intValue(), ChronoUnit.SECONDS); 109 } 110 111 /** 112 * get to {@link TemporalAmount} 113 * 114 * @return the TemporalAmount 115 */ 116 public TemporalAmount getTemporalAmount() { 117 return amount; 118 } 119 120 /** 121 * get to {@link TemporalUnit} 122 * 123 * @return the TemporalUnit 124 */ 125 public TemporalUnit getTemporalUnit() { 126 return timeUnit; 127 } 128 129 /** 130 * get value expressed in {@link Integer} 131 * 132 * @return the value 133 */ 134 public Integer getValue() { 135 return value; 136 } 137 138 /** 139 * converts the {@link TemporalUnit} to {@link Unit} 140 * 141 * @return the {@link TemporalQuantity#getTemporalUnit()} converted to Unit 142 */ 143 public Unit<Time> toUnit() { 144 return toUnit(timeUnit); 145 } 146 147 /** 148 * Converts the {@link TemporalQuantity} to {@link Quantity<Time>} 149 * 150 * @return this class converted to Quantity 151 */ 152 public Quantity<Time> toQuantity() { 153 return Quantities.getQuantity(value, toUnit()); 154 } 155 156 public TemporalQuantity to(TemporalUnit timeUnit) { 157 Quantity<Time> time = toQuantity().to(toUnit(timeUnit)); 158 return new TemporalQuantity(time.getValue().intValue(), timeUnit); 159 } 160 161 private static Unit<Time> toUnit(TemporalUnit timeUnit) { 162 if (timeUnit instanceof ChronoUnit) { 163 ChronoUnit chronoUnit = (ChronoUnit) timeUnit; 164 switch (chronoUnit) { 165 case MICROS: 166 return TimeQuantities.MICROSECOND; 167 case MILLIS: 168 return TimeQuantities.MILLISECOND; 169 case NANOS: 170 return TimeQuantities.NANOSECOND; 171 case SECONDS: 172 return SECOND; 173 case MINUTES: 174 return MINUTE; 175 case HOURS: 176 return HOUR; 177 case DAYS: 178 return DAY; 179 default: 180 throw new IllegalArgumentException( 181 "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 305 /** 306 * @since 1.0.2 307 */ 308 @Override 309 public Quantity<Time> negate() { 310 return of(-value, getTemporalUnit()); 311 } 312}