Class CalendricalRule<T>
- Type Parameters:
T
- the underlying type representing the data, typically aCalendrical
,Number
orEnum
, must be immutable, should be comparable
- All Implemented Interfaces:
Serializable
,Comparable<CalendricalRule<?>>
,Comparator<Calendrical>
- Direct Known Subclasses:
Chronology.Rule
,CopticDate.Rule
,DateTimeFieldRule
,HistoricDate.Rule
,ISOChronology.EpochDaysRule
,ISOChronology.NanoOfDayRule
,LocalDate.Rule
,LocalDateTime.Rule
,LocalTime.Rule
,MonthDay.Rule
,OffsetDate.Rule
,OffsetDateTime.Rule
,OffsetTime.Rule
,TimeZone.Rule
,YearMonth.Rule
,ZonedDateTime.Rule
,ZoneOffset.Rule
Calendrical rules may define fields like day-of-month, combinations like date-time, or other related types like time-zone.
Each rule uses an underlying type to represent the data.
This is captured in the generic type of the rule.
The underlying type is reified and made available via getReifiedType()
.
It is expected, but not enforced, that the underlying type is Comparable
.
CalendricalRule is an abstract class and must be implemented with care to ensure other classes in the framework operate correctly. All instantiable subclasses must be final, immutable and thread-safe and must ensure serialization works correctly.
- See Also:
-
Field Summary
FieldsModifier and TypeFieldDescriptionprivate final Chronology
The chronology of the rule, not null.private final String
The id of the rule, not null.private final String
The name of the rule, not null.private final PeriodUnit
The period range, not null.private final PeriodUnit
The period unit, not null.The reified class for the generic type.private static final long
A serialization identifier for this class. -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotected
CalendricalRule
(Class<T> reifiedClass, Chronology chronology, String name, PeriodUnit periodUnit, PeriodUnit periodRange) Constructor used to create a rule. -
Method Summary
Modifier and TypeMethodDescriptionint
compare
(Calendrical cal1, Calendrical cal2) Compares twoCalendrical
implementations based on the value of this rule extracted from each calendrical.int
compareTo
(CalendricalRule<?> other) Compares thisCalendricalRule
to another.protected T
derive
(Calendrical calendrical) Derives the value of this rule from a calendrical.final <R> R
deriveValueFor
(CalendricalRule<R> rule, T value, Calendrical calendrical, Chronology chronology) Derives the value of the specified rule from a calendrical.final T
deriveValueFrom
(Calendrical calendrical) Derives the value of this rule from a calendrical.boolean
Compares two rules based on their ID.final Chronology
Gets the chronology of the rule.final String
getID()
Gets the ID of the rule.final String
getName()
Gets the name of the rule.Gets the range that the rule is bound by.Gets the unit that the rule is measured in.Gets the reified class representing the underlying type of the rule.final T
getValue
(Calendrical calendrical) Gets the value of this rule from the specified calendrical returningnull
if the value cannot be returned.final T
getValueChecked
(Calendrical calendrical) Gets the value of the rule from the specified calendrical throwing an exception if the rule cannot be returned.int
hashCode()
Returns a hash code based on the ID.protected T
interpret
(CalendricalMerger merger, Object value) Interprets the specified value converting it into an in range value of the correct type for this rule.(package private) final T
interpretValue
(CalendricalMerger merger, Object value) Interprets the specified value converting it into an in range value of the correct type for this rule.protected void
merge
(CalendricalMerger merger) Merges this field with other fields to form higher level fields.final T
Returns the input value cast to the correct generic type.toString()
Returns a string representation of the rule.Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
Methods inherited from interface java.util.Comparator
reversed, thenComparing, thenComparing, thenComparing, thenComparingDouble, thenComparingInt, thenComparingLong
-
Field Details
-
serialVersionUID
private static final long serialVersionUIDA serialization identifier for this class.- See Also:
-
reified
The reified class for the generic type. -
chronology
The chronology of the rule, not null. -
id
The id of the rule, not null. -
name
The name of the rule, not null. -
periodUnit
The period unit, not null. -
periodRange
The period range, not null.
-
-
Constructor Details
-
CalendricalRule
protected CalendricalRule(Class<T> reifiedClass, Chronology chronology, String name, PeriodUnit periodUnit, PeriodUnit periodRange) Constructor used to create a rule.- Parameters:
reifiedClass
- the reified class, not nullchronology
- the chronology, not nullname
- the name of the type, not nullperiodUnit
- the period unit, may be nullperiodRange
- the period range, may be null
-
-
Method Details
-
getChronology
Gets the chronology of the rule.- Returns:
- the chronology of the rule, never null
-
getID
Gets the ID of the rule.The ID is of the form 'ChronologyName.RuleName'. No two fields should have the same ID.
- Returns:
- the ID of the rule, never null
-
getName
Gets the name of the rule.Implementations should use the name that best represents themselves. If the rule represents a field, then the form 'UnitOfRange' should be used. Otherwise, use the simple class name of the generic type, such as 'ZoneOffset'.
- Returns:
- the name of the rule, never null
-
getPeriodUnit
Gets the unit that the rule is measured in.Most rules define a field such as 'hour of day' or 'month of year'. The unit is the period that varies within the range.
For example, the rule for hour-of-day will return Hours, while the rule for month-of-year will return Months. The rule for a date will return Days as a date could alternately be described as 'days of forever'.
The
null
value is returned if the rule is not defined by a unit and range.- Returns:
- the unit defining the rule unit, null if this rule isn't based on a period
-
getPeriodRange
Gets the range that the rule is bound by.Most rules define a field such as 'hour of day' or 'month of year'. The range is the period that the field varies within.
For example, the rule for hour-of-day will return Days, while the rule for month-of-year will return Years.
When the range is unbounded, such as for a date or the year field, then
null
will be returned. Thenull
value is also returned if the rule is not defined by a unit and range.- Returns:
- the unit defining the rule range, null if unbounded, or if this rule isn't based on a period
-
getReifiedType
Gets the reified class representing the underlying type of the rule.Each rule uses an underlying type to represent the data. This is captured in the generic type of the rule. Since the generic implementation is Java is limited to the compiler, the underlying type has been reified and made available through this method. It is expected, but not enforced, that the underlying type is
Comparable
.- Returns:
- the reified type of values of the rule, never null
-
reify
Returns the input value cast to the correct generic type.Each rule uses an underlying type to represent the data. This is captured in the generic type of the rule. Since the generic implementation is Java is limited to the compiler, the underlying type has been reified which allows this method to validate the generic type fully. The implementation simply returns the input value typed as the generic type.
- Parameters:
value
- the value to reify, may be null- Returns:
- the type-cast input value, may be null
- Throws:
ClassCastException
- if the value is not of the reified type
-
getValue
Gets the value of this rule from the specified calendrical returningnull
if the value cannot be returned.This method simply queries the calendrical.
- Parameters:
calendrical
- the calendrical to get the field value from, not null- Returns:
- the value of the field, null if unable to extract the field
-
getValueChecked
Gets the value of the rule from the specified calendrical throwing an exception if the rule cannot be returned.This convenience method uses
getValue(Calendrical)
to find the value and then ensures it isn'tnull
.- Parameters:
calendrical
- the calendrical to get the field value from, not null- Returns:
- the value of the field, never null
- Throws:
UnsupportedRuleException
- if the rule cannot be extracted
-
deriveValueFor
public final <R> R deriveValueFor(CalendricalRule<R> rule, T value, Calendrical calendrical, Chronology chronology) Derives the value of the specified rule from a calendrical.This method is provided for implementations of
Calendrical.get(javax.time.calendar.CalendricalRule<T>)
and is rarely called directly by application code. It is used when the calendrical has its own rule, and this method is called on the rule of the calendrical implementation, not the rule passed into theget
method.public
The last parameter in the code snippet above is alwaysT get(CalendricalRule rule) { return IMPLEMENTATION_RULE.deriveValueFor(rule, this, this); } this
, however the second parameter may be a different representation, for example inYear.get(javax.time.calendar.CalendricalRule<T>)
.If this rule and the specified rule are the same, then the value is returned. Otherwise, an attempt is made to
derive(javax.time.calendar.Calendrical)
the field value.- Parameters:
rule
- the rule to retrieve, not nullvalue
- the value to return if this rule is the specified rule, not nullcalendrical
- the calendrical to get the value from, not nullchronology
- the chronology the value belongs to, null if chronology neutral- Returns:
- the value, null if unable to derive the value
-
deriveValueFrom
Derives the value of this rule from a calendrical.This method is provided for implementations of
Calendrical.get(javax.time.calendar.CalendricalRule<T>)
and is rarely called directly by application code. It is used when the calendrical has its own values but does not have its own rule.public
T get(CalendricalRule rule) { // return data, for example if (rule.equals(...)) { return valueForRule; } // call this method return rule.deriveValueFrom(this); } - Parameters:
calendrical
- the calendrical to get the value from, not null- Returns:
- the value, null if unable to derive the value
-
derive
Derives the value of this rule from a calendrical.This method derives the value for this field from other fields in the calendrical without directly querying the calendrical for the value.
For example, if this field is quarter-of-year, then the value can be derived from month-of-year.
The implementation only needs to derive the value based on its immediate parents. The use of
Calendrical.get(javax.time.calendar.CalendricalRule<T>)
will extract any further parents on demand.A typical implementation of this method obtains the parent value and performs a calculation. For example, here is a simple implementation for the quarter-of-year field:
Integer moyVal = calendrical.get(ISOChronology.monthOfYearRule()); return (moyVal != null ? ((moyVal - 1) % 4) + 1) : null;
This method is designed to be overridden in subclasses. The subclass implementation must be thread-safe. The subclass implementation must not request the value of this rule from the specified calendrical, otherwise a stack overflow error will occur.
- Parameters:
calendrical
- the calendrical to derive from, not null- Returns:
- the derived value, null if unable to derive
-
interpretValue
Interprets the specified value converting it into an in range value of the correct type for this rule.- Parameters:
merger
- the merger instance controlling the merge process, not nullvalue
- the value to interpret, not null
-
interpret
Interprets the specified value converting it into an in range value of the correct type for this rule.Before this method is called, the value will be checked to ensure it is not of the type of this rule.
- Parameters:
merger
- the merger instance controlling the merge process, not nullvalue
- the value to interpret, null if unable to interpret the value- Returns:
- the interpreted value
-
merge
Merges this field with other fields to form higher level fields.The aim of this method is to assist in the process of extracting the most date-time information possible from a map of field-value pairs. The merging process is controlled by the mutable merger instance and the input and output of the this merge are held there.
Subclasses that override this method may use methods on the merger to obtain the values to merge. The value is guaranteed to be available for this field if this method is called.
If the override successfully merged some fields then the following must be performed. The merged field must be stored using
CalendricalMerger.storeMerged(javax.time.calendar.CalendricalRule<T>, T)
. Each field used in the merge must be marked as being used by callingCalendricalMerger.removeProcessed(javax.time.calendar.CalendricalRule<?>)
.An example to merge two fields into one - hour of AM/PM and AM/PM:
Integer hapVal = merger.getValue(ISOChronology.hourOfAmPmRule()); if (hapVal != null) { AmPmOfDay amPm = merger.getValue(this); int hourOfDay = MathUtils.safeAdd(MathUtils.safeMultiply(amPm, 12), hapVal); merger.storeMerged(ISOChronology.hourOfDayRule(), hourOfDay); merger.removeProcessed(this); merger.removeProcessed(ISOChronology.hourOfAmPmRule()); }
- Parameters:
merger
- the merger instance controlling the merge process, not null
-
compare
Compares twoCalendrical
implementations based on the value of this rule extracted from each calendrical.This implements the
Comparator
interface and allows any twoCalendrical
implementations to be compared using this rule. The comparison is based on the result of callingCalendrical.get(javax.time.calendar.CalendricalRule<T>)
on each calendrical, and comparing those values.For example, to sort a list into year order when the list may contain any mixture of calendricals, such as a
LocalDate
,YearMonth
andZonedDateTime
:List
If the value of this rule cannot be obtained from a calendrical, then an exception is thrown.list = ... Collections.sort(list, ISOChronology.yearRule()); If the underlying type of this rule does not implement
Comparable
then an exception will be thrown.- Specified by:
compare
in interfaceComparator<T>
- Parameters:
cal1
- the first calendrical to compare, not nullcal2
- the second calendrical to compare, not null- Returns:
- the comparator result, negative if first is less, positive if first is greater, zero if equal
- Throws:
NullPointerException
- if either input is nullClassCastException
- if this rule has a type that is not comparableIllegalArgumentException
- if this rule cannot be extracted from either input parameter
-
compareTo
Compares thisCalendricalRule
to another.The comparison is based on the period unit followed by the period range followed by the rule ID. The period unit is compared first, so MinuteOfHour will be less than HourOfDay, which will be less than DayOfWeek. When the period unit is the same, the period range is compared, so DayOfWeek is less than DayOfMonth, which is less than DayOfYear. Finally, the rule ID is compared.
- Specified by:
compareTo
in interfaceComparable<T>
- Parameters:
other
- the other type to compare to, not null- Returns:
- the comparator result, negative if less, positive if greater, zero if equal
- Throws:
NullPointerException
- if other is null
-
equals
Compares two rules based on their ID.- Specified by:
equals
in interfaceComparator<T>
- Overrides:
equals
in classObject
- Returns:
- true if the rules are the same
-
hashCode
public int hashCode()Returns a hash code based on the ID. -
toString
Returns a string representation of the rule.
-