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