Class PeriodFields

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

public final class PeriodFields extends Object implements PeriodProvider, Iterable<PeriodField>, 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.

See Also:
  • Field Details

    • ZERO

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

      private static final long serialVersionUID
      The serialization version.
      See Also:
    • unitFieldMap

      private final TreeMap<PeriodUnit,PeriodField> unitFieldMap
      The map of periods.
  • Constructor Details

    • PeriodFields

      private PeriodFields(TreeMap<PeriodUnit,PeriodField> periodMap)
      Constructs an instance using a pre-built map. The map must not be used by the calling code after calling the constructor.
      Parameters:
      periodMap - the map of periods to represent, not null and safe to assign
  • Method Details

    • 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 of create with, positive or negative
      unit - the period unit, not null
      Returns:
      the PeriodFields instance, never 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, never 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, never null
      Throws:
      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, never null
      Throws:
      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, never null
      Throws:
      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, never null
    • createMap

      private static TreeMap<PeriodUnit,PeriodField> createMap()
      Creates a new empty map.
      Returns:
      ordered representation of internal map
    • create

      static PeriodFields create(TreeMap<PeriodUnit,PeriodField> periodMap)
      Internal factory to create an instance using a pre-built map. The map must not be used by the calling code after calling the constructor.
      Parameters:
      periodMap - the unit-amount map, not null, assigned not cloned
      Returns:
      the created period, never null
    • checkNotNull

      static void checkNotNull(Object object, String errorMessage)
      Validates that the input value is not null.
      Parameters:
      object - the object to check
      errorMessage - the error to throw
      Throws:
      NullPointerException - if the object is null
    • readResolve

      private Object readResolve()
      Resolves singletons.
      Returns:
      the resolved instance
    • 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()
      Returns the size of the set of units in this period.

      This returns the number of different units that are stored.

      Returns:
      number of unit-amount pairs
    • iterator

      public Iterator<PeriodField> iterator()
      Iterates through all the single-unit periods in this period.

      This method fulfills the Iterable interface and allows looping around the contained single-unit periods using the for-each loop.

      Specified by:
      iterator in interface Iterable<PeriodField>
      Returns:
      an iterator over the single-unit periods in this period, never null
    • contains

      public boolean contains(PeriodUnit unit)
      Checks whether this period contains an amount for the unit.
      Parameters:
      unit - the unit to query, null returns false
      Returns:
      true if the map contains an amount for the unit
    • get

      public PeriodField get(PeriodUnit unit)
      Gets the period for the specified unit.

      This method allows the period to be queried by unit, like a map. If the unit is not found then null is returned.

      Parameters:
      unit - the unit to query, not null
      Returns:
      the period, null if no period stored for the unit
    • getAmount

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

      This method allows the amount to be queried by unit, like a map. If the unit is not found then zero is returned.

      Parameters:
      unit - the unit to query, not null
      Returns:
      the period amount, 0 if no period stored for the unit
      Throws:
      CalendricalException - if there is no amount for the unit
    • getAmountInt

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

      This method allows the amount to be queried by unit, like a map. If the unit is not found then zero is returned.

      Parameters:
      unit - the unit to query, not null
      Returns:
      the period amount, 0 if no period stored for the unit
      Throws:
      CalendricalException - if there is no amount for the unit
      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, never null
    • with

      public PeriodFields with(long amount, PeriodUnit unit)
      Returns a copy of this period with the specified amount for the unit.

      If this period already contains an amount for the unit then the amount is replaced. Otherwise, the unit-amount pair is added.

      This instance is immutable and unaffected by this method call.

      Parameters:
      amount - the amount to store in terms of the unit, positive or negative
      unit - the unit to store not null
      Returns:
      a PeriodFields based on this period with the specified period overlaid, never 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, never null
    • without

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

      If this period already contains an amount for the unit then the amount is removed. Otherwise, no action occurs.

      This instance is immutable and unaffected by this method call.

      Parameters:
      unit - the unit to remove, not null
      Returns:
      a PeriodFields based on this period with the specified unit removed, never null
    • plus

      public PeriodFields plus(PeriodProvider periodProvider)
      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:
      periodProvider - the period to add, not null
      Returns:
      a PeriodFields based on this period with the specified period added, never null
      Throws:
      ArithmeticException - if the calculation overflows
    • plus

      public PeriodFields plus(long amount, 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:
      amount - 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, never null
      Throws:
      ArithmeticException - if the calculation overflows
    • minus

      public PeriodFields minus(PeriodProvider periodProvider)
      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:
      periodProvider - the period to subtract, not null
      Returns:
      a PeriodFields based on this period with the specified period subtracted, never null
      Throws:
      ArithmeticException - if the calculation overflows
    • minus

      public PeriodFields minus(long amount, 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:
      amount - 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, never null
      Throws:
      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, never null
      Throws:
      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, never null
      Throws:
      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, never null
      Throws:
      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, never 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, never 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, never 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.

      The calculation examines each pair of units in this period that have a fixed conversion factor. Each pair is adjusted so that the amount in the smaller unit does not exceed the amount of the fixed conversion factor.

      For example, a period of '2 Decades, 2 Years, 17 Months' normalized using 'Years' and 'Months' will return '23 Years, 5 Months'.

      The result will always contain all the units present in this period, even if they are zero. The result will be equivalent to this period.

      Returns:
      a period equivalent to this period with the amounts normalized, never null
      Throws:
      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 examines each pair of units that have a fixed conversion factor. Each pair is adjusted so that the amount in the smaller unit does not exceed the amount of the fixed conversion factor. At least one unit must be specified for this method to have any effect.

      For example, a period of '2 Decades, 2 Years, 17 Months' normalized using 'Years' and 'Months' will return '23 Years, 5 Months'.

      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, never null
      Throws:
      ArithmeticException - if the calculation overflows
    • clonedMap

      private TreeMap<PeriodUnit,PeriodField> clonedMap()
      Clone the internal data storage map.
      Returns:
      the cloned map, never null
    • 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, never null
      Throws:
      CalendricalException - if this period cannot be converted to the unit
      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, never null
      Throws:
      CalendricalException - if this period cannot be converted to any of the units
      ArithmeticException - if the calculation overflows
    • toEstimatedDuration

      public Duration toEstimatedDuration()
      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, never null
      Throws:
      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, never null
      Throws:
      ArithmeticException - if the calculation overflows
    • toMap

      public SortedMap<PeriodUnit,PeriodField> toMap()
      Returns a Map equivalent to this period.

      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, never null
    • toPeriodFields

      public PeriodFields toPeriodFields()
      Converts this period to a PeriodFields, trivially returning this.
      Specified by:
      toPeriodFields in interface PeriodProvider
      Returns:
      this, never null
    • equals

      public boolean equals(Object obj)
      Checks if this instance equal to the specified period.

      Two PeriodFields instances are equal if all the contained PeriodField instances are equal.

      Overrides:
      equals in class Object
      Parameters:
      obj - the other period to compare to, null returns false
      Returns:
      true if this instance is equal to the specified period
    • hashCode

      public int hashCode()
      Returns the hash code for this period.
      Overrides:
      hashCode in class Object
      Returns:
      a suitable hash code
    • toString

      public String toString()
      Returns a string representation of the period, such as '[6 Days, 13 Hours]'.
      Overrides:
      toString in class Object
      Returns:
      a descriptive representation of the period, not null