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.MINUTE; 035import static tech.units.indriya.unit.Units.SECOND; 036 037import java.util.Objects; 038import java.util.concurrent.TimeUnit; 039import java.util.function.BinaryOperator; 040 041import javax.measure.Quantity; 042import javax.measure.Unit; 043import javax.measure.UnitConverter; 044import javax.measure.quantity.Frequency; 045import javax.measure.quantity.Time; 046 047import tech.units.indriya.AbstractQuantity; 048import tech.units.indriya.ComparableQuantity; 049import tech.units.indriya.function.Calculus; 050import tech.units.indriya.internal.function.calc.Calculator; 051import tech.units.indriya.quantity.Quantities; 052 053/** 054 * Class that represents {@link TimeUnit} in Unit-API 055 * 056 * @author otaviojava 057 * @author keilw 058 * @author Andi Huber 059 * @version 1.0.4 060 * @since 1.0 061 */ 062public final class TimeUnitQuantity extends AbstractQuantity<Time> { 063 064 /** 065 * 066 */ 067 private static final long serialVersionUID = -5840251813363744230L; 068 069 private final TimeUnit timeUnit; 070 071 private final Number value; 072 073 /** 074 * creates the {@link TimeUnitQuantity} using {@link TimeUnit} and {@link Long} 075 * 076 * @param timeUnit 077 * - time to be used 078 * @param value 079 * - value to be used 080 */ 081 TimeUnitQuantity(TimeUnit timeUnit, Number value) { 082 super(toUnit(timeUnit)); 083 this.timeUnit = timeUnit; 084 this.value = value; 085 } 086 087 /** 088 * creates the {@link TimeUnitQuantity} using {@link TimeUnit} and {@link Long} 089 * 090 * @param timeUnit 091 * - time to be used 092 * @param value 093 * - value to be used 094 * @since 1.0.9 095 */ 096 public static TimeUnitQuantity of(Number number, TimeUnit timeUnit) { 097 return new TimeUnitQuantity(Objects.requireNonNull(timeUnit), Objects.requireNonNull(number)); 098 } 099 100 /** 101 * creates the {@link TimeUnitQuantity} using {@link TimeUnit} and {@link Integer} 102 * 103 * @param timeUnit 104 * - time to be used 105 * @param value 106 * - value to be used 107 * @since 1.0 108 * @deprecated use #of(Integer, TimeUnit) 109 */ 110 @Deprecated 111 public static TimeUnitQuantity of(TimeUnit timeUnit, Integer number) { 112 return of(number, timeUnit); 113 } 114 115 /** 116 * Creates a {@link TimeUnitQuantity} based a {@link Quantity<Time>} converted to {@link SI#SECOND}. 117 * 118 * @param quantity 119 * - quantity to be used 120 * @return the {@link TimeUnitQuantity} converted be quantity in seconds. 121 * @since 1.0 122 */ 123 public static TimeUnitQuantity of(Quantity<Time> quantity) { 124 Quantity<Time> seconds = Objects.requireNonNull(quantity).to(SECOND); 125 return new TimeUnitQuantity(TimeUnit.SECONDS, seconds.getValue()); 126 } 127 128 /** 129 * get to {@link TimeUnit} 130 * 131 * @return the TimeUnit 132 * @since 1.0 133 */ 134 public TimeUnit getTimeUnit() { 135 return timeUnit; 136 } 137 138 /** 139 * get value expressed in {@link Number} 140 * 141 * @return the value 142 * @since 1.0 143 */ 144 public Number getValue() { 145 return value; 146 } 147 148 /** 149 * converts the {@link TimeUnit} to {@link Unit} 150 * 151 * @return the {@link TimeUnitQuantity#getTimeUnit()} converted to Unit 152 * @since 1.0 153 */ 154 public Unit<Time> toUnit() { 155 return toUnit(timeUnit); 156 } 157 158 /** 159 * Converts the {@link TimeUnitQuantity} to {@link Quantity<Time>} 160 * 161 * @return this class converted to Quantity 162 * @since 1.0 163 */ 164 public Quantity<Time> toQuantity() { 165 return Quantities.getQuantity(value, toUnit()); 166 } 167 168 public TimeUnitQuantity to(TimeUnit aTimeUnit) { 169 Quantity<Time> time = toQuantity().to(toUnit(aTimeUnit)); 170 return new TimeUnitQuantity(aTimeUnit, time.getValue().longValue()); 171 } 172 173 private static Unit<Time> toUnit(TimeUnit timeUnit) { 174 switch (timeUnit) { 175 case MICROSECONDS: 176 return TimeQuantities.MICROSECOND; 177 case MILLISECONDS: 178 return TimeQuantities.MILLISECOND; 179 case NANOSECONDS: 180 return TimeQuantities.NANOSECOND; 181 case SECONDS: 182 return SECOND; 183 case MINUTES: 184 return MINUTE; 185 case HOURS: 186 return HOUR; 187 case DAYS: 188 return DAY; 189 default: 190 throw new IllegalStateException("In TimeUnitQuantity just supports DAYS, HOURS, MICROSECONDS, MILLISECONDS, MINUTES, NANOSECONDS, SECONDS "); 191 } 192 } 193 194 /** 195 * @since 1.0 196 */ 197 @Override 198 public int hashCode() { 199 return Objects.hash(timeUnit, value); 200 } 201 202 /** 203 * @since 1.0 204 */ 205 @Override 206 public boolean equals(Object obj) { 207 if (this == obj) { 208 return true; 209 } 210 if (TimeUnitQuantity.class.isInstance(obj)) { 211 TimeUnitQuantity other = TimeUnitQuantity.class.cast(obj); 212 return Objects.equals(timeUnit, other.timeUnit) && Objects.equals(value, other.value); 213 } 214 if (obj instanceof Quantity<?>) { 215 Quantity<?> that = (Quantity<?>) obj; 216 return Objects.equals(getUnit(), that.getUnit()) && 217 Calculus.currentNumberSystem().compare(value, that.getValue()) == 0; 218 219 } 220 return super.equals(obj); 221 } 222 223 @Override 224 public String toString() { 225 return "Time unit:" + timeUnit + " value: " + value; 226 } 227 228 /** 229 * @since 1.0.1 230 */ 231 @Override 232 public ComparableQuantity<Time> add(Quantity<Time> that) { 233 final UnitConverter thisToThat = this.getUnit().getConverterTo(that.getUnit()); 234 final boolean thatUnitIsSmaller = 235 Calculus.currentNumberSystem().compare(thisToThat.convert(1.), 1.)>0; 236 237 final Unit<Time> preferedUnit = thatUnitIsSmaller ? that.getUnit() : this.getUnit(); 238 239 final Number thisValueInPreferedUnit = convertedQuantityValue(this, preferedUnit); 240 final Number thatValueInPreferedUnit = convertedQuantityValue(that, preferedUnit); 241 242 final Number resultValueInPreferedUnit = Calculator.of(thisValueInPreferedUnit) 243 .add(thatValueInPreferedUnit) 244 .peek(); 245 246 return Quantities.getQuantity(resultValueInPreferedUnit, preferedUnit); 247 } 248 249 /** 250 * @since 1.0.1 251 */ 252 @Override 253 public ComparableQuantity<Time> subtract(Quantity<Time> that) { 254 return add(that.negate()); 255 } 256 257 /** 258 * @since 1.0.1 259 */ 260 @Override 261 public ComparableQuantity<?> divide(Quantity<?> that) { 262 return applyMultiplicativeQuantityOperation( 263 that, (a, b)->Calculator.of(a).divide(b).peek(), Unit::divide); 264 } 265 266 /** 267 * @since 1.0.1 268 */ 269 @Override 270 public ComparableQuantity<Time> divide(Number that) { 271 return applyMultiplicativeNumberOperation( 272 that, (a, b)->Calculator.of(a).divide(b).peek()); 273 } 274 275 /** 276 * @since 1.0.1 277 */ 278 @Override 279 public ComparableQuantity<?> multiply(Quantity<?> that) { 280 return applyMultiplicativeQuantityOperation( 281 that, (a, b)->Calculator.of(a).multiply(b).peek(), Unit::multiply); 282 } 283 284 /** 285 * @since 1.0.1 286 */ 287 @Override 288 public ComparableQuantity<Time> multiply(Number that) { 289 return applyMultiplicativeNumberOperation( 290 that, (a, b)->Calculator.of(a).multiply(b).peek()); 291 } 292 293 /** 294 * @since 1.0.1 295 */ 296 @Override 297 public ComparableQuantity<Frequency> inverse() { 298 return Quantities.getQuantity( 299 Calculator.of(value).reciprocal().peek(), 300 toUnit(timeUnit).inverse()).asType(Frequency.class); 301 } 302 303 /** 304 * @since 1.0.2 305 */ 306 @Override 307 public Quantity<Time> negate() { 308 return of( 309 Calculator.of(value).negate().peek(), 310 getTimeUnit()); 311 } 312 313 // -- HELPER 314 315 private static <R extends Quantity<R>> Number quantityValue(Quantity<R> that) { 316 return convertedQuantityValue(that, that.getUnit()); 317 } 318 319 private static <R extends Quantity<R>> Number convertedQuantityValue(Quantity<R> that, Unit<R> unit) { 320 return that.getUnit().getConverterTo(unit).convert(that.getValue()); 321 } 322 323 private ComparableQuantity<?> applyMultiplicativeQuantityOperation( 324 Quantity<?> that, 325 BinaryOperator<Number> valueOperator, 326 BinaryOperator<Unit<?>> unitOperator) { 327 328 final Number thisValue = quantityValue(this); 329 final Number thatValue = quantityValue(that); 330 final Number result = valueOperator.apply(thisValue, thatValue); 331 final Unit<?> resultUnit = unitOperator.apply(getUnit(), that.getUnit()); 332 return Quantities.getQuantity(result, resultUnit); 333 } 334 335 private ComparableQuantity<Time> applyMultiplicativeNumberOperation(Number that, 336 BinaryOperator<Number> valueOperator) { 337 final Number thisValue = this.getValue(); 338 final Number thatValue = that; 339 final Number result = valueOperator.apply(thisValue, thatValue); 340 return Quantities.getQuantity(result, getUnit()); 341 } 342}