001/* 002 * Copyright (c) 2007-2013, Stephen Colebourne & Michael Nascimento Santos 003 * 004 * All rights reserved. 005 * 006 * Redistribution and use in source and binary forms, with or without 007 * modification, are permitted provided that the following conditions are met: 008 * 009 * * Redistributions of source code must retain the above copyright notice, 010 * this list of conditions and the following disclaimer. 011 * 012 * * Redistributions in binary form must reproduce the above copyright notice, 013 * this list of conditions and the following disclaimer in the documentation 014 * and/or other materials provided with the distribution. 015 * 016 * * Neither the name of JSR-310 nor the names of its contributors 017 * may be used to endorse or promote products derived from this software 018 * without specific prior written permission. 019 * 020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 021 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 022 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 023 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 024 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 026 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 027 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 028 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 029 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 031 */ 032package org.threeten.bp.temporal; 033 034import java.util.Comparator; 035 036import org.threeten.bp.DateTimeException; 037import org.threeten.bp.format.DateTimeBuilder; 038 039/** 040 * A field of date-time, such as month-of-year or hour-of-minute. 041 * <p> 042 * Date and time is expressed using fields which partition the time-line into something 043 * meaningful for humans. Implementations of this interface represent those fields. 044 * <p> 045 * The most commonly used units are defined in {@link ChronoField}. 046 * Further fields are supplied in {@link ISOFields}, {@link WeekFields} and {@link JulianFields}. 047 * Fields can also be written by application code by implementing this interface. 048 * <p> 049 * The field works using double dispatch. Client code calls methods on a date-time like 050 * {@code LocalDateTime} which check if the field is a {@code ChronoField}. 051 * If it is, then the date-time must handle it. 052 * Otherwise, the method call is re-dispatched to the matching method in this interface. 053 * 054 * <h3>Specification for implementors</h3> 055 * This interface must be implemented with care to ensure other classes operate correctly. 056 * All implementations that can be instantiated must be final, immutable and thread-safe. 057 * It is recommended to use an enum where possible. 058 */ 059public interface TemporalField extends Comparator<TemporalAccessor> { 060 061 /** 062 * Gets a descriptive name for the field. 063 * <p> 064 * The should be of the format 'BaseOfRange', such as 'MonthOfYear', 065 * unless the field has a range of {@code FOREVER}, when only 066 * the base unit is mentioned, such as 'Year' or 'Era'. 067 * 068 * @return the name, not null 069 */ 070 String getName(); 071 072 /** 073 * Gets the unit that the field is measured in. 074 * <p> 075 * The unit of the field is the period that varies within the range. 076 * For example, in the field 'MonthOfYear', the unit is 'Months'. 077 * See also {@link #getRangeUnit()}. 078 * 079 * @return the period unit defining the base unit of the field, not null 080 */ 081 TemporalUnit getBaseUnit(); 082 083 /** 084 * Gets the range that the field is bound by. 085 * <p> 086 * The range of the field is the period that the field varies within. 087 * For example, in the field 'MonthOfYear', the range is 'Years'. 088 * See also {@link #getBaseUnit()}. 089 * <p> 090 * The range is never null. For example, the 'Year' field is shorthand for 091 * 'YearOfForever'. It therefore has a unit of 'Years' and a range of 'Forever'. 092 * 093 * @return the period unit defining the range of the field, not null 094 */ 095 TemporalUnit getRangeUnit(); 096 097 //----------------------------------------------------------------------- 098 /** 099 * Compares the value of this field in two temporal objects. 100 * <p> 101 * All fields implement {@link Comparator} on {@link TemporalAccessor}. 102 * This allows a list of date-times to be compared using the value of a field. 103 * For example, you could sort a list of arbitrary temporal objects by the value of 104 * the month-of-year field - {@code Collections.sort(list, MONTH_OF_YEAR)} 105 * 106 * @param temporal1 the first temporal object to compare, not null 107 * @param temporal2 the second temporal object to compare, not null 108 * @throws DateTimeException if unable to obtain the value for this field 109 */ 110 int compare(TemporalAccessor temporal1, TemporalAccessor temporal2); 111 112 /** 113 * Gets the range of valid values for the field. 114 * <p> 115 * All fields can be expressed as a {@code long} integer. 116 * This method returns an object that describes the valid range for that value. 117 * This method is generally only applicable to the ISO-8601 calendar system. 118 * <p> 119 * Note that the result only describes the minimum and maximum valid values 120 * and it is important not to read too much into them. For example, there 121 * could be values within the range that are invalid for the field. 122 * 123 * @return the range of valid values for the field, not null 124 */ 125 ValueRange range(); 126 127 //----------------------------------------------------------------------- 128 /** 129 * Checks if this field is supported by the temporal object. 130 * <p> 131 * This determines whether the temporal accessor supports this field. 132 * If this returns false, the the temporal cannot be queried for this field. 133 * <p> 134 * There are two equivalent ways of using this method. 135 * The first is to invoke this method directly. 136 * The second is to use {@link TemporalAccessor#isSupported(TemporalField)}: 137 * <pre> 138 * // these two lines are equivalent, but the second approach is recommended 139 * temporal = thisField.doIsSupported(temporal); 140 * temporal = temporal.isSupported(thisField); 141 * </pre> 142 * It is recommended to use the second approach, {@code isSupported(TemporalField)}, 143 * as it is a lot clearer to read in code. 144 * <p> 145 * Implementations should determine whether they are supported using the fields 146 * available in {@link ChronoField}. 147 * 148 * @param temporal the temporal object to query, not null 149 * @return true if the date-time can be queried for this field, false if not 150 */ 151 boolean doIsSupported(TemporalAccessor temporal); 152 153 /** 154 * Get the range of valid values for this field using the temporal object to 155 * refine the result. 156 * <p> 157 * This uses the temporal object to find the range of valid values for the field. 158 * This is similar to {@link #range()}, however this method refines the result 159 * using the temporal. For example, if the field is {@code DAY_OF_MONTH} the 160 * {@code range} method is not accurate as there are four possible month lengths, 161 * 28, 29, 30 and 31 days. Using this method with a date allows the range to be 162 * accurate, returning just one of those four options. 163 * <p> 164 * There are two equivalent ways of using this method. 165 * The first is to invoke this method directly. 166 * The second is to use {@link TemporalAccessor#range(TemporalField)}: 167 * <pre> 168 * // these two lines are equivalent, but the second approach is recommended 169 * temporal = thisField.doRange(temporal); 170 * temporal = temporal.range(thisField); 171 * </pre> 172 * It is recommended to use the second approach, {@code range(TemporalField)}, 173 * as it is a lot clearer to read in code. 174 * <p> 175 * Implementations should perform any queries or calculations using the fields 176 * available in {@link ChronoField}. 177 * If the field is not supported a {@code DateTimeException} must be thrown. 178 * 179 * @param temporal the temporal object used to refine the result, not null 180 * @return the range of valid values for this field, not null 181 * @throws DateTimeException if the range for the field cannot be obtained 182 */ 183 ValueRange doRange(TemporalAccessor temporal); 184 185 /** 186 * Gets the value of this field from the specified temporal object. 187 * <p> 188 * This queries the temporal object for the value of this field. 189 * <p> 190 * There are two equivalent ways of using this method. 191 * The first is to invoke this method directly. 192 * The second is to use {@link TemporalAccessor#getLong(TemporalField)} 193 * (or {@link TemporalAccessor#get(TemporalField)}): 194 * <pre> 195 * // these two lines are equivalent, but the second approach is recommended 196 * temporal = thisField.doGet(temporal); 197 * temporal = temporal.getLong(thisField); 198 * </pre> 199 * It is recommended to use the second approach, {@code getLong(TemporalField)}, 200 * as it is a lot clearer to read in code. 201 * <p> 202 * Implementations should perform any queries or calculations using the fields 203 * available in {@link ChronoField}. 204 * If the field is not supported a {@code DateTimeException} must be thrown. 205 * 206 * @param temporal the temporal object to query, not null 207 * @return the value of this field, not null 208 * @throws DateTimeException if a value for the field cannot be obtained 209 */ 210 long doGet(TemporalAccessor temporal); 211 212 /** 213 * Returns a copy of the specified temporal object with the value of this field set. 214 * <p> 215 * This returns a new temporal object based on the specified one with the value for 216 * this field changed. For example, on a {@code LocalDate}, this could be used to 217 * set the year, month or day-of-month. 218 * The returned object has the same observable type as the specified object. 219 * <p> 220 * In some cases, changing a field is not fully defined. For example, if the target object is 221 * a date representing the 31st January, then changing the month to February would be unclear. 222 * In cases like this, the implementation is responsible for resolving the result. 223 * Typically it will choose the previous valid date, which would be the last valid 224 * day of February in this example. 225 * <p> 226 * There are two equivalent ways of using this method. 227 * The first is to invoke this method directly. 228 * The second is to use {@link Temporal#with(TemporalField, long)}: 229 * <pre> 230 * // these two lines are equivalent, but the second approach is recommended 231 * temporal = thisField.doWith(temporal); 232 * temporal = temporal.with(thisField); 233 * </pre> 234 * It is recommended to use the second approach, {@code with(TemporalField)}, 235 * as it is a lot clearer to read in code. 236 * <p> 237 * Implementations should perform any queries or calculations using the fields 238 * available in {@link ChronoField}. 239 * If the field is not supported a {@code DateTimeException} must be thrown. 240 * <p> 241 * Implementations must not alter the specified temporal object. 242 * Instead, an adjusted copy of the original must be returned. 243 * This provides equivalent, safe behavior for immutable and mutable implementations. 244 * 245 * @param <R> the type of the Temporal object 246 * @param temporal the temporal object to adjust, not null 247 * @param newValue the new value of the field 248 * @return the adjusted temporal object, not null 249 * @throws DateTimeException if the field cannot be set 250 */ 251 <R extends Temporal> R doWith(R temporal, long newValue); 252 253 /** 254 * Resolves the date/time information in the builder 255 * <p> 256 * This method is invoked during the resolve of the builder. 257 * Implementations should combine the associated field with others to form 258 * objects like {@code LocalDate}, {@code LocalTime} and {@code LocalDateTime} 259 * 260 * @param builder the builder to resolve, not null 261 * @param value the value of the associated field 262 * @return true if builder has been changed, false otherwise 263 * @throws DateTimeException if unable to resolve 264 */ 265 boolean resolve(DateTimeBuilder builder, long value); 266 267}