All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ibm.icu.impl.duration.Period Maven / Gradle / Ivy

There is a newer version: 2.12.15
Show newest version
// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
/*
******************************************************************************
* Copyright (C) 2007, International Business Machines Corporation and   *
* others. All Rights Reserved.                                               *
******************************************************************************
*/

package com.ibm.icu.impl.duration;

import com.ibm.icu.impl.duration.impl.DataRecord.ETimeLimit;

/**
 * Represents an approximate duration in multiple TimeUnits.  Each unit,
 * if set, has a count (which can be fractional and must be non-negative).
 * In addition Period can either represent the duration as being into the past
 * or future, and as being more or less than the defined value.
 * 

* Use a PeriodFormatter to convert a Period to a String. *

* Periods are immutable. Mutating operations return the new * result leaving the original unchanged. *

* Example:

 * Period p1 = Period.at(3, WEEK).and(2, DAY).inFuture();
 * Period p2 = p1.and(12, HOUR);
*/ public final class Period { final byte timeLimit; final boolean inFuture; final int[] counts; /** * Constructs a Period representing a duration of * count units extending into the past. * @param count the number of units, must be non-negative * @param unit the unit * @return the new Period */ public static Period at(float count, TimeUnit unit) { checkCount(count); return new Period(ETimeLimit.NOLIMIT, false, count, unit); } /** * Constructs a Period representing a duration more than * count units extending into the past. * @param count the number of units. must be non-negative * @param unit the unit * @return the new Period */ public static Period moreThan(float count, TimeUnit unit) { checkCount(count); return new Period(ETimeLimit.MT, false, count, unit); } /** * Constructs a Period representing a duration * less than count units extending into the past. * @param count the number of units. must be non-negative * @param unit the unit * @return the new Period */ public static Period lessThan(float count, TimeUnit unit) { checkCount(count); return new Period(ETimeLimit.LT, false, count, unit); } /** * Set the given unit to have the given count. Marks the * unit as having been set. This can be used to set * multiple units, or to reset a unit to have a new count. * This does not add the count to an existing count * for this unit. * * @param count the number of units. must be non-negative * @param unit the unit * @return the new Period */ public Period and(float count, TimeUnit unit) { checkCount(count); return setTimeUnitValue(unit, count); } /** * Mark the given unit as not being set. * * @param unit the unit to unset * @return the new Period */ public Period omit(TimeUnit unit) { return setTimeUnitInternalValue(unit, 0); } /** * Mark the duration as being at the defined duration. * * @return the new Period */ public Period at() { return setTimeLimit(ETimeLimit.NOLIMIT); } /** * Mark the duration as being more than the defined duration. * * @return the new Period */ public Period moreThan() { return setTimeLimit(ETimeLimit.MT); } /** * Mark the duration as being less than the defined duration. * * @return the new Period */ public Period lessThan() { return setTimeLimit(ETimeLimit.LT); } /** * Mark the time as being in the future. * * @return the new Period */ public Period inFuture() { return setFuture(true); } /** * Mark the duration as extending into the past. * * @return the new Period */ public Period inPast() { return setFuture(false); } /** * Mark the duration as extending into the future if * future is true, and into the past otherwise. * * @param future true if the time is in the future * @return the new Period */ public Period inFuture(boolean future) { return setFuture(future); } /** * Mark the duration as extending into the past if * past is true, and into the future otherwise. * * @param past true if the time is in the past * @return the new Period */ public Period inPast(boolean past) { return setFuture(!past); } /** * Returns true if any unit is set. * @return true if any unit is set */ public boolean isSet() { for (int i = 0; i < counts.length; ++i) { if (counts[i] != 0) { return true; } } return false; } /** * Returns true if the given unit is set. * @param unit the unit to test * @return true if the given unit is set. */ public boolean isSet(TimeUnit unit) { return counts[unit.ordinal] > 0; } /** * Returns the count for the specified unit. If the * unit is not set, returns 0. * @param unit the unit to test * @return the count */ public float getCount(TimeUnit unit) { int ord = unit.ordinal; if (counts[ord] == 0) { return 0; } return (counts[ord] - 1)/1000f; } /** * Returns true if this represents a * duration into the future. * @return true if this represents a * duration into the future. */ public boolean isInFuture() { return inFuture; } /** * Returns true if this represents a * duration into the past * @return true if this represents a * duration into the past */ public boolean isInPast () { return !inFuture; } /** * Returns true if this represents a duration in * excess of the defined duration. * @return true if this represents a duration in * excess of the defined duration. */ public boolean isMoreThan() { return timeLimit == ETimeLimit.MT; } /** * Returns true if this represents a duration * less than the defined duration. * @return true if this represents a duration * less than the defined duration. */ public boolean isLessThan() { return timeLimit == ETimeLimit.LT; } /** * Returns true if rhs extends Period and * the two Periods are equal. * @param rhs the object to compare to * @return true if rhs is a Period and is equal to this */ @Override public boolean equals(Object rhs) { try { return equals((Period)rhs); } catch (ClassCastException e) { return false; } } /** * Returns true if the same units are defined with * the same counts, both extend into the future or both into the * past, and if the limits (at, more than, less than) are the same. * Note that this means that a period of 1000ms and a period of 1sec * will not compare equal. * * @param rhs the period to compare to * @return true if the two periods are equal */ public boolean equals(Period rhs) { if (rhs != null && this.timeLimit == rhs.timeLimit && this.inFuture == rhs.inFuture) { for (int i = 0; i < counts.length; ++i) { if (counts[i] != rhs.counts[i]) { return false; } } return true; } return false; } /** * Returns the hashCode. * @return the hashCode */ @Override public int hashCode() { int hc = (timeLimit << 1) | (inFuture ? 1 : 0); for (int i = 0; i < counts.length; ++i) { hc = (hc << 2) ^ counts[i]; } return hc; } /** * Private constructor used by static factory methods. */ private Period(int limit, boolean future, float count, TimeUnit unit) { this.timeLimit = (byte) limit; this.inFuture = future; this.counts = new int[TimeUnit.units.length]; this.counts[unit.ordinal] = (int)(count * 1000) + 1; } /** * Package private constructor used by setters and factory. */ Period(int timeLimit, boolean inFuture, int[] counts) { this.timeLimit = (byte) timeLimit; this.inFuture = inFuture; this.counts = counts; } /** * Set the unit's internal value, converting from float to int. */ private Period setTimeUnitValue(TimeUnit unit, float value) { if (value < 0) { throw new IllegalArgumentException("value: " + value); } return setTimeUnitInternalValue(unit, (int)(value * 1000) + 1); } /** * Sets the period to have the provided value, 1/1000 of the * unit plus 1. Thus unset values are '0', 1' is the set value '0', * 2 is the set value '1/1000', 3 is the set value '2/1000' etc. * @param p the period to change * @param value the int value as described above. * @eturn the new Period object. */ private Period setTimeUnitInternalValue(TimeUnit unit, int value) { int ord = unit.ordinal; if (counts[ord] != value) { int[] newCounts = new int[counts.length]; for (int i = 0; i < counts.length; ++i) { newCounts[i] = counts[i]; } newCounts[ord] = value; return new Period(timeLimit, inFuture, newCounts); } return this; } /** * Sets whether this defines a future time. * @param future true if the time is in the future * @return the new Period */ private Period setFuture(boolean future) { if (this.inFuture != future) { return new Period(timeLimit, future, counts); } return this; } /** * Sets whether this is more than, less than, or * 'about' the specified time. * @param limit the kind of limit * @return the new Period */ private Period setTimeLimit(byte limit) { if (this.timeLimit != limit) { return new Period(limit, inFuture, counts); } return this; } /** * Validate count. */ private static void checkCount(float count) { if (count < 0) { throw new IllegalArgumentException("count (" + count + ") cannot be negative"); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy