javax.time.calendar
Class PeriodFields

java.lang.Object
  extended by javax.time.calendar.PeriodFields
All Implemented Interfaces:
java.io.Serializable, java.lang.Iterable<PeriodField>, PeriodProvider

public final class PeriodFields
extends java.lang.Object
implements PeriodProvider, java.lang.Iterable<PeriodField>, java.io.Serializable

A period of time measured using a number of different units, such as '3 Months, 4 Days and 7 Hours'.

PeriodFields is an immutable period that stores an amount of human-scale time for a number of units. For example, humans typically measure periods of time in units of years, months, days, hours, minutes and seconds. These concepts are defined by instances of PeriodUnit in the chronology classes. This class allows an amount to be specified for a number of the units, such as '3 Days and 65 Seconds'.

Basic mathematical operations are provided - plus(), minus(), multipliedBy(), dividedBy() and negated(), all of which return a new instance

A value of zero can also be stored for any unit. This means that a period of zero hours is not equal to a period of zero minutes. However, an empty instance constant exists to represent zero irrespective of unit. The withZeroesRemoved() method removes zero values.

PeriodFields can store units of any kind which makes it usable with any calendar system.

PeriodFields is immutable and thread-safe.

Author:
Stephen Colebourne
See Also:
Serialized Form

Field Summary
static PeriodFields ZERO
          A constant for a period of zero.
 
Method Summary
 boolean contains(PeriodUnit unit)
          Checks if this set of fields contains a field with the specified unit.
 PeriodFields dividedBy(long divisor)
          Returns a copy of this period with each amount in this period divided by the specified value.
 boolean equals(java.lang.Object obj)
          Checks if this set of fields is equal to another set of fields.
 long getAmount(PeriodUnit unit)
          Gets the amount for the specified unit.
 int getAmountInt(PeriodUnit unit)
          Gets the amount for the specified unit converted to an int.
 PeriodField getField(PeriodUnit unit)
          Gets the stored field for the specified unit.
 int hashCode()
          A hash code for this set of fields.
 boolean isPositive()
          Checks if this period is fully positive, excluding zero.
 boolean isPositiveOrZero()
          Checks if this period is fully positive, including zero.
 boolean isZero()
          Checks if this period is zero-length.
 java.util.Iterator<PeriodField> iterator()
          Iterates through all the fields.
 PeriodFields minus(long amountToSubtract, PeriodUnit unit)
          Returns a copy of this period with the specified period subtracted.
 PeriodFields minus(PeriodProvider periodToSubtract)
          Returns a copy of this period with the specified period subtracted.
 PeriodFields multipliedBy(long scalar)
          Returns a copy of this period with each amount in this period multiplied by the specified scalar.
 PeriodFields negated()
          Returns a copy of this period with each amount in this period negated.
 PeriodFields normalized()
          Returns a copy of this period with the amounts normalized.
 PeriodFields normalizedTo(PeriodUnit... units)
          Returns a copy of this period with the amounts normalized to the specified units.
static PeriodFields of(Duration duration)
          Obtains a PeriodFields from a Duration based on the standard durations of seconds and nanoseconds.
static PeriodFields of(java.lang.Iterable<PeriodField> periods)
          Obtains a PeriodFields from an array of single-unit periods.
static PeriodFields of(long amount, PeriodUnit unit)
          Obtains a PeriodFields from an amount and unit.
static PeriodFields of(PeriodField... periods)
          Obtains a PeriodFields from an array of single-unit periods.
static PeriodFields of(PeriodField period)
          Obtains a PeriodFields from a single-unit period.
static PeriodFields of(PeriodProvider periodProvider)
          Obtains a PeriodFields from a PeriodProvider.
static PeriodFields ofTotal(PeriodProvider... periodProviders)
          Obtains a PeriodFields by totalling the amounts in a list of PeriodProvider instances.
 PeriodFields plus(long amountToAdd, PeriodUnit unit)
          Returns a copy of this period with the specified period added.
 PeriodFields plus(PeriodProvider periodToAdd)
          Returns a copy of this period with the specified period added.
 PeriodFields remainder(PeriodField period)
          Returns a copy of this period with the modular division remainder of each field calculated with respect to the specified period.
 PeriodFields retain(PeriodUnit... units)
          Returns a copy of this period with the specified units retained.
 PeriodFields retainConvertible(PeriodUnit... units)
          Returns a copy of this period with only those units that can be converted to the specified units.
 int size()
          Gets the number of fields.
 Duration toDuration()
          Calculates the accurate duration of this period.
 Duration toDurationEstimate()
          Estimates the duration of this period.
 PeriodFields toEquivalent(PeriodUnit... units)
          Converts this period to one containing only the units specified.
 java.util.SortedMap<PeriodUnit,PeriodField> toMap()
          Returns a Map equivalent to this set of fields.
 PeriodFields toPeriodFields()
          Converts this period to a PeriodFields, trivially returning this.
 java.lang.String toString()
          Outputs this set of fields as a String, such as [6 Days, 13 Hours].
 PeriodField toTotal(PeriodUnit unit)
          Totals this period in terms of a single unit.
 PeriodFields with(long amount, PeriodUnit unit)
          Returns a copy of these fields with the specified unit and amount.
 PeriodFields with(PeriodProvider periodProvider)
          Returns a copy of this period with the specified values altered.
 PeriodFields without(PeriodUnit unit)
          Returns a copy of these fields with the specified unit removed.
 PeriodFields withZeroesRemoved()
          Returns a copy of this period with all zero amounts removed.
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
 

Field Detail

ZERO

public static final PeriodFields ZERO
A constant for a period of zero. This constant is independent of any unit.

Method Detail

of

public static PeriodFields of(long amount,
                              PeriodUnit unit)
Obtains a PeriodFields from an amount and unit.

The parameters represent the two parts of a phrase like '6 Days'.

Parameters:
amount - the amount to create with, positive or negative
unit - the period unit, not null
Returns:
the PeriodFields instance, not null

of

public static PeriodFields of(PeriodField period)
Obtains a PeriodFields from a single-unit period.

Parameters:
period - the single-unit period, not null
Returns:
the PeriodFields instance, not null

of

public static PeriodFields of(PeriodField... periods)
Obtains a PeriodFields from an array of single-unit periods.

The period fields must all have different units.

Parameters:
periods - the array of single-unit periods, not null
Returns:
the PeriodFields instance, not null
Throws:
java.lang.IllegalArgumentException - if the same period unit occurs twice

of

public static PeriodFields of(java.lang.Iterable<PeriodField> periods)
Obtains a PeriodFields from an array of single-unit periods.

Parameters:
periods - the array of single-unit periods, not null
Returns:
the PeriodFields instance, not null
Throws:
java.lang.IllegalArgumentException - if the same period unit occurs twice

of

public static PeriodFields of(PeriodProvider periodProvider)
Obtains a PeriodFields from a PeriodProvider.

This method provides null-checking around PeriodProvider.toPeriodFields().

Parameters:
periodProvider - the provider to create from, not null
Returns:
the PeriodFields instance, not null
Throws:
java.lang.NullPointerException - if the period provider is null or returns null

ofTotal

public static PeriodFields ofTotal(PeriodProvider... periodProviders)
Obtains a PeriodFields by totalling the amounts in a list of PeriodProvider instances.

This method returns a period with all the unit-amount pairs from the providers totalled. Thus a period of '2 Months and 5 Days' combined with a period of '7 Days and 21 Hours' will yield a result of '2 Months, 12 Days and 21 Hours'.

Parameters:
periodProviders - the providers to total, not null
Returns:
the PeriodFields instance, not null
Throws:
java.lang.NullPointerException - if any period provider is null or returns null

of

public static PeriodFields of(Duration duration)
Obtains a PeriodFields from a Duration based on the standard durations of seconds and nanoseconds.

The conversion will create an instance with two units - the ISOChronology seconds and nanoseconds units. This matches the toDuration() method.

Parameters:
duration - the duration to create from, not null
Returns:
the PeriodFields instance, not null

isZero

public boolean isZero()
Checks if this period is zero-length.

This checks whether all the amounts in this period are zero.

Returns:
true if this period is zero-length

isPositive

public boolean isPositive()
Checks if this period is fully positive, excluding zero.

This checks whether all the amounts in this period are positive, defined as greater than zero.

Returns:
true if this period is fully positive excluding zero

isPositiveOrZero

public boolean isPositiveOrZero()
Checks if this period is fully positive, including zero.

This checks whether all the amounts in this period are positive, defined as greater than or equal to zero.

Returns:
true if this period is fully positive including zero

size

public int size()
Gets the number of fields.

This method returns the number of stored PeriodField instances.

Returns:
number of unit-amount pairs, zero or greater

iterator

public java.util.Iterator<PeriodField> iterator()
Iterates through all the fields.

This method fulfills the Iterable interface and allows looping around the fields using the for-each loop. The fields are returned sorted in reverse order.

Specified by:
iterator in interface java.lang.Iterable<PeriodField>
Returns:
an iterator over the fields, not null

contains

public boolean contains(PeriodUnit unit)
Checks if this set of fields contains a field with the specified unit.

This method returns true one of the stored PeriodField instances has the specified unit.

Parameters:
unit - the unit to query, null returns false
Returns:
true if this contains a field with the specified unit

getField

public PeriodField getField(PeriodUnit unit)
Gets the stored field for the specified unit.

This method queries the stored PeriodField instances by unit. If no field is found with the specified unit then null is returned.

Parameters:
unit - the unit to query, not null
Returns:
the field with the specified unit, null if not found

getAmount

public long getAmount(PeriodUnit unit)
Gets the amount for the specified unit.

This method queries the stored PeriodField instances by unit returning the amount. If no field is found with the specified unit then zero is returned.

Parameters:
unit - the unit to query, not null
Returns:
the amount from the field with the specified unit, zero if not found

getAmountInt

public int getAmountInt(PeriodUnit unit)
Gets the amount for the specified unit converted to an int.

This method queries the stored PeriodField instances by unit returning the amount. If no field is found with the specified unit then zero is returned.

Parameters:
unit - the unit to query, not null
Returns:
the amount from the field with the specified unit, zero if not found
Throws:
java.lang.ArithmeticException - if the amount is too large to be returned in an int

withZeroesRemoved

public PeriodFields withZeroesRemoved()
Returns a copy of this period with all zero amounts removed.

This instance is immutable and unaffected by this method call.

Returns:
a PeriodFields based on this period with zero amounts removed, not null

with

public PeriodFields with(long amount,
                         PeriodUnit unit)
Returns a copy of these fields with the specified unit and amount.

The result is the set of fields in this instance with the specified field merged as though using Map.put with the unit and amount.

This instance is immutable and unaffected by this method call.

Parameters:
amount - the amount to set in the result, positive or negative
unit - the unit to set in the result, not null
Returns:
a PeriodFields based on this fields with the specified field set, not null

with

public PeriodFields with(PeriodProvider periodProvider)
Returns a copy of this period with the specified values altered.

This method operates on each unit in the input in turn. If this period already contains an amount for the unit then the amount is replaced. Otherwise, the unit-amount pair is added.

For example, '6 Years, 7 Months' with '2 Months 3 Days' will return '6 Years, 2 Months, 3 Days'.

This instance is immutable and unaffected by this method call.

Parameters:
periodProvider - the period to merge over this period, not null
Returns:
a PeriodFields based on this period with the specified period overlaid, not null

without

public PeriodFields without(PeriodUnit unit)
Returns a copy of these fields with the specified unit removed.

The result is the set of fields in this instance with the specified unit removed. No error occurs if the unit is not present.

This instance is immutable and unaffected by this method call.

Parameters:
unit - the unit to remove from the result, not null
Returns:
a PeriodFields based on this fields with the specified unit removed, not null

plus

public PeriodFields plus(PeriodProvider periodToAdd)
Returns a copy of this period with the specified period added.

The returned period will take each unit in the provider and add the value to the amount already stored in this period, returning a new one. If this period does not contain an amount for the unit then the unit and amount are simply returned directly in the result. The result will have the union of the units in this instance and the units in the specified instance.

This instance is immutable and unaffected by this method call.

Parameters:
periodToAdd - the period to add, not null
Returns:
a PeriodFields based on this period with the specified period added, not null
Throws:
java.lang.ArithmeticException - if the calculation overflows

plus

public PeriodFields plus(long amountToAdd,
                         PeriodUnit unit)
Returns a copy of this period with the specified period added.

The result will contain the units and amounts from this period plus the specified unit and amount. The specified unit will always be in the result even if the amount is zero.

This instance is immutable and unaffected by this method call.

Parameters:
amountToAdd - the amount to add, measured in the specified unit, positive or negative
unit - the unit defining the amount, not null
Returns:
a PeriodFields based on this period with the specified period added, not null
Throws:
java.lang.ArithmeticException - if the calculation overflows

minus

public PeriodFields minus(PeriodProvider periodToSubtract)
Returns a copy of this period with the specified period subtracted.

The returned period will take each unit in the provider and subtract the value from the amount already stored in this period, returning a new one. If this period does not contain an amount for the unit then the unit and amount are simply returned directly in the result. The result will have the union of the units in this instance and the units in the specified instance.

This instance is immutable and unaffected by this method call.

Parameters:
periodToSubtract - the period to subtract, not null
Returns:
a PeriodFields based on this period with the specified period subtracted, not null
Throws:
java.lang.ArithmeticException - if the calculation overflows

minus

public PeriodFields minus(long amountToSubtract,
                          PeriodUnit unit)
Returns a copy of this period with the specified period subtracted.

The result will contain the units and amounts from this period minus the specified unit and amount. The specified unit will always be in the result even if the amount is zero.

This instance is immutable and unaffected by this method call.

Parameters:
amountToSubtract - the amount to subtract, measured in the specified unit, positive or negative
unit - the unit defining the amount, not null
Returns:
a PeriodFields based on this period with the specified period subtracted, not null
Throws:
java.lang.ArithmeticException - if the calculation overflows

multipliedBy

public PeriodFields multipliedBy(long scalar)
Returns a copy of this period with each amount in this period multiplied by the specified scalar.

Parameters:
scalar - the scalar to multiply by, not null
Returns:
a PeriodFields based on this period with the amounts multiplied by the scalar, not null
Throws:
java.lang.ArithmeticException - if the calculation overflows

dividedBy

public PeriodFields dividedBy(long divisor)
Returns a copy of this period with each amount in this period divided by the specified value.

Parameters:
divisor - the value to divide by, not null, not zero
Returns:
a PeriodFields based on this period with the amounts divided by the divisor, not null
Throws:
java.lang.ArithmeticException - if dividing by zero

negated

public PeriodFields negated()
Returns a copy of this period with each amount in this period negated.

Returns:
a PeriodFields based on this period with the amounts negated, not null
Throws:
java.lang.ArithmeticException - if the calculation overflows

retain

public PeriodFields retain(PeriodUnit... units)
Returns a copy of this period with the specified units retained.

This method will return a new period that only has the specified units. All units not present in the input will not be present in the result. In most cases, the result will not be equivalent to this period.

This instance is immutable and unaffected by this method call.

Parameters:
units - the units to retain, not altered, not null, no nulls
Returns:
a PeriodFields based on this period with the specified units retained, not null

retainConvertible

public PeriodFields retainConvertible(PeriodUnit... units)
Returns a copy of this period with only those units that can be converted to the specified units.

This method will return a new period where every field can be converted to one of the specified units. In the result, each of the retained periods will have the same amount as they do in this period - no conversion or normalization occurs.

For example, if this period is '2 Days, 5 Hours, 7 Minutes' and the specified unit array contains 'Seconds' then the output will be '5 Hours, 7 Minutes'. The 'Days' unit is not retained as it cannot be converted to 'Seconds'.

This instance is immutable and unaffected by this method call.

Parameters:
units - the units to retain, not altered, not null, no nulls
Returns:
a PeriodFields based on this period with the specified units retained, not null

remainder

public PeriodFields remainder(PeriodField period)
Returns a copy of this period with the modular division remainder of each field calculated with respect to the specified period.

This method will return a new period where every field represents a period less than the specified period. If this period contains a period that cannot be converted to the specified unit then an exception is thrown.

For example, if this period is '37 Hours, 7 Minutes' and the specified period is '24 Hours' then the output will be '13 Hours, 7 Minutes'.

This method requires this period to be convertible to the specified period. To ensure this is true, call retainConvertible(javax.time.calendar.PeriodUnit...), with the base unit of the period passed into this method, before calling this method.

This instance is immutable and unaffected by this method call.

Parameters:
period - the period to calculate the remainder against, not null
Returns:
a PeriodFields based on this period with the remainder, not null
Throws:
CalendricalException - if any field cannot be converted to the unit of the period

normalized

public PeriodFields normalized()
Returns a copy of this period with the amounts normalized.

This will normalize the period around the units in this period. For example, a period of '2 Years, 14 Months, 6 Hours, -7 Minutes' will be normalized to '3 Years, 2 Months, 5 Hours, 53 Minutes'. See normalizedTo(javax.time.calendar.PeriodUnit...) for details of the algorithm.

Returns:
a period equivalent to this period with the amounts normalized, not null
Throws:
java.lang.ArithmeticException - if the calculation overflows

normalizedTo

public PeriodFields normalizedTo(PeriodUnit... units)
Returns a copy of this period with the amounts normalized to the specified units.

This will normalize the period around the specified units. The calculation normalizes amounts within groups of units that share a common base unit. For example, hours, minutes and seconds share a base unit or nanoseconds, while years and months share a base unit of months. Thus, normalization will occur between hours and minutes, but not between hours and months.

Normalization ensures that within any group of units with a common base, the smaller units will all have values between zero and that of the next larger unit. For example, a period of '2 Decades, 2 Years, 17 Months' normalized using 'Years' and 'Months' will return '23 Years, 5 Months', because months must be between 0 and 11 (inclusive).

After this method completes, negative values will have been moved to the largest unit in the group. For example, a period of '6 Hours, -7 Minutes' normalized using 'Hours' and 'Minutes' will return '5 Hours, 53 Minutes'.

At least one unit must be specified for this method to make any changes. Any part of this period that cannot be converted to one of the specified units will be unaffected in the result. The result will always contain all the specified units, even if they are zero. The result will be equivalent to this period.

Parameters:
units - the unit array to normalize to, not altered, not null, no nulls
Returns:
a period equivalent to this period with the amounts normalized, not null
Throws:
java.lang.ArithmeticException - if the calculation overflows

toTotal

public PeriodField toTotal(PeriodUnit unit)
Totals this period in terms of a single unit.

This will take each of the stored PeriodField instances and convert them to the specified unit. The result will be the total of these converted periods.

For example, '3 Hours, 34 Minutes' can be totalled to minutes resulting in '214 Minutes'.

Parameters:
unit - the unit to total in, not null
Returns:
a period equivalent to the total of this period in a single unit, not null
Throws:
CalendricalException - if this period cannot be converted to the unit
java.lang.ArithmeticException - if the calculation overflows

toEquivalent

public PeriodFields toEquivalent(PeriodUnit... units)
Converts this period to one containing only the units specified.

This converts this period to one measured in the specified units. It operates by looping through the individual parts of this period, converting each in turn to one of the specified units. These converted periods are then combined to form the result.

No normalization is performed on the result. This means that an amount in a smaller unit cannot be converted to an amount in a larger unit. If you need to do this, call normalized() before calling this method.

This method uses PeriodField.toEquivalent(PeriodUnit...) and as such, it is recommended to specify the units from largest to smallest.

For example, '3 Hours' can normally be converted to both minutes and seconds. If the units array contains both 'Minutes' and 'Seconds', then the result will be measured in whichever is first in the array.

Parameters:
units - the required unit array, not altered, not null, no nulls
Returns:
a period equivalent to this period, not null
Throws:
CalendricalException - if this period cannot be converted to any of the units
java.lang.ArithmeticException - if the calculation overflows

toDurationEstimate

public Duration toDurationEstimate()
Estimates the duration of this period.

Each PeriodUnit contains an estimated duration for that unit. The per-unit estimate allows an estimate to be calculated for the whole period including fields of variable duration. The estimate will equal the accurate calculation if all the fields are based on seconds.

Returns:
the estimated duration of this period, not null
Throws:
java.lang.ArithmeticException - if the calculation overflows

toDuration

public Duration toDuration()
Calculates the accurate duration of this period.

The conversion is based on the ISOChronology definition of the seconds and nanoseconds units. If all the fields in this period can be converted to either seconds or nanoseconds then the conversion will succeed, subject to calculation overflow. If any field cannot be converted to these fields above then an exception is thrown.

Returns:
the duration of this period based on ISOChronology fields, not null
Throws:
CalendricalException - if this period cannot be converted to an exact duration
java.lang.ArithmeticException - if the calculation overflows

toMap

public java.util.SortedMap<PeriodUnit,PeriodField> toMap()
Returns a Map equivalent to this set of fields.

The map will connect the unit to the single field period. The sort order is from largest unit to smallest unit.

Returns:
the map equivalent to this period, unmodifiable, not null

toPeriodFields

public PeriodFields toPeriodFields()
Converts this period to a PeriodFields, trivially returning this.

Specified by:
toPeriodFields in interface PeriodProvider
Returns:
this, not null

equals

public boolean equals(java.lang.Object obj)
Checks if this set of fields is equal to another set of fields.

The comparison is based on the complete set of fields.

Overrides:
equals in class java.lang.Object
Parameters:
obj - the object to check, null returns false
Returns:
true if this is equal to the other set of fields

hashCode

public int hashCode()
A hash code for this set of fields.

Overrides:
hashCode in class java.lang.Object
Returns:
a suitable hash code

toString

public java.lang.String toString()
Outputs this set of fields as a String, such as [6 Days, 13 Hours].

The output will include of the complete set of fields.

Overrides:
toString in class java.lang.Object
Returns:
a string representation of this set of fields, not null