1 /* GENERATED SOURCE. DO NOT MODIFY. */
2 // © 2016 and later: Unicode, Inc. and others.
3 // License & terms of use: http://www.unicode.org/copyright.html#License
4 /*
5 ******************************************************************************
6 * Copyright (C) 2007, International Business Machines Corporation and *
7 * others. All Rights Reserved. *
8 ******************************************************************************
9 */
10
11 package ohos.global.icu.impl.duration;
12
13 import ohos.global.icu.impl.duration.impl.DataRecord.ETimeLimit;
14
15 /**
16 * Represents an approximate duration in multiple TimeUnits. Each unit,
17 * if set, has a count (which can be fractional and must be non-negative).
18 * In addition Period can either represent the duration as being into the past
19 * or future, and as being more or less than the defined value.
20 * <p>
21 * Use a PeriodFormatter to convert a Period to a String.
22 * <p>
23 * Periods are immutable. Mutating operations return the new
24 * result leaving the original unchanged.
25 * <p>
26 * Example:<pre>
27 * Period p1 = Period.at(3, WEEK).and(2, DAY).inFuture();
28 * Period p2 = p1.and(12, HOUR);</pre>
29 * @hide exposed on OHOS
30 */
31 public final class Period {
32 final byte timeLimit;
33 final boolean inFuture;
34 final int[] counts;
35
36 /**
37 * Constructs a Period representing a duration of
38 * count units extending into the past.
39 * @param count the number of units, must be non-negative
40 * @param unit the unit
41 * @return the new Period
42 */
at(float count, TimeUnit unit)43 public static Period at(float count, TimeUnit unit) {
44 checkCount(count);
45 return new Period(ETimeLimit.NOLIMIT, false, count, unit);
46 }
47
48 /**
49 * Constructs a Period representing a duration more than
50 * count units extending into the past.
51 * @param count the number of units. must be non-negative
52 * @param unit the unit
53 * @return the new Period
54 */
moreThan(float count, TimeUnit unit)55 public static Period moreThan(float count, TimeUnit unit) {
56 checkCount(count);
57 return new Period(ETimeLimit.MT, false, count, unit);
58 }
59
60 /**
61 * Constructs a Period representing a duration
62 * less than count units extending into the past.
63 * @param count the number of units. must be non-negative
64 * @param unit the unit
65 * @return the new Period
66 */
lessThan(float count, TimeUnit unit)67 public static Period lessThan(float count, TimeUnit unit) {
68 checkCount(count);
69 return new Period(ETimeLimit.LT, false, count, unit);
70 }
71
72 /**
73 * Set the given unit to have the given count. Marks the
74 * unit as having been set. This can be used to set
75 * multiple units, or to reset a unit to have a new count.
76 * This does <b>not</b> add the count to an existing count
77 * for this unit.
78 *
79 * @param count the number of units. must be non-negative
80 * @param unit the unit
81 * @return the new Period
82 */
and(float count, TimeUnit unit)83 public Period and(float count, TimeUnit unit) {
84 checkCount(count);
85 return setTimeUnitValue(unit, count);
86 }
87
88 /**
89 * Mark the given unit as not being set.
90 *
91 * @param unit the unit to unset
92 * @return the new Period
93 */
omit(TimeUnit unit)94 public Period omit(TimeUnit unit) {
95 return setTimeUnitInternalValue(unit, 0);
96 }
97
98 /**
99 * Mark the duration as being at the defined duration.
100 *
101 * @return the new Period
102 */
at()103 public Period at() {
104 return setTimeLimit(ETimeLimit.NOLIMIT);
105 }
106
107 /**
108 * Mark the duration as being more than the defined duration.
109 *
110 * @return the new Period
111 */
moreThan()112 public Period moreThan() {
113 return setTimeLimit(ETimeLimit.MT);
114 }
115
116 /**
117 * Mark the duration as being less than the defined duration.
118 *
119 * @return the new Period
120 */
lessThan()121 public Period lessThan() {
122 return setTimeLimit(ETimeLimit.LT);
123 }
124
125 /**
126 * Mark the time as being in the future.
127 *
128 * @return the new Period
129 */
inFuture()130 public Period inFuture() {
131 return setFuture(true);
132 }
133
134 /**
135 * Mark the duration as extending into the past.
136 *
137 * @return the new Period
138 */
inPast()139 public Period inPast() {
140 return setFuture(false);
141 }
142
143 /**
144 * Mark the duration as extending into the future if
145 * future is true, and into the past otherwise.
146 *
147 * @param future true if the time is in the future
148 * @return the new Period
149 */
inFuture(boolean future)150 public Period inFuture(boolean future) {
151 return setFuture(future);
152 }
153
154 /**
155 * Mark the duration as extending into the past if
156 * past is true, and into the future otherwise.
157 *
158 * @param past true if the time is in the past
159 * @return the new Period
160 */
inPast(boolean past)161 public Period inPast(boolean past) {
162 return setFuture(!past);
163 }
164
165 /**
166 * Returns true if any unit is set.
167 * @return true if any unit is set
168 */
isSet()169 public boolean isSet() {
170 for (int i = 0; i < counts.length; ++i) {
171 if (counts[i] != 0) {
172 return true;
173 }
174 }
175 return false;
176 }
177
178 /**
179 * Returns true if the given unit is set.
180 * @param unit the unit to test
181 * @return true if the given unit is set.
182 */
isSet(TimeUnit unit)183 public boolean isSet(TimeUnit unit) {
184 return counts[unit.ordinal] > 0;
185 }
186
187 /**
188 * Returns the count for the specified unit. If the
189 * unit is not set, returns 0.
190 * @param unit the unit to test
191 * @return the count
192 */
getCount(TimeUnit unit)193 public float getCount(TimeUnit unit) {
194 int ord = unit.ordinal;
195 if (counts[ord] == 0) {
196 return 0;
197 }
198 return (counts[ord] - 1)/1000f;
199 }
200
201 /**
202 * Returns true if this represents a
203 * duration into the future.
204 * @return true if this represents a
205 * duration into the future.
206 */
isInFuture()207 public boolean isInFuture() {
208 return inFuture;
209 }
210
211 /**
212 * Returns true if this represents a
213 * duration into the past
214 * @return true if this represents a
215 * duration into the past
216 */
isInPast()217 public boolean isInPast () {
218 return !inFuture;
219 }
220
221 /**
222 * Returns true if this represents a duration in
223 * excess of the defined duration.
224 * @return true if this represents a duration in
225 * excess of the defined duration.
226 */
isMoreThan()227 public boolean isMoreThan() {
228 return timeLimit == ETimeLimit.MT;
229 }
230
231 /**
232 * Returns true if this represents a duration
233 * less than the defined duration.
234 * @return true if this represents a duration
235 * less than the defined duration.
236 */
isLessThan()237 public boolean isLessThan() {
238 return timeLimit == ETimeLimit.LT;
239 }
240
241 /**
242 * Returns true if rhs extends Period and
243 * the two Periods are equal.
244 * @param rhs the object to compare to
245 * @return true if rhs is a Period and is equal to this
246 */
247 @Override
equals(Object rhs)248 public boolean equals(Object rhs) {
249 try {
250 return equals((Period)rhs);
251 }
252 catch (ClassCastException e) {
253 return false;
254 }
255 }
256
257 /**
258 * Returns true if the same units are defined with
259 * the same counts, both extend into the future or both into the
260 * past, and if the limits (at, more than, less than) are the same.
261 * Note that this means that a period of 1000ms and a period of 1sec
262 * will not compare equal.
263 *
264 * @param rhs the period to compare to
265 * @return true if the two periods are equal
266 */
equals(Period rhs)267 public boolean equals(Period rhs) {
268 if (rhs != null &&
269 this.timeLimit == rhs.timeLimit &&
270 this.inFuture == rhs.inFuture) {
271 for (int i = 0; i < counts.length; ++i) {
272 if (counts[i] != rhs.counts[i]) {
273 return false;
274 }
275 }
276 return true;
277 }
278 return false;
279 }
280
281 /**
282 * Returns the hashCode.
283 * @return the hashCode
284 */
285 @Override
hashCode()286 public int hashCode() {
287 int hc = (timeLimit << 1) | (inFuture ? 1 : 0);
288 for (int i = 0; i < counts.length; ++i) {
289 hc = (hc << 2) ^ counts[i];
290 }
291 return hc;
292 }
293
294 /**
295 * Private constructor used by static factory methods.
296 */
Period(int limit, boolean future, float count, TimeUnit unit)297 private Period(int limit, boolean future, float count, TimeUnit unit) {
298 this.timeLimit = (byte) limit;
299 this.inFuture = future;
300 this.counts = new int[TimeUnit.units.length];
301 this.counts[unit.ordinal] = (int)(count * 1000) + 1;
302 }
303
304 /**
305 * Package private constructor used by setters and factory.
306 */
Period(int timeLimit, boolean inFuture, int[] counts)307 Period(int timeLimit, boolean inFuture, int[] counts) {
308 this.timeLimit = (byte) timeLimit;
309 this.inFuture = inFuture;
310 this.counts = counts;
311 }
312
313 /**
314 * Set the unit's internal value, converting from float to int.
315 */
setTimeUnitValue(TimeUnit unit, float value)316 private Period setTimeUnitValue(TimeUnit unit, float value) {
317 if (value < 0) {
318 throw new IllegalArgumentException("value: " + value);
319 }
320 return setTimeUnitInternalValue(unit, (int)(value * 1000) + 1);
321 }
322
323 /**
324 * Sets the period to have the provided value, 1/1000 of the
325 * unit plus 1. Thus unset values are '0', 1' is the set value '0',
326 * 2 is the set value '1/1000', 3 is the set value '2/1000' etc.
327 * @param p the period to change
328 * @param value the int value as described above.
329 * @eturn the new Period object.
330 */
setTimeUnitInternalValue(TimeUnit unit, int value)331 private Period setTimeUnitInternalValue(TimeUnit unit, int value) {
332 int ord = unit.ordinal;
333 if (counts[ord] != value) {
334 int[] newCounts = new int[counts.length];
335 for (int i = 0; i < counts.length; ++i) {
336 newCounts[i] = counts[i];
337 }
338 newCounts[ord] = value;
339 return new Period(timeLimit, inFuture, newCounts);
340 }
341 return this;
342 }
343
344 /**
345 * Sets whether this defines a future time.
346 * @param future true if the time is in the future
347 * @return the new Period
348 */
setFuture(boolean future)349 private Period setFuture(boolean future) {
350 if (this.inFuture != future) {
351 return new Period(timeLimit, future, counts);
352 }
353 return this;
354 }
355
356 /**
357 * Sets whether this is more than, less than, or
358 * 'about' the specified time.
359 * @param limit the kind of limit
360 * @return the new Period
361 */
setTimeLimit(byte limit)362 private Period setTimeLimit(byte limit) {
363 if (this.timeLimit != limit) {
364 return new Period(limit, inFuture, counts);
365
366 }
367 return this;
368 }
369
370 /**
371 * Validate count.
372 */
checkCount(float count)373 private static void checkCount(float count) {
374 if (count < 0) {
375 throw new IllegalArgumentException("count (" + count +
376 ") cannot be negative");
377 }
378 }
379 }
380