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 11package android.icu.impl.duration; 12 13import android.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 Only a subset of ICU is exposed in Android 30 */ 31public 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 286public 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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