001/* 002 * Units of Measurement Implementation for Java SE 003 * Copyright (c) 2005-2017, Jean-Marie Dautelle, Werner Keil, V2COM. 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-363 nor the names of its 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 tec.uom.se.quantity.time; 031 032import static tec.uom.se.unit.Units.DAY; 033import static tec.uom.se.unit.Units.HOUR; 034import static tec.uom.se.unit.Units.MINUTE; 035import static tec.uom.se.unit.Units.SECOND; 036 037import java.util.Objects; 038import java.math.BigDecimal; 039import java.math.MathContext; 040import java.time.Duration; 041import java.time.temporal.ChronoUnit; 042import java.time.temporal.TemporalAmount; 043import java.time.temporal.TemporalUnit; 044 045import javax.measure.IncommensurableException; 046import javax.measure.Quantity; 047import javax.measure.UnconvertibleException; 048import javax.measure.Unit; 049import javax.measure.UnitConverter; 050import javax.measure.quantity.Time; 051 052import tec.uom.se.AbstractQuantity; 053import tec.uom.se.ComparableQuantity; 054import tec.uom.se.quantity.Quantities; 055 056/** 057 * Class that represents {@link TemporalUnit} in Unit-API 058 * 059 * @author keilw 060 * @since 1.0 061 */ 062public final class TemporalQuantity extends AbstractQuantity<Time> { 063 /** 064 * 065 */ 066 private static final long serialVersionUID = 6835738653744691425L; 067 068 private final TemporalUnit timeUnit; 069 private final Integer value; 070 private final TemporalAmount amount; 071 072 /** 073 * creates the {@link TemporalQuantity} using {@link TemporalUnit} and {@link Integer} 074 * 075 * @param timeUnit 076 * - time to be used 077 * @param value 078 * - value to be used 079 */ 080 TemporalQuantity(Integer value, TemporalUnit timeUnit) { 081 super(toUnit(timeUnit)); 082 this.timeUnit = timeUnit; 083 this.amount = Duration.of(value, timeUnit); 084 this.value = value; 085 } 086 087 /** 088 * creates the {@link TemporalQuantity} using {@link TemporalUnit} and {@link Integer} 089 * 090 * @param value 091 * - value to be used 092 * @param timeUnit 093 * - 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 to {@link Units#SECOND}. 101 * 102 * @param quantity 103 * - 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("TemporalQuantity only supports DAYS, HOURS, MICROS, MILLIS, MINUTES, NANOS, SECONDS "); 181 } 182 } else { 183 throw new IllegalArgumentException("TemporalQuantity only supports temporal units of type ChronoUnit"); 184 185 } 186 } 187 188 @Override 189 public int hashCode() { 190 return Objects.hash(timeUnit, value); 191 } 192 193 @Override 194 public boolean equals(Object obj) { 195 if (this == obj) { 196 return true; 197 } 198 if (TemporalQuantity.class.isInstance(obj)) { 199 TemporalQuantity other = TemporalQuantity.class.cast(obj); 200 return Objects.equals(timeUnit, other.timeUnit) && Objects.equals(value, other.value); 201 } 202 return super.equals(obj); 203 } 204 205 @Override 206 public String toString() { 207 return "Temporal unit:" + timeUnit + " value: " + value; 208 } 209 210 @Override 211 public ComparableQuantity<Time> add(Quantity<Time> that) { 212 if (getUnit().equals(that.getUnit())) { 213 return TimeQuantities.getQuantity(value + that.getValue().intValue(), timeUnit); 214 } 215 Quantity<Time> converted = that.to(getUnit()); 216 return TimeQuantities.getQuantity(value + converted.getValue().intValue(), timeUnit); 217 } 218 219 @Override 220 public ComparableQuantity<Time> subtract(Quantity<Time> that) { 221 if (getUnit().equals(that.getUnit())) { 222 return TimeQuantities.getQuantity(value - that.getValue().intValue(), timeUnit); 223 } 224 Quantity<Time> converted = that.to(getUnit()); 225 return TimeQuantities.getQuantity(value - converted.getValue().intValue(), timeUnit); 226 } 227 228 @Override 229 public ComparableQuantity<?> divide(Quantity<?> that) { 230 if (getUnit().equals(that.getUnit())) { 231 return TimeQuantities.getQuantity(value / that.getValue().intValue(), timeUnit); 232 } 233 Unit<?> divUnit = getUnit().divide(that.getUnit()); 234 UnitConverter conv; 235 try { 236 conv = getUnit().getConverterToAny(divUnit); 237 return TimeQuantities.getQuantity(value / conv.convert(that.getValue()).intValue(), timeUnit); 238 } catch (UnconvertibleException e) { 239 // TODO Auto-generated catch block 240 e.printStackTrace(); 241 return TimeQuantities.getQuantity(value / that.getValue().intValue(), timeUnit); 242 } catch (IncommensurableException e) { 243 // TODO Auto-generated catch block 244 e.printStackTrace(); 245 return TimeQuantities.getQuantity(value / that.getValue().intValue(), timeUnit); 246 } 247 } 248 249 @Override 250 public ComparableQuantity<Time> divide(Number that) { 251 return TimeQuantities.getQuantity(value / that.intValue(), timeUnit); 252 } 253 254 @Override 255 public ComparableQuantity<?> multiply(Quantity<?> multiplier) { 256 if (getUnit().equals(multiplier.getUnit())) { 257 return TimeQuantities.getQuantity(value * multiplier.getValue().intValue(), timeUnit); 258 } 259 Unit<?> mulUnit = getUnit().multiply(multiplier.getUnit()); 260 UnitConverter conv; 261 try { 262 conv = getUnit().getConverterToAny(mulUnit); 263 return TimeQuantities.getQuantity(value * conv.convert(multiplier.getValue()).intValue(), timeUnit); 264 } catch (UnconvertibleException e) { 265 // TODO Auto-generated catch block 266 e.printStackTrace(); 267 return TimeQuantities.getQuantity(value * multiplier.getValue().intValue(), timeUnit); 268 } catch (IncommensurableException e) { 269 // TODO Auto-generated catch block 270 e.printStackTrace(); 271 return TimeQuantities.getQuantity(value * multiplier.getValue().intValue(), timeUnit); 272 } 273 } 274 275 @Override 276 public ComparableQuantity<Time> multiply(Number multiplier) { 277 return TimeQuantities.getQuantity(value * multiplier.intValue(), timeUnit); 278 } 279 280 @Override 281 public ComparableQuantity<?> inverse() { 282 return TimeQuantities.getQuantity(1 / value, timeUnit); 283 } 284 285 @Override 286 public boolean isBig() { 287 return true; // Duration backed by BigDecimal/BigInteger 288 } 289 290 @Override 291 public BigDecimal decimalValue(Unit<Time> unit, MathContext ctx) throws ArithmeticException { 292 return BigDecimal.valueOf(value.doubleValue()); 293 } 294 295 @Override 296 public double doubleValue(Unit<Time> unit) throws ArithmeticException { 297 return value.doubleValue(); 298 } 299}