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 }