1 package org.djunits.quantity;
2
3 import org.djunits.quantity.def.AbsQuantity;
4 import org.djunits.quantity.def.AbstractReference;
5 import org.djunits.quantity.def.Quantity;
6 import org.djunits.unit.Units;
7
8 /**
9 * Time is the absolute equivalent of Duration, and can, e.g., represent a calendar date with a zero. Note that built-in time
10 * references are independent; DJUNITS does not embed calendar calculations.
11 * <p>
12 * Copyright (c) 2025-2026 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
13 * for project information <a href="https://djunits.org" target="_blank">https://djunits.org</a>. The DJUNITS project is
14 * distributed under a <a href="https://djunits.org/docs/license.html" target="_blank">three-clause BSD-style license</a>.
15 * @author Alexander Verbraeck
16 */
17 public class Time extends AbsQuantity<Time, Duration, Time.Reference>
18 {
19 /** */
20 private static final long serialVersionUID = 600L;
21
22 /**
23 * Instantiate a Time quantity with a unit and a reference point.
24 * @param valueInUnit the duration value, expressed in a duration unit
25 * @param unit the duration unit in which the value is expressed, relative to the reference point
26 * @param reference the reference point of this time
27 */
28 public Time(final double valueInUnit, final Duration.Unit unit, final Reference reference)
29 {
30 super(new Duration(valueInUnit, unit), reference);
31 }
32
33 /**
34 * Instantiate a Time quantity with a unit, expressed as a String, and a reference point.
35 * @param valueInUnit the duration value, expressed in the unit, relative to the reference point
36 * @param abbreviation the String abbreviation of the unit in which the value is expressed
37 * @param reference the reference point of this time
38 */
39 public Time(final double valueInUnit, final String abbreviation, final Reference reference)
40 {
41 this(valueInUnit, Units.resolve(Duration.Unit.class, abbreviation), reference);
42 }
43
44 /**
45 * Instantiate a Time instance based on an duration and a reference point.
46 * @param duration the duration, relative to the reference point
47 * @param reference the reference point of this time
48 */
49 public Time(final Duration duration, final Reference reference)
50 {
51 super(duration, reference);
52 }
53
54 /**
55 * Return a Time instance based on an SI value and a reference point.
56 * @param si the duration si value, relative to the reference point
57 * @param reference the reference point of this time
58 * @return the Time instance based on an SI value
59 */
60 public static Time ofSi(final double si, final Reference reference)
61 {
62 return new Time(si, Duration.Unit.SI, reference);
63 }
64
65 @Override
66 public Time instantiate(final Duration duration, final Reference reference)
67 {
68 return new Time(duration, reference);
69 }
70
71 /**
72 * Returns a Time representation of a textual representation of a value with a unit. The String representation that can be
73 * parsed is the double value in the unit, followed by a localized or English abbreviation of the unit. Spaces are allowed,
74 * but not required, between the value and the unit.
75 * @param text the textual representation to parse into a Time
76 * @param reference the reference point of this time
77 * @return the Scalar representation of the value in its unit
78 * @throws IllegalArgumentException when the text cannot be parsed
79 * @throws NullPointerException when the text argument is null
80 */
81 public static Time valueOf(final String text, final Reference reference)
82 {
83 return new Time(Quantity.valueOf(text, Duration.ZERO), reference);
84 }
85
86 /**
87 * Returns a Time based on a value and the textual representation of the unit, which can be localized.
88 * @param valueInUnit the value, expressed in the unit as given by unitString
89 * @param unitString the textual representation of the unit
90 * @param reference the reference point of this time
91 * @return the Scalar representation of the value in its unit
92 * @throws IllegalArgumentException when the unit cannot be parsed or is incorrect
93 * @throws NullPointerException when the unitString argument is null
94 */
95 public static Time of(final double valueInUnit, final String unitString, final Reference reference)
96 {
97 return new Time(Quantity.of(valueInUnit, unitString, Duration.ZERO), reference);
98 }
99
100 @Override
101 public Duration subtract(final Time other)
102 {
103 var otherRef = other.relativeTo(getReference());
104 return Duration.ofSi(si() - otherRef.si()).setDisplayUnit(getDisplayUnit());
105 }
106
107 @Override
108 public Time add(final Duration other)
109 {
110 return new Time(Duration.ofSi(si() + other.si()).setDisplayUnit(getDisplayUnit()), getReference());
111 }
112
113 @Override
114 public Time subtract(final Duration other)
115 {
116 return new Time(Duration.ofSi(si() - other.si()).setDisplayUnit(getDisplayUnit()), getReference());
117 }
118
119 /**
120 * The reference class to define a reference point for the time. Note that built-in time references are independent; DJUNITS
121 * does not embed calendar calculations.
122 */
123 public static final class Reference extends AbstractReference<Reference, Time, Duration>
124 {
125 /** Gregorian. */
126 public static final Reference GREGORIAN = new Reference("GREGORIAN", "Gregorian time origin (1-1-0000)");
127
128 /** Unix. */
129 public static final Reference UNIX = new Reference("UNIX", "UNIX epoch, 1-1-1970, 00:00 GMT");
130
131 /** GPS. */
132 public static final Reference GPS = new Reference("GPS", "GPS epoch, 6-1-1980");
133
134 /**
135 * Define a new reference point for the time, with an offset value to another reference.
136 * @param id the id
137 * @param name the name or explanation
138 * @param offset the offset w.r.t. offsetReference
139 * @param offsetReference the reference to which the offset is relative
140 */
141 public Reference(final String id, final String name, final Duration offset, final Reference offsetReference)
142 {
143 super(id, name, offset, offsetReference);
144 }
145
146 /**
147 * Define a new reference point for the time without an offset to a base reference.
148 * @param id the id
149 * @param name the name or explanation
150 */
151 public Reference(final String id, final String name)
152 {
153 super(id, name, Duration.ZERO, null);
154 }
155
156 /**
157 * Define a new reference point for the time, with an offset value to another reference.
158 * @param id the id
159 * @param name the name or explanation
160 * @param offset the offset w.r.t. offsetReference
161 * @param offsetReference the reference to which the offset is relative
162 */
163 public static void add(final String id, final String name, final Duration offset, final Reference offsetReference)
164 {
165 new Reference(id, name, offset, offsetReference);
166 }
167
168 /**
169 * Define a new reference point for the time without an offset to a base reference.
170 * @param id the id
171 * @param name the name or explanation
172 */
173 public static void add(final String id, final String name)
174 {
175 new Reference(id, name);
176 }
177
178 /**
179 * Get a reference point for the time, based on its id. Return null when the id could not be found.
180 * @param id the id
181 * @return the TimeReference object
182 */
183 public static Reference get(final String id)
184 {
185 return AbstractReference.get(Time.Reference.class, id);
186 }
187
188 @Override
189 public Time instantiate(final Duration duration)
190 {
191 return new Time(duration, this);
192 }
193 }
194 }