1 package org.djunits.value.vdouble.scalar; 2 3 import java.util.regex.Matcher; 4 5 import org.djunits.unit.DurationUnit; 6 import org.djunits.unit.TimeUnit; 7 import org.djunits.unit.Unit; 8 9 /** 10 * Easy access methods for the Absolute Time DoubleScalar. Instead of: 11 * 12 * <pre> 13 * DoubleScalar.Abs<TimeUnit> value = new DoubleScalar.Abs<TimeUnit>(100.0, TimeUnit.SI); 14 * </pre> 15 * 16 * we can now write: 17 * 18 * <pre> 19 * Time value = new Time(100.0, TimeUnit.BASE); 20 * </pre> 21 * 22 * The compiler will automatically recognize which units belong to which quantity, and whether the quantity type and the unit 23 * used are compatible. 24 * <p> 25 * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. <br> 26 * All rights reserved. <br> 27 * BSD-style license. See <a href="http://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>. 28 * <p> 29 * Note that when the offset of a stored absolute Time becomes large, precision of a double might not be enough for the required 30 * resolution of a Time. A double has around 16 significant digits (52 bit mantissa). This means that when we need to have a 31 * double Time with TimeUnit.BASE as its unit, the largest value where the ms precision is reached is 2^51 = 2.3E15, which is 32 * around 71000 years. This is sufficient to store a date in the 21st Century with a BASE or an Epoch offset precise to a 33 * microsecond. 34 * <p> 35 * $LastChangedDate: 2019-03-03 00:53:50 +0100 (Sun, 03 Mar 2019) $, @version $Revision: 349 $, by $Author: averbraeck $, 36 * initial version Sep 1, 2015 <br> 37 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a> 38 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a> 39 */ 40 public class Time extends AbstractDoubleScalarAbs<TimeUnit, Time, DurationUnit, Duration> 41 { 42 /** */ 43 private static final long serialVersionUID = 20150901L; 44 45 /** constant with value zero. */ 46 public static final Time ZERO = new Time(0.0, TimeUnit.BASE); 47 48 /** 49 * Construct Time scalar. 50 * @param value double value 51 * @param unit unit for the double value 52 */ 53 public Time(final double value, final TimeUnit unit) 54 { 55 super(value, unit); 56 } 57 58 /** 59 * Construct Time scalar. 60 * @param value Scalar from which to construct this instance 61 */ 62 public Time(final Time value) 63 { 64 super(value); 65 } 66 67 /** {@inheritDoc} */ 68 @Override 69 public final Time instantiateAbs(final double value, final TimeUnit unit) 70 { 71 return new Time(value, unit); 72 } 73 74 /** {@inheritDoc} */ 75 @Override 76 public final Duration instantiateRel(final double value, final DurationUnit unit) 77 { 78 return new Duration(value, unit); 79 } 80 81 /** 82 * Construct %TypeAbsl% scalar. 83 * @param value double value in SI units 84 * @return the new scalar with the SI value 85 */ 86 public static final Time createSI(final double value) 87 { 88 return new Time(value, TimeUnit.BASE); 89 } 90 91 /** 92 * Interpolate between two values. 93 * @param zero the low value 94 * @param one the high value 95 * @param ratio the ratio between 0 and 1, inclusive 96 * @return a Scalar at the ratio between 97 */ 98 public static Time interpolate(final Time zero, final Time one, final double ratio) 99 { 100 return new Time(zero.getInUnit() * (1 - ratio) + one.getInUnit(zero.getUnit()) * ratio, zero.getUnit()); 101 } 102 103 /** 104 * Return the maximum value of two absolute scalars. 105 * @param a1 the first scalar 106 * @param a2 the second scalar 107 * @return the maximum value of two absolute scalars 108 */ 109 public static Time max(final Time a1, final Time a2) 110 { 111 return (a1.gt(a2)) ? a1 : a2; 112 } 113 114 /** 115 * Return the maximum value of more than two absolute scalars. 116 * @param a1 the first scalar 117 * @param a2 the second scalar 118 * @param an the other scalars 119 * @return the maximum value of more than two absolute scalars 120 */ 121 public static Time max(final Time a1, final Time a2, final Time... an) 122 { 123 Time maxa = (a1.gt(a2)) ? a1 : a2; 124 for (Time a : an) 125 { 126 if (a.gt(maxa)) 127 { 128 maxa = a; 129 } 130 } 131 return maxa; 132 } 133 134 /** 135 * Return the minimum value of two absolute scalars. 136 * @param a1 the first scalar 137 * @param a2 the second scalar 138 * @return the minimum value of two absolute scalars 139 */ 140 public static Time min(final Time a1, final Time a2) 141 { 142 return (a1.lt(a2)) ? a1 : a2; 143 } 144 145 /** 146 * Return the minimum value of more than two absolute scalars. 147 * @param a1 the first scalar 148 * @param a2 the second scalar 149 * @param an the other scalars 150 * @return the minimum value of more than two absolute scalars 151 */ 152 public static Time min(final Time a1, final Time a2, final Time... an) 153 { 154 Time mina = (a1.lt(a2)) ? a1 : a2; 155 for (Time a : an) 156 { 157 if (a.lt(mina)) 158 { 159 mina = a; 160 } 161 } 162 return mina; 163 } 164 165 /** 166 * Returns a Time representation of a textual representation of a value with a unit. The String representation that can be 167 * parsed is the double value in the unit, followed by the official abbreviation of the unit. Spaces are allowed, but not 168 * necessary, between the value and the unit. 169 * @param text String; the textual representation to parse into a Time 170 * @return the String representation of the value in its unit, followed by the official abbreviation of the unit 171 * @throws IllegalArgumentException when the text cannot be parsed 172 */ 173 public static Time valueOf(final String text) throws IllegalArgumentException 174 { 175 if (text == null || text.length() == 0) 176 { 177 throw new IllegalArgumentException("Error parsing Time -- null or empty argument"); 178 } 179 Matcher matcher = NUMBER_PATTERN.matcher(text); 180 if (matcher.find()) 181 { 182 int index = matcher.end(); 183 try 184 { 185 String unitString = text.substring(index).trim(); 186 String valueString = text.substring(0, index).trim(); 187 for (TimeUnit unit : Unit.getUnits(TimeUnit.class)) 188 { 189 if (unit.getDefaultLocaleTextualRepresentations().contains(unitString)) 190 { 191 double d = Double.parseDouble(valueString); 192 return new Time(d, unit); 193 } 194 } 195 } 196 catch (Exception exception) 197 { 198 throw new IllegalArgumentException("Error parsing Time from " + text, exception); 199 } 200 } 201 throw new IllegalArgumentException("Error parsing Time from " + text); 202 } 203 204 }