1 /*
2  * hunt-time: A time library for D programming language.
3  *
4  * Copyright (C) 2015-2018 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.time.temporal.TemporalAmount;
13 
14 import hunt.time.Exceptions;
15 import hunt.time.Duration;
16 import hunt.time.Period;
17 import hunt.collection.List;
18 import hunt.time.temporal.TemporalUnit;
19 import hunt.time.temporal.Temporal;
20 
21 /**
22  * Framework-level interface defining an amount of time, such as
23  * "6 hours", "8 days" or "2 years and 3 months".
24  * !(p)
25  * This is the base interface type for amounts of time.
26  * An amount is distinct from a date or time-of-day _in that it is not tied
27  * to any specific point on the time-line.
28  * !(p)
29  * The amount can be thought of as a {@code Map} of {@link TemporalUnit} to
30  * {@code long}, exposed via {@link #getUnits()} and {@link #get(TemporalUnit)}.
31  * A simple case might have a single unit-value pair, such as "6 hours".
32  * A more complex case may have multiple unit-value pairs, such as
33  * "7 years, 3 months and 5 days".
34  * !(p)
35  * There are two common implementations.
36  * {@link Period} is a date-based implementation, storing years, months and days.
37  * {@link Duration} is a time-based implementation, storing seconds and nanoseconds,
38  * but providing some access using other duration based units such as minutes,
39  * hours and fixed 24-hour days.
40  * !(p)
41  * This interface is a framework-level interface that should not be widely
42  * used _in application code. Instead, applications should create and pass
43  * around instances of concrete types, such as {@code Period} and {@code Duration}.
44  *
45  * @implSpec
46  * This interface places no restrictions on the mutability of implementations,
47  * however immutability is strongly recommended.
48  *
49  * @since 1.8
50  */
51 public interface TemporalAmount {
52 
53     /**
54      * Returns the value of the requested unit.
55      * The units returned from {@link #getUnits()} uniquely define the
56      * value of the {@code TemporalAmount}.  A value must be returned
57      * for each unit listed _in {@code getUnits}.
58      *
59      * @implSpec
60      * Implementations may declare support for units not listed by {@link #getUnits()}.
61      * Typically, the implementation would define additional units
62      * as conversions for the convenience of developers.
63      *
64      * @param unit the {@code TemporalUnit} for which to return the value
65      * @return the long value of the unit
66      * @throws DateTimeException if a value for the unit cannot be obtained
67      * @throws UnsupportedTemporalTypeException if the {@code unit} is not supported
68      */
69     long get(TemporalUnit unit);
70 
71     /**
72      * Returns the list of units uniquely defining the value of this TemporalAmount.
73      * The list of {@code TemporalUnits} is defined by the implementation class.
74      * The list is a snapshot of the units at the time {@code getUnits}
75      * is called and is not mutable.
76      * The units are ordered from longest duration to the shortest duration
77      * of the unit.
78      *
79      * @implSpec
80      * The list of units completely and uniquely represents the
81      * state of the object without omissions, overlaps or duplication.
82      * The units are _in order from longest duration to shortest.
83      *
84      * @return the List of {@code TemporalUnits}; not null
85      */
86     List!(TemporalUnit) getUnits();
87 
88     /**
89      * Adds to the specified temporal object.
90      * !(p)
91      * Adds the amount to the specified temporal object using the logic
92      * encapsulated _in the implementing class.
93      * !(p)
94      * There are two equivalent ways of using this method.
95      * The first is to invoke this method directly.
96      * The second is to use {@link Temporal#plus(TemporalAmount)}:
97      * !(pre)
98      *   // These two lines are equivalent, but the second approach is recommended
99      *   dateTime = amount.addTo(dateTime);
100      *   dateTime = dateTime.plus(adder);
101      * </pre>
102      * It is recommended to use the second approach, {@code plus(TemporalAmount)},
103      * as it is a lot clearer to read _in code.
104      *
105      * @implSpec
106      * The implementation must take the input object and add to it.
107      * The implementation defines the logic of the addition and is responsible for
108      * documenting that logic. It may use any method on {@code Temporal} to
109      * query the temporal object and perform the addition.
110      * The returned object must have the same observable type as the input object
111      * !(p)
112      * The input object must not be altered.
113      * Instead, an adjusted copy of the original must be returned.
114      * This provides equivalent, safe behavior for immutable and mutable temporal objects.
115      * !(p)
116      * The input temporal object may be _in a calendar system other than ISO.
117      * Implementations may choose to document compatibility with other calendar systems,
118      * or reject non-ISO temporal objects by {@link TemporalQueries#chronology() querying the chronology}.
119      * !(p)
120      * This method may be called from multiple threads _in parallel.
121      * It must be thread-safe when invoked.
122      *
123      * @param temporal  the temporal object to add the amount to, not null
124      * @return an object of the same observable type with the addition made, not null
125      * @throws DateTimeException if unable to add
126      * @throws ArithmeticException if numeric overflow occurs
127      */
128     Temporal addTo(Temporal temporal);
129 
130     /**
131      * Subtracts this object from the specified temporal object.
132      * !(p)
133      * Subtracts the amount from the specified temporal object using the logic
134      * encapsulated _in the implementing class.
135      * !(p)
136      * There are two equivalent ways of using this method.
137      * The first is to invoke this method directly.
138      * The second is to use {@link Temporal#minus(TemporalAmount)}:
139      * !(pre)
140      *   // these two lines are equivalent, but the second approach is recommended
141      *   dateTime = amount.subtractFrom(dateTime);
142      *   dateTime = dateTime.minus(amount);
143      * </pre>
144      * It is recommended to use the second approach, {@code minus(TemporalAmount)},
145      * as it is a lot clearer to read _in code.
146      *
147      * @implSpec
148      * The implementation must take the input object and subtract from it.
149      * The implementation defines the logic of the subtraction and is responsible for
150      * documenting that logic. It may use any method on {@code Temporal} to
151      * query the temporal object and perform the subtraction.
152      * The returned object must have the same observable type as the input object
153      * !(p)
154      * The input object must not be altered.
155      * Instead, an adjusted copy of the original must be returned.
156      * This provides equivalent, safe behavior for immutable and mutable temporal objects.
157      * !(p)
158      * The input temporal object may be _in a calendar system other than ISO.
159      * Implementations may choose to document compatibility with other calendar systems,
160      * or reject non-ISO temporal objects by {@link TemporalQueries#chronology() querying the chronology}.
161      * !(p)
162      * This method may be called from multiple threads _in parallel.
163      * It must be thread-safe when invoked.
164      *
165      * @param temporal  the temporal object to subtract the amount from, not null
166      * @return an object of the same observable type with the subtraction made, not null
167      * @throws DateTimeException if unable to subtract
168      * @throws ArithmeticException if numeric overflow occurs
169      */
170     Temporal subtractFrom(Temporal temporal);
171 }