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