8187443: Forest Consolidation: Move files to unified layout

Reviewed-by: darcy, ihse
This commit is contained in:
Erik Joelsson 2017-09-12 19:03:39 +02:00
parent 270fe13182
commit 3789983e89
56923 changed files with 3 additions and 15727 deletions

View file

@ -0,0 +1,764 @@
/*
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package java.time.temporal;
import static java.time.temporal.ChronoUnit.DAYS;
import static java.time.temporal.ChronoUnit.ERAS;
import static java.time.temporal.ChronoUnit.FOREVER;
import static java.time.temporal.ChronoUnit.HALF_DAYS;
import static java.time.temporal.ChronoUnit.HOURS;
import static java.time.temporal.ChronoUnit.MICROS;
import static java.time.temporal.ChronoUnit.MILLIS;
import static java.time.temporal.ChronoUnit.MINUTES;
import static java.time.temporal.ChronoUnit.MONTHS;
import static java.time.temporal.ChronoUnit.NANOS;
import static java.time.temporal.ChronoUnit.SECONDS;
import static java.time.temporal.ChronoUnit.WEEKS;
import static java.time.temporal.ChronoUnit.YEARS;
import java.time.DayOfWeek;
import java.time.Instant;
import java.time.Year;
import java.time.ZoneOffset;
import java.time.chrono.ChronoLocalDate;
import java.time.chrono.Chronology;
import java.util.Locale;
import java.util.Objects;
import java.util.ResourceBundle;
import sun.util.locale.provider.LocaleProviderAdapter;
import sun.util.locale.provider.LocaleResources;
/**
* A standard set of fields.
* <p>
* This set of fields provide field-based access to manipulate a date, time or date-time.
* The standard set of fields can be extended by implementing {@link TemporalField}.
* <p>
* These fields are intended to be applicable in multiple calendar systems.
* For example, most non-ISO calendar systems define dates as a year, month and day,
* just with slightly different rules.
* The documentation of each field explains how it operates.
*
* @implSpec
* This is a final, immutable and thread-safe enum.
*
* @since 1.8
*/
public enum ChronoField implements TemporalField {
/**
* The nano-of-second.
* <p>
* This counts the nanosecond within the second, from 0 to 999,999,999.
* This field has the same meaning for all calendar systems.
* <p>
* This field is used to represent the nano-of-second handling any fraction of the second.
* Implementations of {@code TemporalAccessor} should provide a value for this field if
* they can return a value for {@link #SECOND_OF_MINUTE}, {@link #SECOND_OF_DAY} or
* {@link #INSTANT_SECONDS} filling unknown precision with zero.
* <p>
* When this field is used for setting a value, it should set as much precision as the
* object stores, using integer division to remove excess precision.
* For example, if the {@code TemporalAccessor} stores time to millisecond precision,
* then the nano-of-second must be divided by 1,000,000 before replacing the milli-of-second.
* <p>
* When parsing this field it behaves equivalent to the following:
* The value is validated in strict and smart mode but not in lenient mode.
* The field is resolved in combination with {@code MILLI_OF_SECOND} and {@code MICRO_OF_SECOND}.
*/
NANO_OF_SECOND("NanoOfSecond", NANOS, SECONDS, ValueRange.of(0, 999_999_999)),
/**
* The nano-of-day.
* <p>
* This counts the nanosecond within the day, from 0 to (24 * 60 * 60 * 1,000,000,000) - 1.
* This field has the same meaning for all calendar systems.
* <p>
* This field is used to represent the nano-of-day handling any fraction of the second.
* Implementations of {@code TemporalAccessor} should provide a value for this field if
* they can return a value for {@link #SECOND_OF_DAY} filling unknown precision with zero.
* <p>
* When parsing this field it behaves equivalent to the following:
* The value is validated in strict and smart mode but not in lenient mode.
* The value is split to form {@code NANO_OF_SECOND}, {@code SECOND_OF_MINUTE},
* {@code MINUTE_OF_HOUR} and {@code HOUR_OF_DAY} fields.
*/
NANO_OF_DAY("NanoOfDay", NANOS, DAYS, ValueRange.of(0, 86400L * 1000_000_000L - 1)),
/**
* The micro-of-second.
* <p>
* This counts the microsecond within the second, from 0 to 999,999.
* This field has the same meaning for all calendar systems.
* <p>
* This field is used to represent the micro-of-second handling any fraction of the second.
* Implementations of {@code TemporalAccessor} should provide a value for this field if
* they can return a value for {@link #SECOND_OF_MINUTE}, {@link #SECOND_OF_DAY} or
* {@link #INSTANT_SECONDS} filling unknown precision with zero.
* <p>
* When this field is used for setting a value, it should behave in the same way as
* setting {@link #NANO_OF_SECOND} with the value multiplied by 1,000.
* <p>
* When parsing this field it behaves equivalent to the following:
* The value is validated in strict and smart mode but not in lenient mode.
* The field is resolved in combination with {@code MILLI_OF_SECOND} to produce
* {@code NANO_OF_SECOND}.
*/
MICRO_OF_SECOND("MicroOfSecond", MICROS, SECONDS, ValueRange.of(0, 999_999)),
/**
* The micro-of-day.
* <p>
* This counts the microsecond within the day, from 0 to (24 * 60 * 60 * 1,000,000) - 1.
* This field has the same meaning for all calendar systems.
* <p>
* This field is used to represent the micro-of-day handling any fraction of the second.
* Implementations of {@code TemporalAccessor} should provide a value for this field if
* they can return a value for {@link #SECOND_OF_DAY} filling unknown precision with zero.
* <p>
* When this field is used for setting a value, it should behave in the same way as
* setting {@link #NANO_OF_DAY} with the value multiplied by 1,000.
* <p>
* When parsing this field it behaves equivalent to the following:
* The value is validated in strict and smart mode but not in lenient mode.
* The value is split to form {@code MICRO_OF_SECOND}, {@code SECOND_OF_MINUTE},
* {@code MINUTE_OF_HOUR} and {@code HOUR_OF_DAY} fields.
*/
MICRO_OF_DAY("MicroOfDay", MICROS, DAYS, ValueRange.of(0, 86400L * 1000_000L - 1)),
/**
* The milli-of-second.
* <p>
* This counts the millisecond within the second, from 0 to 999.
* This field has the same meaning for all calendar systems.
* <p>
* This field is used to represent the milli-of-second handling any fraction of the second.
* Implementations of {@code TemporalAccessor} should provide a value for this field if
* they can return a value for {@link #SECOND_OF_MINUTE}, {@link #SECOND_OF_DAY} or
* {@link #INSTANT_SECONDS} filling unknown precision with zero.
* <p>
* When this field is used for setting a value, it should behave in the same way as
* setting {@link #NANO_OF_SECOND} with the value multiplied by 1,000,000.
* <p>
* When parsing this field it behaves equivalent to the following:
* The value is validated in strict and smart mode but not in lenient mode.
* The field is resolved in combination with {@code MICRO_OF_SECOND} to produce
* {@code NANO_OF_SECOND}.
*/
MILLI_OF_SECOND("MilliOfSecond", MILLIS, SECONDS, ValueRange.of(0, 999)),
/**
* The milli-of-day.
* <p>
* This counts the millisecond within the day, from 0 to (24 * 60 * 60 * 1,000) - 1.
* This field has the same meaning for all calendar systems.
* <p>
* This field is used to represent the milli-of-day handling any fraction of the second.
* Implementations of {@code TemporalAccessor} should provide a value for this field if
* they can return a value for {@link #SECOND_OF_DAY} filling unknown precision with zero.
* <p>
* When this field is used for setting a value, it should behave in the same way as
* setting {@link #NANO_OF_DAY} with the value multiplied by 1,000,000.
* <p>
* When parsing this field it behaves equivalent to the following:
* The value is validated in strict and smart mode but not in lenient mode.
* The value is split to form {@code MILLI_OF_SECOND}, {@code SECOND_OF_MINUTE},
* {@code MINUTE_OF_HOUR} and {@code HOUR_OF_DAY} fields.
*/
MILLI_OF_DAY("MilliOfDay", MILLIS, DAYS, ValueRange.of(0, 86400L * 1000L - 1)),
/**
* The second-of-minute.
* <p>
* This counts the second within the minute, from 0 to 59.
* This field has the same meaning for all calendar systems.
* <p>
* When parsing this field it behaves equivalent to the following:
* The value is validated in strict and smart mode but not in lenient mode.
*/
SECOND_OF_MINUTE("SecondOfMinute", SECONDS, MINUTES, ValueRange.of(0, 59), "second"),
/**
* The second-of-day.
* <p>
* This counts the second within the day, from 0 to (24 * 60 * 60) - 1.
* This field has the same meaning for all calendar systems.
* <p>
* When parsing this field it behaves equivalent to the following:
* The value is validated in strict and smart mode but not in lenient mode.
* The value is split to form {@code SECOND_OF_MINUTE}, {@code MINUTE_OF_HOUR}
* and {@code HOUR_OF_DAY} fields.
*/
SECOND_OF_DAY("SecondOfDay", SECONDS, DAYS, ValueRange.of(0, 86400L - 1)),
/**
* The minute-of-hour.
* <p>
* This counts the minute within the hour, from 0 to 59.
* This field has the same meaning for all calendar systems.
* <p>
* When parsing this field it behaves equivalent to the following:
* The value is validated in strict and smart mode but not in lenient mode.
*/
MINUTE_OF_HOUR("MinuteOfHour", MINUTES, HOURS, ValueRange.of(0, 59), "minute"),
/**
* The minute-of-day.
* <p>
* This counts the minute within the day, from 0 to (24 * 60) - 1.
* This field has the same meaning for all calendar systems.
* <p>
* When parsing this field it behaves equivalent to the following:
* The value is validated in strict and smart mode but not in lenient mode.
* The value is split to form {@code MINUTE_OF_HOUR} and {@code HOUR_OF_DAY} fields.
*/
MINUTE_OF_DAY("MinuteOfDay", MINUTES, DAYS, ValueRange.of(0, (24 * 60) - 1)),
/**
* The hour-of-am-pm.
* <p>
* This counts the hour within the AM/PM, from 0 to 11.
* This is the hour that would be observed on a standard 12-hour digital clock.
* This field has the same meaning for all calendar systems.
* <p>
* When parsing this field it behaves equivalent to the following:
* The value is validated from 0 to 11 in strict and smart mode.
* In lenient mode the value is not validated. It is combined with
* {@code AMPM_OF_DAY} to form {@code HOUR_OF_DAY} by multiplying
* the {AMPM_OF_DAY} value by 12.
* <p>
* See {@link #CLOCK_HOUR_OF_AMPM} for the related field that counts hours from 1 to 12.
*/
HOUR_OF_AMPM("HourOfAmPm", HOURS, HALF_DAYS, ValueRange.of(0, 11)),
/**
* The clock-hour-of-am-pm.
* <p>
* This counts the hour within the AM/PM, from 1 to 12.
* This is the hour that would be observed on a standard 12-hour analog wall clock.
* This field has the same meaning for all calendar systems.
* <p>
* When parsing this field it behaves equivalent to the following:
* The value is validated from 1 to 12 in strict mode and from
* 0 to 12 in smart mode. In lenient mode the value is not validated.
* The field is converted to an {@code HOUR_OF_AMPM} with the same value,
* unless the value is 12, in which case it is converted to 0.
* <p>
* See {@link #HOUR_OF_AMPM} for the related field that counts hours from 0 to 11.
*/
CLOCK_HOUR_OF_AMPM("ClockHourOfAmPm", HOURS, HALF_DAYS, ValueRange.of(1, 12)),
/**
* The hour-of-day.
* <p>
* This counts the hour within the day, from 0 to 23.
* This is the hour that would be observed on a standard 24-hour digital clock.
* This field has the same meaning for all calendar systems.
* <p>
* When parsing this field it behaves equivalent to the following:
* The value is validated in strict and smart mode but not in lenient mode.
* The field is combined with {@code MINUTE_OF_HOUR}, {@code SECOND_OF_MINUTE} and
* {@code NANO_OF_SECOND} to produce a {@code LocalTime}.
* In lenient mode, any excess days are added to the parsed date, or
* made available via {@link java.time.format.DateTimeFormatter#parsedExcessDays()}.
* <p>
* See {@link #CLOCK_HOUR_OF_DAY} for the related field that counts hours from 1 to 24.
*/
HOUR_OF_DAY("HourOfDay", HOURS, DAYS, ValueRange.of(0, 23), "hour"),
/**
* The clock-hour-of-day.
* <p>
* This counts the hour within the day, from 1 to 24.
* This is the hour that would be observed on a 24-hour analog wall clock.
* This field has the same meaning for all calendar systems.
* <p>
* When parsing this field it behaves equivalent to the following:
* The value is validated from 1 to 24 in strict mode and from
* 0 to 24 in smart mode. In lenient mode the value is not validated.
* The field is converted to an {@code HOUR_OF_DAY} with the same value,
* unless the value is 24, in which case it is converted to 0.
* <p>
* See {@link #HOUR_OF_DAY} for the related field that counts hours from 0 to 23.
*/
CLOCK_HOUR_OF_DAY("ClockHourOfDay", HOURS, DAYS, ValueRange.of(1, 24)),
/**
* The am-pm-of-day.
* <p>
* This counts the AM/PM within the day, from 0 (AM) to 1 (PM).
* This field has the same meaning for all calendar systems.
* <p>
* When parsing this field it behaves equivalent to the following:
* The value is validated from 0 to 1 in strict and smart mode.
* In lenient mode the value is not validated. It is combined with
* {@code HOUR_OF_AMPM} to form {@code HOUR_OF_DAY} by multiplying
* the {AMPM_OF_DAY} value by 12.
*/
AMPM_OF_DAY("AmPmOfDay", HALF_DAYS, DAYS, ValueRange.of(0, 1), "dayperiod"),
/**
* The day-of-week, such as Tuesday.
* <p>
* This represents the standard concept of the day of the week.
* In the default ISO calendar system, this has values from Monday (1) to Sunday (7).
* The {@link DayOfWeek} class can be used to interpret the result.
* <p>
* Most non-ISO calendar systems also define a seven day week that aligns with ISO.
* Those calendar systems must also use the same numbering system, from Monday (1) to
* Sunday (7), which allows {@code DayOfWeek} to be used.
* <p>
* Calendar systems that do not have a standard seven day week should implement this field
* if they have a similar concept of named or numbered days within a period similar
* to a week. It is recommended that the numbering starts from 1.
*/
DAY_OF_WEEK("DayOfWeek", DAYS, WEEKS, ValueRange.of(1, 7), "weekday"),
/**
* The aligned day-of-week within a month.
* <p>
* This represents concept of the count of days within the period of a week
* where the weeks are aligned to the start of the month.
* This field is typically used with {@link #ALIGNED_WEEK_OF_MONTH}.
* <p>
* For example, in a calendar systems with a seven day week, the first aligned-week-of-month
* starts on day-of-month 1, the second aligned-week starts on day-of-month 8, and so on.
* Within each of these aligned-weeks, the days are numbered from 1 to 7 and returned
* as the value of this field.
* As such, day-of-month 1 to 7 will have aligned-day-of-week values from 1 to 7.
* And day-of-month 8 to 14 will repeat this with aligned-day-of-week values from 1 to 7.
* <p>
* Calendar systems that do not have a seven day week should typically implement this
* field in the same way, but using the alternate week length.
*/
ALIGNED_DAY_OF_WEEK_IN_MONTH("AlignedDayOfWeekInMonth", DAYS, WEEKS, ValueRange.of(1, 7)),
/**
* The aligned day-of-week within a year.
* <p>
* This represents concept of the count of days within the period of a week
* where the weeks are aligned to the start of the year.
* This field is typically used with {@link #ALIGNED_WEEK_OF_YEAR}.
* <p>
* For example, in a calendar systems with a seven day week, the first aligned-week-of-year
* starts on day-of-year 1, the second aligned-week starts on day-of-year 8, and so on.
* Within each of these aligned-weeks, the days are numbered from 1 to 7 and returned
* as the value of this field.
* As such, day-of-year 1 to 7 will have aligned-day-of-week values from 1 to 7.
* And day-of-year 8 to 14 will repeat this with aligned-day-of-week values from 1 to 7.
* <p>
* Calendar systems that do not have a seven day week should typically implement this
* field in the same way, but using the alternate week length.
*/
ALIGNED_DAY_OF_WEEK_IN_YEAR("AlignedDayOfWeekInYear", DAYS, WEEKS, ValueRange.of(1, 7)),
/**
* The day-of-month.
* <p>
* This represents the concept of the day within the month.
* In the default ISO calendar system, this has values from 1 to 31 in most months.
* April, June, September, November have days from 1 to 30, while February has days
* from 1 to 28, or 29 in a leap year.
* <p>
* Non-ISO calendar systems should implement this field using the most recognized
* day-of-month values for users of the calendar system.
* Normally, this is a count of days from 1 to the length of the month.
*/
DAY_OF_MONTH("DayOfMonth", DAYS, MONTHS, ValueRange.of(1, 28, 31), "day"),
/**
* The day-of-year.
* <p>
* This represents the concept of the day within the year.
* In the default ISO calendar system, this has values from 1 to 365 in standard
* years and 1 to 366 in leap years.
* <p>
* Non-ISO calendar systems should implement this field using the most recognized
* day-of-year values for users of the calendar system.
* Normally, this is a count of days from 1 to the length of the year.
* <p>
* Note that a non-ISO calendar system may have year numbering system that changes
* at a different point to the natural reset in the month numbering. An example
* of this is the Japanese calendar system where a change of era, which resets
* the year number to 1, can happen on any date. The era and year reset also cause
* the day-of-year to be reset to 1, but not the month-of-year or day-of-month.
*/
DAY_OF_YEAR("DayOfYear", DAYS, YEARS, ValueRange.of(1, 365, 366)),
/**
* The epoch-day, based on the Java epoch of 1970-01-01 (ISO).
* <p>
* This field is the sequential count of days where 1970-01-01 (ISO) is zero.
* Note that this uses the <i>local</i> time-line, ignoring offset and time-zone.
* <p>
* This field is strictly defined to have the same meaning in all calendar systems.
* This is necessary to ensure interoperation between calendars.
* <p>
* Range of EpochDay is between (LocalDate.MIN.toEpochDay(), LocalDate.MAX.toEpochDay())
* both inclusive.
*/
EPOCH_DAY("EpochDay", DAYS, FOREVER, ValueRange.of(-365243219162L, 365241780471L)),
/**
* The aligned week within a month.
* <p>
* This represents concept of the count of weeks within the period of a month
* where the weeks are aligned to the start of the month.
* This field is typically used with {@link #ALIGNED_DAY_OF_WEEK_IN_MONTH}.
* <p>
* For example, in a calendar systems with a seven day week, the first aligned-week-of-month
* starts on day-of-month 1, the second aligned-week starts on day-of-month 8, and so on.
* Thus, day-of-month values 1 to 7 are in aligned-week 1, while day-of-month values
* 8 to 14 are in aligned-week 2, and so on.
* <p>
* Calendar systems that do not have a seven day week should typically implement this
* field in the same way, but using the alternate week length.
*/
ALIGNED_WEEK_OF_MONTH("AlignedWeekOfMonth", WEEKS, MONTHS, ValueRange.of(1, 4, 5)),
/**
* The aligned week within a year.
* <p>
* This represents concept of the count of weeks within the period of a year
* where the weeks are aligned to the start of the year.
* This field is typically used with {@link #ALIGNED_DAY_OF_WEEK_IN_YEAR}.
* <p>
* For example, in a calendar systems with a seven day week, the first aligned-week-of-year
* starts on day-of-year 1, the second aligned-week starts on day-of-year 8, and so on.
* Thus, day-of-year values 1 to 7 are in aligned-week 1, while day-of-year values
* 8 to 14 are in aligned-week 2, and so on.
* <p>
* Calendar systems that do not have a seven day week should typically implement this
* field in the same way, but using the alternate week length.
*/
ALIGNED_WEEK_OF_YEAR("AlignedWeekOfYear", WEEKS, YEARS, ValueRange.of(1, 53)),
/**
* The month-of-year, such as March.
* <p>
* This represents the concept of the month within the year.
* In the default ISO calendar system, this has values from January (1) to December (12).
* <p>
* Non-ISO calendar systems should implement this field using the most recognized
* month-of-year values for users of the calendar system.
* Normally, this is a count of months starting from 1.
*/
MONTH_OF_YEAR("MonthOfYear", MONTHS, YEARS, ValueRange.of(1, 12), "month"),
/**
* The proleptic-month based, counting months sequentially from year 0.
* <p>
* This field is the sequential count of months where the first month
* in proleptic-year zero has the value zero.
* Later months have increasingly larger values.
* Earlier months have increasingly small values.
* There are no gaps or breaks in the sequence of months.
* Note that this uses the <i>local</i> time-line, ignoring offset and time-zone.
* <p>
* In the default ISO calendar system, June 2012 would have the value
* {@code (2012 * 12 + 6 - 1)}. This field is primarily for internal use.
* <p>
* Non-ISO calendar systems must implement this field as per the definition above.
* It is just a simple zero-based count of elapsed months from the start of proleptic-year 0.
* All calendar systems with a full proleptic-year definition will have a year zero.
* If the calendar system has a minimum year that excludes year zero, then one must
* be extrapolated in order for this method to be defined.
*/
PROLEPTIC_MONTH("ProlepticMonth", MONTHS, FOREVER, ValueRange.of(Year.MIN_VALUE * 12L, Year.MAX_VALUE * 12L + 11)),
/**
* The year within the era.
* <p>
* This represents the concept of the year within the era.
* This field is typically used with {@link #ERA}.
* <p>
* The standard mental model for a date is based on three concepts - year, month and day.
* These map onto the {@code YEAR}, {@code MONTH_OF_YEAR} and {@code DAY_OF_MONTH} fields.
* Note that there is no reference to eras.
* The full model for a date requires four concepts - era, year, month and day. These map onto
* the {@code ERA}, {@code YEAR_OF_ERA}, {@code MONTH_OF_YEAR} and {@code DAY_OF_MONTH} fields.
* Whether this field or {@code YEAR} is used depends on which mental model is being used.
* See {@link ChronoLocalDate} for more discussion on this topic.
* <p>
* In the default ISO calendar system, there are two eras defined, 'BCE' and 'CE'.
* The era 'CE' is the one currently in use and year-of-era runs from 1 to the maximum value.
* The era 'BCE' is the previous era, and the year-of-era runs backwards.
* <p>
* For example, subtracting a year each time yield the following:<br>
* - year-proleptic 2 = 'CE' year-of-era 2<br>
* - year-proleptic 1 = 'CE' year-of-era 1<br>
* - year-proleptic 0 = 'BCE' year-of-era 1<br>
* - year-proleptic -1 = 'BCE' year-of-era 2<br>
* <p>
* Note that the ISO-8601 standard does not actually define eras.
* Note also that the ISO eras do not align with the well-known AD/BC eras due to the
* change between the Julian and Gregorian calendar systems.
* <p>
* Non-ISO calendar systems should implement this field using the most recognized
* year-of-era value for users of the calendar system.
* Since most calendar systems have only two eras, the year-of-era numbering approach
* will typically be the same as that used by the ISO calendar system.
* The year-of-era value should typically always be positive, however this is not required.
*/
YEAR_OF_ERA("YearOfEra", YEARS, FOREVER, ValueRange.of(1, Year.MAX_VALUE, Year.MAX_VALUE + 1)),
/**
* The proleptic year, such as 2012.
* <p>
* This represents the concept of the year, counting sequentially and using negative numbers.
* The proleptic year is not interpreted in terms of the era.
* See {@link #YEAR_OF_ERA} for an example showing the mapping from proleptic year to year-of-era.
* <p>
* The standard mental model for a date is based on three concepts - year, month and day.
* These map onto the {@code YEAR}, {@code MONTH_OF_YEAR} and {@code DAY_OF_MONTH} fields.
* Note that there is no reference to eras.
* The full model for a date requires four concepts - era, year, month and day. These map onto
* the {@code ERA}, {@code YEAR_OF_ERA}, {@code MONTH_OF_YEAR} and {@code DAY_OF_MONTH} fields.
* Whether this field or {@code YEAR_OF_ERA} is used depends on which mental model is being used.
* See {@link ChronoLocalDate} for more discussion on this topic.
* <p>
* Non-ISO calendar systems should implement this field as follows.
* If the calendar system has only two eras, before and after a fixed date, then the
* proleptic-year value must be the same as the year-of-era value for the later era,
* and increasingly negative for the earlier era.
* If the calendar system has more than two eras, then the proleptic-year value may be
* defined with any appropriate value, although defining it to be the same as ISO may be
* the best option.
*/
YEAR("Year", YEARS, FOREVER, ValueRange.of(Year.MIN_VALUE, Year.MAX_VALUE), "year"),
/**
* The era.
* <p>
* This represents the concept of the era, which is the largest division of the time-line.
* This field is typically used with {@link #YEAR_OF_ERA}.
* <p>
* In the default ISO calendar system, there are two eras defined, 'BCE' and 'CE'.
* The era 'CE' is the one currently in use and year-of-era runs from 1 to the maximum value.
* The era 'BCE' is the previous era, and the year-of-era runs backwards.
* See {@link #YEAR_OF_ERA} for a full example.
* <p>
* Non-ISO calendar systems should implement this field to define eras.
* The value of the era that was active on 1970-01-01 (ISO) must be assigned the value 1.
* Earlier eras must have sequentially smaller values.
* Later eras must have sequentially larger values,
*/
ERA("Era", ERAS, FOREVER, ValueRange.of(0, 1), "era"),
/**
* The instant epoch-seconds.
* <p>
* This represents the concept of the sequential count of seconds where
* 1970-01-01T00:00Z (ISO) is zero.
* This field may be used with {@link #NANO_OF_SECOND} to represent the fraction of the second.
* <p>
* An {@link Instant} represents an instantaneous point on the time-line.
* On their own, an instant has insufficient information to allow a local date-time to be obtained.
* Only when paired with an offset or time-zone can the local date or time be calculated.
* <p>
* This field is strictly defined to have the same meaning in all calendar systems.
* This is necessary to ensure interoperation between calendars.
*/
INSTANT_SECONDS("InstantSeconds", SECONDS, FOREVER, ValueRange.of(Long.MIN_VALUE, Long.MAX_VALUE)),
/**
* The offset from UTC/Greenwich.
* <p>
* This represents the concept of the offset in seconds of local time from UTC/Greenwich.
* <p>
* A {@link ZoneOffset} represents the period of time that local time differs from UTC/Greenwich.
* This is usually a fixed number of hours and minutes.
* It is equivalent to the {@link ZoneOffset#getTotalSeconds() total amount} of the offset in seconds.
* For example, during the winter Paris has an offset of {@code +01:00}, which is 3600 seconds.
* <p>
* This field is strictly defined to have the same meaning in all calendar systems.
* This is necessary to ensure interoperation between calendars.
*/
OFFSET_SECONDS("OffsetSeconds", SECONDS, FOREVER, ValueRange.of(-18 * 3600, 18 * 3600));
private final String name;
private final TemporalUnit baseUnit;
private final TemporalUnit rangeUnit;
private final ValueRange range;
private final String displayNameKey;
private ChronoField(String name, TemporalUnit baseUnit, TemporalUnit rangeUnit, ValueRange range) {
this.name = name;
this.baseUnit = baseUnit;
this.rangeUnit = rangeUnit;
this.range = range;
this.displayNameKey = null;
}
private ChronoField(String name, TemporalUnit baseUnit, TemporalUnit rangeUnit,
ValueRange range, String displayNameKey) {
this.name = name;
this.baseUnit = baseUnit;
this.rangeUnit = rangeUnit;
this.range = range;
this.displayNameKey = displayNameKey;
}
@Override
public String getDisplayName(Locale locale) {
Objects.requireNonNull(locale, "locale");
if (displayNameKey == null) {
return name;
}
LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased()
.getLocaleResources(locale);
ResourceBundle rb = lr.getJavaTimeFormatData();
String key = "field." + displayNameKey;
return rb.containsKey(key) ? rb.getString(key) : name;
}
@Override
public TemporalUnit getBaseUnit() {
return baseUnit;
}
@Override
public TemporalUnit getRangeUnit() {
return rangeUnit;
}
/**
* Gets the range of valid values for the field.
* <p>
* All fields can be expressed as a {@code long} integer.
* This method returns an object that describes the valid range for that value.
* <p>
* This method returns the range of the field in the ISO-8601 calendar system.
* This range may be incorrect for other calendar systems.
* Use {@link Chronology#range(ChronoField)} to access the correct range
* for a different calendar system.
* <p>
* Note that the result only describes the minimum and maximum valid values
* and it is important not to read too much into them. For example, there
* could be values within the range that are invalid for the field.
*
* @return the range of valid values for the field, not null
*/
@Override
public ValueRange range() {
return range;
}
//-----------------------------------------------------------------------
/**
* Checks if this field represents a component of a date.
* <p>
* Fields from day-of-week to era are date-based.
*
* @return true if it is a component of a date
*/
@Override
public boolean isDateBased() {
return ordinal() >= DAY_OF_WEEK.ordinal() && ordinal() <= ERA.ordinal();
}
/**
* Checks if this field represents a component of a time.
* <p>
* Fields from nano-of-second to am-pm-of-day are time-based.
*
* @return true if it is a component of a time
*/
@Override
public boolean isTimeBased() {
return ordinal() < DAY_OF_WEEK.ordinal();
}
//-----------------------------------------------------------------------
/**
* Checks that the specified value is valid for this field.
* <p>
* This validates that the value is within the outer range of valid values
* returned by {@link #range()}.
* <p>
* This method checks against the range of the field in the ISO-8601 calendar system.
* This range may be incorrect for other calendar systems.
* Use {@link Chronology#range(ChronoField)} to access the correct range
* for a different calendar system.
*
* @param value the value to check
* @return the value that was passed in
*/
public long checkValidValue(long value) {
return range().checkValidValue(value, this);
}
/**
* Checks that the specified value is valid and fits in an {@code int}.
* <p>
* This validates that the value is within the outer range of valid values
* returned by {@link #range()}.
* It also checks that all valid values are within the bounds of an {@code int}.
* <p>
* This method checks against the range of the field in the ISO-8601 calendar system.
* This range may be incorrect for other calendar systems.
* Use {@link Chronology#range(ChronoField)} to access the correct range
* for a different calendar system.
*
* @param value the value to check
* @return the value that was passed in
*/
public int checkValidIntValue(long value) {
return range().checkValidIntValue(value, this);
}
//-----------------------------------------------------------------------
@Override
public boolean isSupportedBy(TemporalAccessor temporal) {
return temporal.isSupported(this);
}
@Override
public ValueRange rangeRefinedBy(TemporalAccessor temporal) {
return temporal.range(this);
}
@Override
public long getFrom(TemporalAccessor temporal) {
return temporal.getLong(this);
}
@SuppressWarnings("unchecked")
@Override
public <R extends Temporal> R adjustInto(R temporal, long newValue) {
return (R) temporal.with(this, newValue);
}
//-----------------------------------------------------------------------
@Override
public String toString() {
return name;
}
}

View file

@ -0,0 +1,281 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package java.time.temporal;
import java.time.Duration;
/**
* A standard set of date periods units.
* <p>
* This set of units provide unit-based access to manipulate a date, time or date-time.
* The standard set of units can be extended by implementing {@link TemporalUnit}.
* <p>
* These units are intended to be applicable in multiple calendar systems.
* For example, most non-ISO calendar systems define units of years, months and days,
* just with slightly different rules.
* The documentation of each unit explains how it operates.
*
* @implSpec
* This is a final, immutable and thread-safe enum.
*
* @since 1.8
*/
public enum ChronoUnit implements TemporalUnit {
/**
* Unit that represents the concept of a nanosecond, the smallest supported unit of time.
* For the ISO calendar system, it is equal to the 1,000,000,000th part of the second unit.
*/
NANOS("Nanos", Duration.ofNanos(1)),
/**
* Unit that represents the concept of a microsecond.
* For the ISO calendar system, it is equal to the 1,000,000th part of the second unit.
*/
MICROS("Micros", Duration.ofNanos(1000)),
/**
* Unit that represents the concept of a millisecond.
* For the ISO calendar system, it is equal to the 1000th part of the second unit.
*/
MILLIS("Millis", Duration.ofNanos(1000_000)),
/**
* Unit that represents the concept of a second.
* For the ISO calendar system, it is equal to the second in the SI system
* of units, except around a leap-second.
*/
SECONDS("Seconds", Duration.ofSeconds(1)),
/**
* Unit that represents the concept of a minute.
* For the ISO calendar system, it is equal to 60 seconds.
*/
MINUTES("Minutes", Duration.ofSeconds(60)),
/**
* Unit that represents the concept of an hour.
* For the ISO calendar system, it is equal to 60 minutes.
*/
HOURS("Hours", Duration.ofSeconds(3600)),
/**
* Unit that represents the concept of half a day, as used in AM/PM.
* For the ISO calendar system, it is equal to 12 hours.
*/
HALF_DAYS("HalfDays", Duration.ofSeconds(43200)),
/**
* Unit that represents the concept of a day.
* For the ISO calendar system, it is the standard day from midnight to midnight.
* The estimated duration of a day is {@code 24 Hours}.
* <p>
* When used with other calendar systems it must correspond to the day defined by
* the rising and setting of the Sun on Earth. It is not required that days begin
* at midnight - when converting between calendar systems, the date should be
* equivalent at midday.
*/
DAYS("Days", Duration.ofSeconds(86400)),
/**
* Unit that represents the concept of a week.
* For the ISO calendar system, it is equal to 7 days.
* <p>
* When used with other calendar systems it must correspond to an integral number of days.
*/
WEEKS("Weeks", Duration.ofSeconds(7 * 86400L)),
/**
* Unit that represents the concept of a month.
* For the ISO calendar system, the length of the month varies by month-of-year.
* The estimated duration of a month is one twelfth of {@code 365.2425 Days}.
* <p>
* When used with other calendar systems it must correspond to an integral number of days.
*/
MONTHS("Months", Duration.ofSeconds(31556952L / 12)),
/**
* Unit that represents the concept of a year.
* For the ISO calendar system, it is equal to 12 months.
* The estimated duration of a year is {@code 365.2425 Days}.
* <p>
* When used with other calendar systems it must correspond to an integral number of days
* or months roughly equal to a year defined by the passage of the Earth around the Sun.
*/
YEARS("Years", Duration.ofSeconds(31556952L)),
/**
* Unit that represents the concept of a decade.
* For the ISO calendar system, it is equal to 10 years.
* <p>
* When used with other calendar systems it must correspond to an integral number of days
* and is normally an integral number of years.
*/
DECADES("Decades", Duration.ofSeconds(31556952L * 10L)),
/**
* Unit that represents the concept of a century.
* For the ISO calendar system, it is equal to 100 years.
* <p>
* When used with other calendar systems it must correspond to an integral number of days
* and is normally an integral number of years.
*/
CENTURIES("Centuries", Duration.ofSeconds(31556952L * 100L)),
/**
* Unit that represents the concept of a millennium.
* For the ISO calendar system, it is equal to 1000 years.
* <p>
* When used with other calendar systems it must correspond to an integral number of days
* and is normally an integral number of years.
*/
MILLENNIA("Millennia", Duration.ofSeconds(31556952L * 1000L)),
/**
* Unit that represents the concept of an era.
* The ISO calendar system doesn't have eras thus it is impossible to add
* an era to a date or date-time.
* The estimated duration of the era is artificially defined as {@code 1,000,000,000 Years}.
* <p>
* When used with other calendar systems there are no restrictions on the unit.
*/
ERAS("Eras", Duration.ofSeconds(31556952L * 1000_000_000L)),
/**
* Artificial unit that represents the concept of forever.
* This is primarily used with {@link TemporalField} to represent unbounded fields
* such as the year or era.
* The estimated duration of this unit is artificially defined as the largest duration
* supported by {@link Duration}.
*/
FOREVER("Forever", Duration.ofSeconds(Long.MAX_VALUE, 999_999_999));
private final String name;
private final Duration duration;
private ChronoUnit(String name, Duration estimatedDuration) {
this.name = name;
this.duration = estimatedDuration;
}
//-----------------------------------------------------------------------
/**
* Gets the estimated duration of this unit in the ISO calendar system.
* <p>
* All of the units in this class have an estimated duration.
* Days vary due to daylight saving time, while months have different lengths.
*
* @return the estimated duration of this unit, not null
*/
@Override
public Duration getDuration() {
return duration;
}
/**
* Checks if the duration of the unit is an estimate.
* <p>
* All time units in this class are considered to be accurate, while all date
* units in this class are considered to be estimated.
* <p>
* This definition ignores leap seconds, but considers that Days vary due to
* daylight saving time and months have different lengths.
*
* @return true if the duration is estimated, false if accurate
*/
@Override
public boolean isDurationEstimated() {
return this.compareTo(DAYS) >= 0;
}
//-----------------------------------------------------------------------
/**
* Checks if this unit is a date unit.
* <p>
* All units from days to eras inclusive are date-based.
* Time-based units and {@code FOREVER} return false.
*
* @return true if a date unit, false if a time unit
*/
@Override
public boolean isDateBased() {
return this.compareTo(DAYS) >= 0 && this != FOREVER;
}
/**
* Checks if this unit is a time unit.
* <p>
* All units from nanos to half-days inclusive are time-based.
* Date-based units and {@code FOREVER} return false.
*
* @return true if a time unit, false if a date unit
*/
@Override
public boolean isTimeBased() {
return this.compareTo(DAYS) < 0;
}
//-----------------------------------------------------------------------
@Override
public boolean isSupportedBy(Temporal temporal) {
return temporal.isSupported(this);
}
@SuppressWarnings("unchecked")
@Override
public <R extends Temporal> R addTo(R temporal, long amount) {
return (R) temporal.plus(amount, this);
}
//-----------------------------------------------------------------------
@Override
public long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive) {
return temporal1Inclusive.until(temporal2Exclusive, this);
}
//-----------------------------------------------------------------------
@Override
public String toString() {
return name;
}
}

View file

@ -0,0 +1,741 @@
/*
* Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* Copyright (c) 2011-2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package java.time.temporal;
import static java.time.DayOfWeek.THURSDAY;
import static java.time.DayOfWeek.WEDNESDAY;
import static java.time.temporal.ChronoField.DAY_OF_WEEK;
import static java.time.temporal.ChronoField.DAY_OF_YEAR;
import static java.time.temporal.ChronoField.EPOCH_DAY;
import static java.time.temporal.ChronoField.MONTH_OF_YEAR;
import static java.time.temporal.ChronoField.YEAR;
import static java.time.temporal.ChronoUnit.DAYS;
import static java.time.temporal.ChronoUnit.FOREVER;
import static java.time.temporal.ChronoUnit.MONTHS;
import static java.time.temporal.ChronoUnit.WEEKS;
import static java.time.temporal.ChronoUnit.YEARS;
import java.time.DateTimeException;
import java.time.Duration;
import java.time.LocalDate;
import java.time.chrono.ChronoLocalDate;
import java.time.chrono.Chronology;
import java.time.chrono.IsoChronology;
import java.time.format.ResolverStyle;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.ResourceBundle;
import sun.util.locale.provider.LocaleProviderAdapter;
import sun.util.locale.provider.LocaleResources;
/**
* Fields and units specific to the ISO-8601 calendar system,
* including quarter-of-year and week-based-year.
* <p>
* This class defines fields and units that are specific to the ISO calendar system.
*
* <h3>Quarter of year</h3>
* The ISO-8601 standard is based on the standard civic 12 month year.
* This is commonly divided into four quarters, often abbreviated as Q1, Q2, Q3 and Q4.
* <p>
* January, February and March are in Q1.
* April, May and June are in Q2.
* July, August and September are in Q3.
* October, November and December are in Q4.
* <p>
* The complete date is expressed using three fields:
* <ul>
* <li>{@link #DAY_OF_QUARTER DAY_OF_QUARTER} - the day within the quarter, from 1 to 90, 91 or 92
* <li>{@link #QUARTER_OF_YEAR QUARTER_OF_YEAR} - the quarter within the year, from 1 to 4
* <li>{@link ChronoField#YEAR YEAR} - the standard ISO year
* </ul>
*
* <h3>Week based years</h3>
* The ISO-8601 standard was originally intended as a data interchange format,
* defining a string format for dates and times. However, it also defines an
* alternate way of expressing the date, based on the concept of week-based-year.
* <p>
* The date is expressed using three fields:
* <ul>
* <li>{@link ChronoField#DAY_OF_WEEK DAY_OF_WEEK} - the standard field defining the
* day-of-week from Monday (1) to Sunday (7)
* <li>{@link #WEEK_OF_WEEK_BASED_YEAR} - the week within the week-based-year
* <li>{@link #WEEK_BASED_YEAR WEEK_BASED_YEAR} - the week-based-year
* </ul>
* The week-based-year itself is defined relative to the standard ISO proleptic year.
* It differs from the standard year in that it always starts on a Monday.
* <p>
* The first week of a week-based-year is the first Monday-based week of the standard
* ISO year that has at least 4 days in the new year.
* <ul>
* <li>If January 1st is Monday then week 1 starts on January 1st
* <li>If January 1st is Tuesday then week 1 starts on December 31st of the previous standard year
* <li>If January 1st is Wednesday then week 1 starts on December 30th of the previous standard year
* <li>If January 1st is Thursday then week 1 starts on December 29th of the previous standard year
* <li>If January 1st is Friday then week 1 starts on January 4th
* <li>If January 1st is Saturday then week 1 starts on January 3rd
* <li>If January 1st is Sunday then week 1 starts on January 2nd
* </ul>
* There are 52 weeks in most week-based years, however on occasion there are 53 weeks.
* <p>
* For example:
*
* <table class=striped style="text-align: left">
* <caption>Examples of Week based Years</caption>
* <thead>
* <tr><th scope="col">Date</th><th scope="col">Day-of-week</th><th scope="col">Field values</th></tr>
* </thead>
* <tbody>
* <tr><th scope="row">2008-12-28</th><td>Sunday</td><td>Week 52 of week-based-year 2008</td></tr>
* <tr><th scope="row">2008-12-29</th><td>Monday</td><td>Week 1 of week-based-year 2009</td></tr>
* <tr><th scope="row">2008-12-31</th><td>Wednesday</td><td>Week 1 of week-based-year 2009</td></tr>
* <tr><th scope="row">2009-01-01</th><td>Thursday</td><td>Week 1 of week-based-year 2009</td></tr>
* <tr><th scope="row">2009-01-04</th><td>Sunday</td><td>Week 1 of week-based-year 2009</td></tr>
* <tr><th scope="row">2009-01-05</th><td>Monday</td><td>Week 2 of week-based-year 2009</td></tr>
* </tbody>
* </table>
*
* @implSpec
* <p>
* This class is immutable and thread-safe.
*
* @since 1.8
*/
public final class IsoFields {
/**
* The field that represents the day-of-quarter.
* <p>
* This field allows the day-of-quarter value to be queried and set.
* The day-of-quarter has values from 1 to 90 in Q1 of a standard year, from 1 to 91
* in Q1 of a leap year, from 1 to 91 in Q2 and from 1 to 92 in Q3 and Q4.
* <p>
* The day-of-quarter can only be calculated if the day-of-year, month-of-year and year
* are available.
* <p>
* When setting this field, the value is allowed to be partially lenient, taking any
* value from 1 to 92. If the quarter has less than 92 days, then day 92, and
* potentially day 91, is in the following quarter.
* <p>
* In the resolving phase of parsing, a date can be created from a year,
* quarter-of-year and day-of-quarter.
* <p>
* In {@linkplain ResolverStyle#STRICT strict mode}, all three fields are
* validated against their range of valid values. The day-of-quarter field
* is validated from 1 to 90, 91 or 92 depending on the year and quarter.
* <p>
* In {@linkplain ResolverStyle#SMART smart mode}, all three fields are
* validated against their range of valid values. The day-of-quarter field is
* validated between 1 and 92, ignoring the actual range based on the year and quarter.
* If the day-of-quarter exceeds the actual range by one day, then the resulting date
* is one day later. If the day-of-quarter exceeds the actual range by two days,
* then the resulting date is two days later.
* <p>
* In {@linkplain ResolverStyle#LENIENT lenient mode}, only the year is validated
* against the range of valid values. The resulting date is calculated equivalent to
* the following three stage approach. First, create a date on the first of January
* in the requested year. Then take the quarter-of-year, subtract one, and add the
* amount in quarters to the date. Finally, take the day-of-quarter, subtract one,
* and add the amount in days to the date.
* <p>
* This unit is an immutable and thread-safe singleton.
*/
public static final TemporalField DAY_OF_QUARTER = Field.DAY_OF_QUARTER;
/**
* The field that represents the quarter-of-year.
* <p>
* This field allows the quarter-of-year value to be queried and set.
* The quarter-of-year has values from 1 to 4.
* <p>
* The quarter-of-year can only be calculated if the month-of-year is available.
* <p>
* In the resolving phase of parsing, a date can be created from a year,
* quarter-of-year and day-of-quarter.
* See {@link #DAY_OF_QUARTER} for details.
* <p>
* This unit is an immutable and thread-safe singleton.
*/
public static final TemporalField QUARTER_OF_YEAR = Field.QUARTER_OF_YEAR;
/**
* The field that represents the week-of-week-based-year.
* <p>
* This field allows the week of the week-based-year value to be queried and set.
* The week-of-week-based-year has values from 1 to 52, or 53 if the
* week-based-year has 53 weeks.
* <p>
* In the resolving phase of parsing, a date can be created from a
* week-based-year, week-of-week-based-year and day-of-week.
* <p>
* In {@linkplain ResolverStyle#STRICT strict mode}, all three fields are
* validated against their range of valid values. The week-of-week-based-year
* field is validated from 1 to 52 or 53 depending on the week-based-year.
* <p>
* In {@linkplain ResolverStyle#SMART smart mode}, all three fields are
* validated against their range of valid values. The week-of-week-based-year
* field is validated between 1 and 53, ignoring the week-based-year.
* If the week-of-week-based-year is 53, but the week-based-year only has
* 52 weeks, then the resulting date is in week 1 of the following week-based-year.
* <p>
* In {@linkplain ResolverStyle#LENIENT lenient mode}, only the week-based-year
* is validated against the range of valid values. If the day-of-week is outside
* the range 1 to 7, then the resulting date is adjusted by a suitable number of
* weeks to reduce the day-of-week to the range 1 to 7. If the week-of-week-based-year
* value is outside the range 1 to 52, then any excess weeks are added or subtracted
* from the resulting date.
* <p>
* This unit is an immutable and thread-safe singleton.
*/
public static final TemporalField WEEK_OF_WEEK_BASED_YEAR = Field.WEEK_OF_WEEK_BASED_YEAR;
/**
* The field that represents the week-based-year.
* <p>
* This field allows the week-based-year value to be queried and set.
* <p>
* The field has a range that matches {@link LocalDate#MAX} and {@link LocalDate#MIN}.
* <p>
* In the resolving phase of parsing, a date can be created from a
* week-based-year, week-of-week-based-year and day-of-week.
* See {@link #WEEK_OF_WEEK_BASED_YEAR} for details.
* <p>
* This unit is an immutable and thread-safe singleton.
*/
public static final TemporalField WEEK_BASED_YEAR = Field.WEEK_BASED_YEAR;
/**
* The unit that represents week-based-years for the purpose of addition and subtraction.
* <p>
* This allows a number of week-based-years to be added to, or subtracted from, a date.
* The unit is equal to either 52 or 53 weeks.
* The estimated duration of a week-based-year is the same as that of a standard ISO
* year at {@code 365.2425 Days}.
* <p>
* The rules for addition add the number of week-based-years to the existing value
* for the week-based-year field. If the resulting week-based-year only has 52 weeks,
* then the date will be in week 1 of the following week-based-year.
* <p>
* This unit is an immutable and thread-safe singleton.
*/
public static final TemporalUnit WEEK_BASED_YEARS = Unit.WEEK_BASED_YEARS;
/**
* Unit that represents the concept of a quarter-year.
* For the ISO calendar system, it is equal to 3 months.
* The estimated duration of a quarter-year is one quarter of {@code 365.2425 Days}.
* <p>
* This unit is an immutable and thread-safe singleton.
*/
public static final TemporalUnit QUARTER_YEARS = Unit.QUARTER_YEARS;
/**
* Restricted constructor.
*/
private IsoFields() {
throw new AssertionError("Not instantiable");
}
//-----------------------------------------------------------------------
/**
* Implementation of the field.
*/
private static enum Field implements TemporalField {
DAY_OF_QUARTER {
@Override
public TemporalUnit getBaseUnit() {
return DAYS;
}
@Override
public TemporalUnit getRangeUnit() {
return QUARTER_YEARS;
}
@Override
public ValueRange range() {
return ValueRange.of(1, 90, 92);
}
@Override
public boolean isSupportedBy(TemporalAccessor temporal) {
return temporal.isSupported(DAY_OF_YEAR) && temporal.isSupported(MONTH_OF_YEAR) &&
temporal.isSupported(YEAR) && isIso(temporal);
}
@Override
public ValueRange rangeRefinedBy(TemporalAccessor temporal) {
if (isSupportedBy(temporal) == false) {
throw new UnsupportedTemporalTypeException("Unsupported field: DayOfQuarter");
}
long qoy = temporal.getLong(QUARTER_OF_YEAR);
if (qoy == 1) {
long year = temporal.getLong(YEAR);
return (IsoChronology.INSTANCE.isLeapYear(year) ? ValueRange.of(1, 91) : ValueRange.of(1, 90));
} else if (qoy == 2) {
return ValueRange.of(1, 91);
} else if (qoy == 3 || qoy == 4) {
return ValueRange.of(1, 92);
} // else value not from 1 to 4, so drop through
return range();
}
@Override
public long getFrom(TemporalAccessor temporal) {
if (isSupportedBy(temporal) == false) {
throw new UnsupportedTemporalTypeException("Unsupported field: DayOfQuarter");
}
int doy = temporal.get(DAY_OF_YEAR);
int moy = temporal.get(MONTH_OF_YEAR);
long year = temporal.getLong(YEAR);
return doy - QUARTER_DAYS[((moy - 1) / 3) + (IsoChronology.INSTANCE.isLeapYear(year) ? 4 : 0)];
}
@SuppressWarnings("unchecked")
@Override
public <R extends Temporal> R adjustInto(R temporal, long newValue) {
// calls getFrom() to check if supported
long curValue = getFrom(temporal);
range().checkValidValue(newValue, this); // leniently check from 1 to 92 TODO: check
return (R) temporal.with(DAY_OF_YEAR, temporal.getLong(DAY_OF_YEAR) + (newValue - curValue));
}
@Override
public ChronoLocalDate resolve(
Map<TemporalField, Long> fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) {
Long yearLong = fieldValues.get(YEAR);
Long qoyLong = fieldValues.get(QUARTER_OF_YEAR);
if (yearLong == null || qoyLong == null) {
return null;
}
int y = YEAR.checkValidIntValue(yearLong); // always validate
long doq = fieldValues.get(DAY_OF_QUARTER);
ensureIso(partialTemporal);
LocalDate date;
if (resolverStyle == ResolverStyle.LENIENT) {
date = LocalDate.of(y, 1, 1).plusMonths(Math.multiplyExact(Math.subtractExact(qoyLong, 1), 3));
doq = Math.subtractExact(doq, 1);
} else {
int qoy = QUARTER_OF_YEAR.range().checkValidIntValue(qoyLong, QUARTER_OF_YEAR); // validated
date = LocalDate.of(y, ((qoy - 1) * 3) + 1, 1);
if (doq < 1 || doq > 90) {
if (resolverStyle == ResolverStyle.STRICT) {
rangeRefinedBy(date).checkValidValue(doq, this); // only allow exact range
} else { // SMART
range().checkValidValue(doq, this); // allow 1-92 rolling into next quarter
}
}
doq--;
}
fieldValues.remove(this);
fieldValues.remove(YEAR);
fieldValues.remove(QUARTER_OF_YEAR);
return date.plusDays(doq);
}
@Override
public String toString() {
return "DayOfQuarter";
}
},
QUARTER_OF_YEAR {
@Override
public TemporalUnit getBaseUnit() {
return QUARTER_YEARS;
}
@Override
public TemporalUnit getRangeUnit() {
return YEARS;
}
@Override
public ValueRange range() {
return ValueRange.of(1, 4);
}
@Override
public boolean isSupportedBy(TemporalAccessor temporal) {
return temporal.isSupported(MONTH_OF_YEAR) && isIso(temporal);
}
@Override
public long getFrom(TemporalAccessor temporal) {
if (isSupportedBy(temporal) == false) {
throw new UnsupportedTemporalTypeException("Unsupported field: QuarterOfYear");
}
long moy = temporal.getLong(MONTH_OF_YEAR);
return ((moy + 2) / 3);
}
public ValueRange rangeRefinedBy(TemporalAccessor temporal) {
if (isSupportedBy(temporal) == false) {
throw new UnsupportedTemporalTypeException("Unsupported field: QuarterOfYear");
}
return super.rangeRefinedBy(temporal);
}
@SuppressWarnings("unchecked")
@Override
public <R extends Temporal> R adjustInto(R temporal, long newValue) {
// calls getFrom() to check if supported
long curValue = getFrom(temporal);
range().checkValidValue(newValue, this); // strictly check from 1 to 4
return (R) temporal.with(MONTH_OF_YEAR, temporal.getLong(MONTH_OF_YEAR) + (newValue - curValue) * 3);
}
@Override
public String toString() {
return "QuarterOfYear";
}
},
WEEK_OF_WEEK_BASED_YEAR {
@Override
public String getDisplayName(Locale locale) {
Objects.requireNonNull(locale, "locale");
LocaleResources lr = LocaleProviderAdapter.getResourceBundleBased()
.getLocaleResources(locale);
ResourceBundle rb = lr.getJavaTimeFormatData();
return rb.containsKey("field.week") ? rb.getString("field.week") : toString();
}
@Override
public TemporalUnit getBaseUnit() {
return WEEKS;
}
@Override
public TemporalUnit getRangeUnit() {
return WEEK_BASED_YEARS;
}
@Override
public ValueRange range() {
return ValueRange.of(1, 52, 53);
}
@Override
public boolean isSupportedBy(TemporalAccessor temporal) {
return temporal.isSupported(EPOCH_DAY) && isIso(temporal);
}
@Override
public ValueRange rangeRefinedBy(TemporalAccessor temporal) {
if (isSupportedBy(temporal) == false) {
throw new UnsupportedTemporalTypeException("Unsupported field: WeekOfWeekBasedYear");
}
return getWeekRange(LocalDate.from(temporal));
}
@Override
public long getFrom(TemporalAccessor temporal) {
if (isSupportedBy(temporal) == false) {
throw new UnsupportedTemporalTypeException("Unsupported field: WeekOfWeekBasedYear");
}
return getWeek(LocalDate.from(temporal));
}
@SuppressWarnings("unchecked")
@Override
public <R extends Temporal> R adjustInto(R temporal, long newValue) {
// calls getFrom() to check if supported
range().checkValidValue(newValue, this); // lenient range
return (R) temporal.plus(Math.subtractExact(newValue, getFrom(temporal)), WEEKS);
}
@Override
public ChronoLocalDate resolve(
Map<TemporalField, Long> fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) {
Long wbyLong = fieldValues.get(WEEK_BASED_YEAR);
Long dowLong = fieldValues.get(DAY_OF_WEEK);
if (wbyLong == null || dowLong == null) {
return null;
}
int wby = WEEK_BASED_YEAR.range().checkValidIntValue(wbyLong, WEEK_BASED_YEAR); // always validate
long wowby = fieldValues.get(WEEK_OF_WEEK_BASED_YEAR);
ensureIso(partialTemporal);
LocalDate date = LocalDate.of(wby, 1, 4);
if (resolverStyle == ResolverStyle.LENIENT) {
long dow = dowLong; // unvalidated
if (dow > 7) {
date = date.plusWeeks((dow - 1) / 7);
dow = ((dow - 1) % 7) + 1;
} else if (dow < 1) {
date = date.plusWeeks(Math.subtractExact(dow, 7) / 7);
dow = ((dow + 6) % 7) + 1;
}
date = date.plusWeeks(Math.subtractExact(wowby, 1)).with(DAY_OF_WEEK, dow);
} else {
int dow = DAY_OF_WEEK.checkValidIntValue(dowLong); // validated
if (wowby < 1 || wowby > 52) {
if (resolverStyle == ResolverStyle.STRICT) {
getWeekRange(date).checkValidValue(wowby, this); // only allow exact range
} else { // SMART
range().checkValidValue(wowby, this); // allow 1-53 rolling into next year
}
}
date = date.plusWeeks(wowby - 1).with(DAY_OF_WEEK, dow);
}
fieldValues.remove(this);
fieldValues.remove(WEEK_BASED_YEAR);
fieldValues.remove(DAY_OF_WEEK);
return date;
}
@Override
public String toString() {
return "WeekOfWeekBasedYear";
}
},
WEEK_BASED_YEAR {
@Override
public TemporalUnit getBaseUnit() {
return WEEK_BASED_YEARS;
}
@Override
public TemporalUnit getRangeUnit() {
return FOREVER;
}
@Override
public ValueRange range() {
return YEAR.range();
}
@Override
public boolean isSupportedBy(TemporalAccessor temporal) {
return temporal.isSupported(EPOCH_DAY) && isIso(temporal);
}
@Override
public long getFrom(TemporalAccessor temporal) {
if (isSupportedBy(temporal) == false) {
throw new UnsupportedTemporalTypeException("Unsupported field: WeekBasedYear");
}
return getWeekBasedYear(LocalDate.from(temporal));
}
public ValueRange rangeRefinedBy(TemporalAccessor temporal) {
if (isSupportedBy(temporal) == false) {
throw new UnsupportedTemporalTypeException("Unsupported field: WeekBasedYear");
}
return super.rangeRefinedBy(temporal);
}
@SuppressWarnings("unchecked")
@Override
public <R extends Temporal> R adjustInto(R temporal, long newValue) {
if (isSupportedBy(temporal) == false) {
throw new UnsupportedTemporalTypeException("Unsupported field: WeekBasedYear");
}
int newWby = range().checkValidIntValue(newValue, WEEK_BASED_YEAR); // strict check
LocalDate date = LocalDate.from(temporal);
int dow = date.get(DAY_OF_WEEK);
int week = getWeek(date);
if (week == 53 && getWeekRange(newWby) == 52) {
week = 52;
}
LocalDate resolved = LocalDate.of(newWby, 1, 4); // 4th is guaranteed to be in week one
int days = (dow - resolved.get(DAY_OF_WEEK)) + ((week - 1) * 7);
resolved = resolved.plusDays(days);
return (R) temporal.with(resolved);
}
@Override
public String toString() {
return "WeekBasedYear";
}
};
@Override
public boolean isDateBased() {
return true;
}
@Override
public boolean isTimeBased() {
return false;
}
@Override
public ValueRange rangeRefinedBy(TemporalAccessor temporal) {
return range();
}
//-------------------------------------------------------------------------
private static final int[] QUARTER_DAYS = {0, 90, 181, 273, 0, 91, 182, 274};
private static void ensureIso(TemporalAccessor temporal) {
if (isIso(temporal) == false) {
throw new DateTimeException("Resolve requires IsoChronology");
}
}
private static ValueRange getWeekRange(LocalDate date) {
int wby = getWeekBasedYear(date);
return ValueRange.of(1, getWeekRange(wby));
}
private static int getWeekRange(int wby) {
LocalDate date = LocalDate.of(wby, 1, 1);
// 53 weeks if standard year starts on Thursday, or Wed in a leap year
if (date.getDayOfWeek() == THURSDAY || (date.getDayOfWeek() == WEDNESDAY && date.isLeapYear())) {
return 53;
}
return 52;
}
private static int getWeek(LocalDate date) {
int dow0 = date.getDayOfWeek().ordinal();
int doy0 = date.getDayOfYear() - 1;
int doyThu0 = doy0 + (3 - dow0); // adjust to mid-week Thursday (which is 3 indexed from zero)
int alignedWeek = doyThu0 / 7;
int firstThuDoy0 = doyThu0 - (alignedWeek * 7);
int firstMonDoy0 = firstThuDoy0 - 3;
if (firstMonDoy0 < -3) {
firstMonDoy0 += 7;
}
if (doy0 < firstMonDoy0) {
return (int) getWeekRange(date.withDayOfYear(180).minusYears(1)).getMaximum();
}
int week = ((doy0 - firstMonDoy0) / 7) + 1;
if (week == 53) {
if ((firstMonDoy0 == -3 || (firstMonDoy0 == -2 && date.isLeapYear())) == false) {
week = 1;
}
}
return week;
}
private static int getWeekBasedYear(LocalDate date) {
int year = date.getYear();
int doy = date.getDayOfYear();
if (doy <= 3) {
int dow = date.getDayOfWeek().ordinal();
if (doy - dow < -2) {
year--;
}
} else if (doy >= 363) {
int dow = date.getDayOfWeek().ordinal();
doy = doy - 363 - (date.isLeapYear() ? 1 : 0);
if (doy - dow >= 0) {
year++;
}
}
return year;
}
}
//-----------------------------------------------------------------------
/**
* Implementation of the unit.
*/
private static enum Unit implements TemporalUnit {
/**
* Unit that represents the concept of a week-based-year.
*/
WEEK_BASED_YEARS("WeekBasedYears", Duration.ofSeconds(31556952L)),
/**
* Unit that represents the concept of a quarter-year.
*/
QUARTER_YEARS("QuarterYears", Duration.ofSeconds(31556952L / 4));
private final String name;
private final Duration duration;
private Unit(String name, Duration estimatedDuration) {
this.name = name;
this.duration = estimatedDuration;
}
@Override
public Duration getDuration() {
return duration;
}
@Override
public boolean isDurationEstimated() {
return true;
}
@Override
public boolean isDateBased() {
return true;
}
@Override
public boolean isTimeBased() {
return false;
}
@Override
public boolean isSupportedBy(Temporal temporal) {
return temporal.isSupported(EPOCH_DAY) && isIso(temporal);
}
@SuppressWarnings("unchecked")
@Override
public <R extends Temporal> R addTo(R temporal, long amount) {
switch (this) {
case WEEK_BASED_YEARS:
return (R) temporal.with(WEEK_BASED_YEAR,
Math.addExact(temporal.get(WEEK_BASED_YEAR), amount));
case QUARTER_YEARS:
// no overflow (256 is multiple of 4)
return (R) temporal.plus(amount / 256, YEARS)
.plus((amount % 256) * 3, MONTHS);
default:
throw new IllegalStateException("Unreachable");
}
}
@Override
public long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive) {
if (temporal1Inclusive.getClass() != temporal2Exclusive.getClass()) {
return temporal1Inclusive.until(temporal2Exclusive, this);
}
switch(this) {
case WEEK_BASED_YEARS:
return Math.subtractExact(temporal2Exclusive.getLong(WEEK_BASED_YEAR),
temporal1Inclusive.getLong(WEEK_BASED_YEAR));
case QUARTER_YEARS:
return temporal1Inclusive.until(temporal2Exclusive, MONTHS) / 3;
default:
throw new IllegalStateException("Unreachable");
}
}
@Override
public String toString() {
return name;
}
}
static boolean isIso(TemporalAccessor temporal) {
return Chronology.from(temporal).equals(IsoChronology.INSTANCE);
}
}

View file

@ -0,0 +1,314 @@
/*
* Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package java.time.temporal;
import static java.time.temporal.ChronoField.EPOCH_DAY;
import static java.time.temporal.ChronoUnit.DAYS;
import static java.time.temporal.ChronoUnit.FOREVER;
import java.time.DateTimeException;
import java.time.chrono.ChronoLocalDate;
import java.time.chrono.Chronology;
import java.time.format.ResolverStyle;
import java.util.Map;
/**
* A set of date fields that provide access to Julian Days.
* <p>
* The Julian Day is a standard way of expressing date and time commonly used in the scientific community.
* It is expressed as a decimal number of whole days where days start at midday.
* This class represents variations on Julian Days that count whole days from midnight.
* <p>
* The fields are implemented relative to {@link ChronoField#EPOCH_DAY EPOCH_DAY}.
* The fields are supported, and can be queried and set if {@code EPOCH_DAY} is available.
* The fields work with all chronologies.
*
* @implSpec
* This is an immutable and thread-safe class.
*
* @since 1.8
*/
public final class JulianFields {
/**
* The offset from Julian to EPOCH DAY.
*/
private static final long JULIAN_DAY_OFFSET = 2440588L;
/**
* Julian Day field.
* <p>
* This is an integer-based version of the Julian Day Number.
* Julian Day is a well-known system that represents the count of whole days since day 0,
* which is defined to be January 1, 4713 BCE in the Julian calendar, and -4713-11-24 Gregorian.
* The field has "JulianDay" as 'name', and 'DAYS' as 'baseUnit'.
* The field always refers to the local date-time, ignoring the offset or zone.
* <p>
* For date-times, 'JULIAN_DAY.getFrom()' assumes the same value from
* midnight until just before the next midnight.
* When 'JULIAN_DAY.adjustInto()' is applied to a date-time, the time of day portion remains unaltered.
* 'JULIAN_DAY.adjustInto()' and 'JULIAN_DAY.getFrom()' only apply to {@code Temporal} objects that
* can be converted into {@link ChronoField#EPOCH_DAY}.
* An {@link UnsupportedTemporalTypeException} is thrown for any other type of object.
* <p>
* In the resolving phase of parsing, a date can be created from a Julian Day field.
* In {@linkplain ResolverStyle#STRICT strict mode} and {@linkplain ResolverStyle#SMART smart mode}
* the Julian Day value is validated against the range of valid values.
* In {@linkplain ResolverStyle#LENIENT lenient mode} no validation occurs.
*
* <h3>Astronomical and Scientific Notes</h3>
* The standard astronomical definition uses a fraction to indicate the time-of-day,
* where each day is counted from midday to midday. For example,
* a fraction of 0 represents midday, a fraction of 0.25
* represents 18:00, a fraction of 0.5 represents midnight and a fraction
* of 0.75 represents 06:00.
* <p>
* By contrast, this implementation has no fractional part, and counts
* days from midnight to midnight.
* This implementation uses an integer and days starting at midnight.
* The integer value for the Julian Day Number is the astronomical Julian Day value at midday
* of the date in question.
* This amounts to the astronomical Julian Day, rounded to an integer {@code JDN = floor(JD + 0.5)}.
*
* <pre>
* | ISO date | Julian Day Number | Astronomical Julian Day |
* | 1970-01-01T00:00 | 2,440,588 | 2,440,587.5 |
* | 1970-01-01T06:00 | 2,440,588 | 2,440,587.75 |
* | 1970-01-01T12:00 | 2,440,588 | 2,440,588.0 |
* | 1970-01-01T18:00 | 2,440,588 | 2,440,588.25 |
* | 1970-01-02T00:00 | 2,440,589 | 2,440,588.5 |
* | 1970-01-02T06:00 | 2,440,589 | 2,440,588.75 |
* | 1970-01-02T12:00 | 2,440,589 | 2,440,589.0 |
* </pre>
* <p>
* Julian Days are sometimes taken to imply Universal Time or UTC, but this
* implementation always uses the Julian Day number for the local date,
* regardless of the offset or time-zone.
*/
public static final TemporalField JULIAN_DAY = Field.JULIAN_DAY;
/**
* Modified Julian Day field.
* <p>
* This is an integer-based version of the Modified Julian Day Number.
* Modified Julian Day (MJD) is a well-known system that counts days continuously.
* It is defined relative to astronomical Julian Day as {@code MJD = JD - 2400000.5}.
* Each Modified Julian Day runs from midnight to midnight.
* The field always refers to the local date-time, ignoring the offset or zone.
* <p>
* For date-times, 'MODIFIED_JULIAN_DAY.getFrom()' assumes the same value from
* midnight until just before the next midnight.
* When 'MODIFIED_JULIAN_DAY.adjustInto()' is applied to a date-time, the time of day portion remains unaltered.
* 'MODIFIED_JULIAN_DAY.adjustInto()' and 'MODIFIED_JULIAN_DAY.getFrom()' only apply to {@code Temporal} objects
* that can be converted into {@link ChronoField#EPOCH_DAY}.
* An {@link UnsupportedTemporalTypeException} is thrown for any other type of object.
* <p>
* This implementation is an integer version of MJD with the decimal part rounded to floor.
* <p>
* In the resolving phase of parsing, a date can be created from a Modified Julian Day field.
* In {@linkplain ResolverStyle#STRICT strict mode} and {@linkplain ResolverStyle#SMART smart mode}
* the Modified Julian Day value is validated against the range of valid values.
* In {@linkplain ResolverStyle#LENIENT lenient mode} no validation occurs.
*
* <h3>Astronomical and Scientific Notes</h3>
* <pre>
* | ISO date | Modified Julian Day | Decimal MJD |
* | 1970-01-01T00:00 | 40,587 | 40,587.0 |
* | 1970-01-01T06:00 | 40,587 | 40,587.25 |
* | 1970-01-01T12:00 | 40,587 | 40,587.5 |
* | 1970-01-01T18:00 | 40,587 | 40,587.75 |
* | 1970-01-02T00:00 | 40,588 | 40,588.0 |
* | 1970-01-02T06:00 | 40,588 | 40,588.25 |
* | 1970-01-02T12:00 | 40,588 | 40,588.5 |
* </pre>
*
* Modified Julian Days are sometimes taken to imply Universal Time or UTC, but this
* implementation always uses the Modified Julian Day for the local date,
* regardless of the offset or time-zone.
*/
public static final TemporalField MODIFIED_JULIAN_DAY = Field.MODIFIED_JULIAN_DAY;
/**
* Rata Die field.
* <p>
* Rata Die counts whole days continuously starting day 1 at midnight at the beginning of 0001-01-01 (ISO).
* The field always refers to the local date-time, ignoring the offset or zone.
* <p>
* For date-times, 'RATA_DIE.getFrom()' assumes the same value from
* midnight until just before the next midnight.
* When 'RATA_DIE.adjustInto()' is applied to a date-time, the time of day portion remains unaltered.
* 'RATA_DIE.adjustInto()' and 'RATA_DIE.getFrom()' only apply to {@code Temporal} objects
* that can be converted into {@link ChronoField#EPOCH_DAY}.
* An {@link UnsupportedTemporalTypeException} is thrown for any other type of object.
* <p>
* In the resolving phase of parsing, a date can be created from a Rata Die field.
* In {@linkplain ResolverStyle#STRICT strict mode} and {@linkplain ResolverStyle#SMART smart mode}
* the Rata Die value is validated against the range of valid values.
* In {@linkplain ResolverStyle#LENIENT lenient mode} no validation occurs.
*/
public static final TemporalField RATA_DIE = Field.RATA_DIE;
/**
* Restricted constructor.
*/
private JulianFields() {
throw new AssertionError("Not instantiable");
}
/**
* Implementation of JulianFields. Each instance is a singleton.
*/
private static enum Field implements TemporalField {
JULIAN_DAY("JulianDay", DAYS, FOREVER, JULIAN_DAY_OFFSET),
MODIFIED_JULIAN_DAY("ModifiedJulianDay", DAYS, FOREVER, 40587L),
RATA_DIE("RataDie", DAYS, FOREVER, 719163L);
private static final long serialVersionUID = -7501623920830201812L;
private final transient String name;
private final transient TemporalUnit baseUnit;
private final transient TemporalUnit rangeUnit;
private final transient ValueRange range;
private final transient long offset;
private Field(String name, TemporalUnit baseUnit, TemporalUnit rangeUnit, long offset) {
this.name = name;
this.baseUnit = baseUnit;
this.rangeUnit = rangeUnit;
this.range = ValueRange.of(-365243219162L + offset, 365241780471L + offset);
this.offset = offset;
}
//-----------------------------------------------------------------------
@Override
public TemporalUnit getBaseUnit() {
return baseUnit;
}
@Override
public TemporalUnit getRangeUnit() {
return rangeUnit;
}
@Override
public boolean isDateBased() {
return true;
}
@Override
public boolean isTimeBased() {
return false;
}
@Override
public ValueRange range() {
return range;
}
//-----------------------------------------------------------------------
@Override
public boolean isSupportedBy(TemporalAccessor temporal) {
return temporal.isSupported(EPOCH_DAY);
}
@Override
public ValueRange rangeRefinedBy(TemporalAccessor temporal) {
if (isSupportedBy(temporal) == false) {
throw new DateTimeException("Unsupported field: " + this);
}
return range();
}
@Override
public long getFrom(TemporalAccessor temporal) {
return temporal.getLong(EPOCH_DAY) + offset;
}
@SuppressWarnings("unchecked")
@Override
public <R extends Temporal> R adjustInto(R temporal, long newValue) {
if (range().isValidValue(newValue) == false) {
throw new DateTimeException("Invalid value: " + name + " " + newValue);
}
return (R) temporal.with(EPOCH_DAY, Math.subtractExact(newValue, offset));
}
//-----------------------------------------------------------------------
@Override
public ChronoLocalDate resolve(
Map<TemporalField, Long> fieldValues, TemporalAccessor partialTemporal, ResolverStyle resolverStyle) {
long value = fieldValues.remove(this);
Chronology chrono = Chronology.from(partialTemporal);
if (resolverStyle == ResolverStyle.LENIENT) {
return chrono.dateEpochDay(Math.subtractExact(value, offset));
}
range().checkValidValue(value, this);
return chrono.dateEpochDay(value - offset);
}
//-----------------------------------------------------------------------
@Override
public String toString() {
return name;
}
}
}

View file

@ -0,0 +1,449 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package java.time.temporal;
import java.time.DateTimeException;
/**
* Framework-level interface defining read-write access to a temporal object,
* such as a date, time, offset or some combination of these.
* <p>
* This is the base interface type for date, time and offset objects that
* are complete enough to be manipulated using plus and minus.
* It is implemented by those classes that can provide and manipulate information
* as {@linkplain TemporalField fields} or {@linkplain TemporalQuery queries}.
* See {@link TemporalAccessor} for the read-only version of this interface.
* <p>
* Most date and time information can be represented as a number.
* These are modeled using {@code TemporalField} with the number held using
* a {@code long} to handle large values. Year, month and day-of-month are
* simple examples of fields, but they also include instant and offsets.
* See {@link ChronoField} for the standard set of fields.
* <p>
* Two pieces of date/time information cannot be represented by numbers,
* the {@linkplain java.time.chrono.Chronology chronology} and the
* {@linkplain java.time.ZoneId time-zone}.
* These can be accessed via {@link #query(TemporalQuery) queries} using
* the static methods defined on {@link TemporalQuery}.
* <p>
* This interface is a framework-level interface that should not be widely
* used in application code. Instead, applications should create and pass
* around instances of concrete types, such as {@code LocalDate}.
* There are many reasons for this, part of which is that implementations
* of this interface may be in calendar systems other than ISO.
* See {@link java.time.chrono.ChronoLocalDate} for a fuller discussion of the issues.
*
* <h3>When to implement</h3>
* <p>
* A class should implement this interface if it meets three criteria:
* <ul>
* <li>it provides access to date/time/offset information, as per {@code TemporalAccessor}
* <li>the set of fields are contiguous from the largest to the smallest
* <li>the set of fields are complete, such that no other field is needed to define the
* valid range of values for the fields that are represented
* </ul>
* <p>
* Four examples make this clear:
* <ul>
* <li>{@code LocalDate} implements this interface as it represents a set of fields
* that are contiguous from days to forever and require no external information to determine
* the validity of each date. It is therefore able to implement plus/minus correctly.
* <li>{@code LocalTime} implements this interface as it represents a set of fields
* that are contiguous from nanos to within days and require no external information to determine
* validity. It is able to implement plus/minus correctly, by wrapping around the day.
* <li>{@code MonthDay}, the combination of month-of-year and day-of-month, does not implement
* this interface. While the combination is contiguous, from days to months within years,
* the combination does not have sufficient information to define the valid range of values
* for day-of-month. As such, it is unable to implement plus/minus correctly.
* <li>The combination day-of-week and day-of-month ("Friday the 13th") should not implement
* this interface. It does not represent a contiguous set of fields, as days to weeks overlaps
* days to months.
* </ul>
*
* @implSpec
* This interface places no restrictions on the mutability of implementations,
* however immutability is strongly recommended.
* All implementations must be {@link Comparable}.
*
* @since 1.8
*/
public interface Temporal extends TemporalAccessor {
/**
* Checks if the specified unit is supported.
* <p>
* This checks if the specified unit can be added to, or subtracted from, this date-time.
* If false, then calling the {@link #plus(long, TemporalUnit)} and
* {@link #minus(long, TemporalUnit) minus} methods will throw an exception.
*
* @implSpec
* Implementations must check and handle all units defined in {@link ChronoUnit}.
* If the unit is supported, then true must be returned, otherwise false must be returned.
* <p>
* If the field is not a {@code ChronoUnit}, then the result of this method
* is obtained by invoking {@code TemporalUnit.isSupportedBy(Temporal)}
* passing {@code this} as the argument.
* <p>
* Implementations must ensure that no observable state is altered when this
* read-only method is invoked.
*
* @param unit the unit to check, null returns false
* @return true if the unit can be added/subtracted, false if not
*/
boolean isSupported(TemporalUnit unit);
/**
* Returns an adjusted object of the same type as this object with the adjustment made.
* <p>
* This adjusts this date-time according to the rules of the specified adjuster.
* A simple adjuster might simply set the one of the fields, such as the year field.
* A more complex adjuster might set the date to the last day of the month.
* A selection of common adjustments is provided in
* {@link java.time.temporal.TemporalAdjusters TemporalAdjusters}.
* These include finding the "last day of the month" and "next Wednesday".
* The adjuster is responsible for handling special cases, such as the varying
* lengths of month and leap years.
* <p>
* Some example code indicating how and why this method is used:
* <pre>
* date = date.with(Month.JULY); // most key classes implement TemporalAdjuster
* date = date.with(lastDayOfMonth()); // static import from Adjusters
* date = date.with(next(WEDNESDAY)); // static import from Adjusters and DayOfWeek
* </pre>
*
* @implSpec
* <p>
* Implementations must not alter either this object or the specified temporal object.
* Instead, an adjusted copy of the original must be returned.
* This provides equivalent, safe behavior for immutable and mutable implementations.
* <p>
* The default implementation must behave equivalent to this code:
* <pre>
* return adjuster.adjustInto(this);
* </pre>
*
* @param adjuster the adjuster to use, not null
* @return an object of the same type with the specified adjustment made, not null
* @throws DateTimeException if unable to make the adjustment
* @throws ArithmeticException if numeric overflow occurs
*/
default Temporal with(TemporalAdjuster adjuster) {
return adjuster.adjustInto(this);
}
/**
* Returns an object of the same type as this object with the specified field altered.
* <p>
* This returns a new object based on this one with the value for the specified field changed.
* For example, on a {@code LocalDate}, this could be used to set the year, month or day-of-month.
* The returned object will have the same observable type as this object.
* <p>
* In some cases, changing a field is not fully defined. For example, if the target object is
* a date representing the 31st January, then changing the month to February would be unclear.
* In cases like this, the field is responsible for resolving the result. Typically it will choose
* the previous valid date, which would be the last valid day of February in this example.
*
* @implSpec
* Implementations must check and handle all fields defined in {@link ChronoField}.
* If the field is supported, then the adjustment must be performed.
* If unsupported, then an {@code UnsupportedTemporalTypeException} must be thrown.
* <p>
* If the field is not a {@code ChronoField}, then the result of this method
* is obtained by invoking {@code TemporalField.adjustInto(Temporal, long)}
* passing {@code this} as the first argument.
* <p>
* Implementations must not alter this object.
* Instead, an adjusted copy of the original must be returned.
* This provides equivalent, safe behavior for immutable and mutable implementations.
*
* @param field the field to set in the result, not null
* @param newValue the new value of the field in the result
* @return an object of the same type with the specified field set, not null
* @throws DateTimeException if the field cannot be set
* @throws UnsupportedTemporalTypeException if the field is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
Temporal with(TemporalField field, long newValue);
//-----------------------------------------------------------------------
/**
* Returns an object of the same type as this object with an amount added.
* <p>
* This adjusts this temporal, adding according to the rules of the specified amount.
* The amount is typically a {@link java.time.Period} but may be any other type implementing
* the {@link TemporalAmount} interface, such as {@link java.time.Duration}.
* <p>
* Some example code indicating how and why this method is used:
* <pre>
* date = date.plus(period); // add a Period instance
* date = date.plus(duration); // add a Duration instance
* date = date.plus(workingDays(6)); // example user-written workingDays method
* </pre>
* <p>
* Note that calling {@code plus} followed by {@code minus} is not guaranteed to
* return the same date-time.
*
* @implSpec
* <p>
* Implementations must not alter either this object or the specified temporal object.
* Instead, an adjusted copy of the original must be returned.
* This provides equivalent, safe behavior for immutable and mutable implementations.
* <p>
* The default implementation must behave equivalent to this code:
* <pre>
* return amount.addTo(this);
* </pre>
*
* @param amount the amount to add, not null
* @return an object of the same type with the specified adjustment made, not null
* @throws DateTimeException if the addition cannot be made
* @throws ArithmeticException if numeric overflow occurs
*/
default Temporal plus(TemporalAmount amount) {
return amount.addTo(this);
}
/**
* Returns an object of the same type as this object with the specified period added.
* <p>
* This method returns a new object based on this one with the specified period added.
* For example, on a {@code LocalDate}, this could be used to add a number of years, months or days.
* The returned object will have the same observable type as this object.
* <p>
* In some cases, changing a field is not fully defined. For example, if the target object is
* a date representing the 31st January, then adding one month would be unclear.
* In cases like this, the field is responsible for resolving the result. Typically it will choose
* the previous valid date, which would be the last valid day of February in this example.
*
* @implSpec
* Implementations must check and handle all units defined in {@link ChronoUnit}.
* If the unit is supported, then the addition must be performed.
* If unsupported, then an {@code UnsupportedTemporalTypeException} must be thrown.
* <p>
* If the unit is not a {@code ChronoUnit}, then the result of this method
* is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)}
* passing {@code this} as the first argument.
* <p>
* Implementations must not alter this object.
* Instead, an adjusted copy of the original must be returned.
* This provides equivalent, safe behavior for immutable and mutable implementations.
*
* @param amountToAdd the amount of the specified unit to add, may be negative
* @param unit the unit of the amount to add, not null
* @return an object of the same type with the specified period added, not null
* @throws DateTimeException if the unit cannot be added
* @throws UnsupportedTemporalTypeException if the unit is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
Temporal plus(long amountToAdd, TemporalUnit unit);
//-----------------------------------------------------------------------
/**
* Returns an object of the same type as this object with an amount subtracted.
* <p>
* This adjusts this temporal, subtracting according to the rules of the specified amount.
* The amount is typically a {@link java.time.Period} but may be any other type implementing
* the {@link TemporalAmount} interface, such as {@link java.time.Duration}.
* <p>
* Some example code indicating how and why this method is used:
* <pre>
* date = date.minus(period); // subtract a Period instance
* date = date.minus(duration); // subtract a Duration instance
* date = date.minus(workingDays(6)); // example user-written workingDays method
* </pre>
* <p>
* Note that calling {@code plus} followed by {@code minus} is not guaranteed to
* return the same date-time.
*
* @implSpec
* <p>
* Implementations must not alter either this object or the specified temporal object.
* Instead, an adjusted copy of the original must be returned.
* This provides equivalent, safe behavior for immutable and mutable implementations.
* <p>
* The default implementation must behave equivalent to this code:
* <pre>
* return amount.subtractFrom(this);
* </pre>
*
* @param amount the amount to subtract, not null
* @return an object of the same type with the specified adjustment made, not null
* @throws DateTimeException if the subtraction cannot be made
* @throws ArithmeticException if numeric overflow occurs
*/
default Temporal minus(TemporalAmount amount) {
return amount.subtractFrom(this);
}
/**
* Returns an object of the same type as this object with the specified period subtracted.
* <p>
* This method returns a new object based on this one with the specified period subtracted.
* For example, on a {@code LocalDate}, this could be used to subtract a number of years, months or days.
* The returned object will have the same observable type as this object.
* <p>
* In some cases, changing a field is not fully defined. For example, if the target object is
* a date representing the 31st March, then subtracting one month would be unclear.
* In cases like this, the field is responsible for resolving the result. Typically it will choose
* the previous valid date, which would be the last valid day of February in this example.
*
* @implSpec
* Implementations must behave in a manor equivalent to the default method behavior.
* <p>
* Implementations must not alter this object.
* Instead, an adjusted copy of the original must be returned.
* This provides equivalent, safe behavior for immutable and mutable implementations.
* <p>
* The default implementation must behave equivalent to this code:
* <pre>
* return (amountToSubtract == Long.MIN_VALUE ?
* plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit));
* </pre>
*
* @param amountToSubtract the amount of the specified unit to subtract, may be negative
* @param unit the unit of the amount to subtract, not null
* @return an object of the same type with the specified period subtracted, not null
* @throws DateTimeException if the unit cannot be subtracted
* @throws UnsupportedTemporalTypeException if the unit is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
default Temporal minus(long amountToSubtract, TemporalUnit unit) {
return (amountToSubtract == Long.MIN_VALUE ? plus(Long.MAX_VALUE, unit).plus(1, unit) : plus(-amountToSubtract, unit));
}
//-----------------------------------------------------------------------
/**
* Calculates the amount of time until another temporal in terms of the specified unit.
* <p>
* This calculates the amount of time between two temporal objects
* in terms of a single {@code TemporalUnit}.
* The start and end points are {@code this} and the specified temporal.
* The end point is converted to be of the same type as the start point if different.
* The result will be negative if the end is before the start.
* For example, the amount in hours between two temporal objects can be
* calculated using {@code startTime.until(endTime, HOURS)}.
* <p>
* The calculation returns a whole number, representing the number of
* complete units between the two temporals.
* For example, the amount in hours between the times 11:30 and 13:29
* will only be one hour as it is one minute short of two hours.
* <p>
* There are two equivalent ways of using this method.
* The first is to invoke this method directly.
* The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:
* <pre>
* // these two lines are equivalent
* temporal = start.until(end, unit);
* temporal = unit.between(start, end);
* </pre>
* The choice should be made based on which makes the code more readable.
* <p>
* For example, this method allows the number of days between two dates to
* be calculated:
* <pre>
* long daysBetween = start.until(end, DAYS);
* // or alternatively
* long daysBetween = DAYS.between(start, end);
* </pre>
*
* @implSpec
* Implementations must begin by checking to ensure that the input temporal
* object is of the same observable type as the implementation.
* They must then perform the calculation for all instances of {@link ChronoUnit}.
* An {@code UnsupportedTemporalTypeException} must be thrown for {@code ChronoUnit}
* instances that are unsupported.
* <p>
* If the unit is not a {@code ChronoUnit}, then the result of this method
* is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}
* passing {@code this} as the first argument and the converted input temporal as
* the second argument.
* <p>
* In summary, implementations must behave in a manner equivalent to this pseudo-code:
* <pre>
* // convert the end temporal to the same type as this class
* if (unit instanceof ChronoUnit) {
* // if unit is supported, then calculate and return result
* // else throw UnsupportedTemporalTypeException for unsupported units
* }
* return unit.between(this, convertedEndTemporal);
* </pre>
* <p>
* Note that the unit's {@code between} method must only be invoked if the
* two temporal objects have exactly the same type evaluated by {@code getClass()}.
* <p>
* Implementations must ensure that no observable state is altered when this
* read-only method is invoked.
*
* @param endExclusive the end temporal, exclusive, converted to be of the
* same type as this object, not null
* @param unit the unit to measure the amount in, not null
* @return the amount of time between this temporal object and the specified one
* in terms of the unit; positive if the specified object is later than this one,
* negative if it is earlier than this one
* @throws DateTimeException if the amount cannot be calculated, or the end
* temporal cannot be converted to the same type as this temporal
* @throws UnsupportedTemporalTypeException if the unit is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
long until(Temporal endExclusive, TemporalUnit unit);
}

View file

@ -0,0 +1,317 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package java.time.temporal;
import java.time.DateTimeException;
import java.util.Objects;
/**
* Framework-level interface defining read-only access to a temporal object,
* such as a date, time, offset or some combination of these.
* <p>
* This is the base interface type for date, time and offset objects.
* It is implemented by those classes that can provide information
* as {@linkplain TemporalField fields} or {@linkplain TemporalQuery queries}.
* <p>
* Most date and time information can be represented as a number.
* These are modeled using {@code TemporalField} with the number held using
* a {@code long} to handle large values. Year, month and day-of-month are
* simple examples of fields, but they also include instant and offsets.
* See {@link ChronoField} for the standard set of fields.
* <p>
* Two pieces of date/time information cannot be represented by numbers,
* the {@linkplain java.time.chrono.Chronology chronology} and the
* {@linkplain java.time.ZoneId time-zone}.
* These can be accessed via {@linkplain #query(TemporalQuery) queries} using
* the static methods defined on {@link TemporalQuery}.
* <p>
* A sub-interface, {@link Temporal}, extends this definition to one that also
* supports adjustment and manipulation on more complete temporal objects.
* <p>
* This interface is a framework-level interface that should not be widely
* used in application code. Instead, applications should create and pass
* around instances of concrete types, such as {@code LocalDate}.
* There are many reasons for this, part of which is that implementations
* of this interface may be in calendar systems other than ISO.
* See {@link java.time.chrono.ChronoLocalDate} for a fuller discussion of the issues.
*
* @implSpec
* This interface places no restrictions on the mutability of implementations,
* however immutability is strongly recommended.
*
* @since 1.8
*/
public interface TemporalAccessor {
/**
* Checks if the specified field is supported.
* <p>
* This checks if the date-time can be queried for the specified field.
* If false, then calling the {@link #range(TemporalField) range} and {@link #get(TemporalField) get}
* methods will throw an exception.
*
* @implSpec
* Implementations must check and handle all fields defined in {@link ChronoField}.
* If the field is supported, then true must be returned, otherwise false must be returned.
* <p>
* If the field is not a {@code ChronoField}, then the result of this method
* is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
* passing {@code this} as the argument.
* <p>
* Implementations must ensure that no observable state is altered when this
* read-only method is invoked.
*
* @param field the field to check, null returns false
* @return true if this date-time can be queried for the field, false if not
*/
boolean isSupported(TemporalField field);
/**
* Gets the range of valid values for the specified field.
* <p>
* All fields can be expressed as a {@code long} integer.
* This method returns an object that describes the valid range for that value.
* The value of this temporal object is used to enhance the accuracy of the returned range.
* If the date-time cannot return the range, because the field is unsupported or for
* some other reason, an exception will be thrown.
* <p>
* Note that the result only describes the minimum and maximum valid values
* and it is important not to read too much into them. For example, there
* could be values within the range that are invalid for the field.
*
* @implSpec
* Implementations must check and handle all fields defined in {@link ChronoField}.
* If the field is supported, then the range of the field must be returned.
* If unsupported, then an {@code UnsupportedTemporalTypeException} must be thrown.
* <p>
* If the field is not a {@code ChronoField}, then the result of this method
* is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessorl)}
* passing {@code this} as the argument.
* <p>
* Implementations must ensure that no observable state is altered when this
* read-only method is invoked.
* <p>
* The default implementation must behave equivalent to this code:
* <pre>
* if (field instanceof ChronoField) {
* if (isSupported(field)) {
* return field.range();
* }
* throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
* }
* return field.rangeRefinedBy(this);
* </pre>
*
* @param field the field to query the range for, not null
* @return the range of valid values for the field, not null
* @throws DateTimeException if the range for the field cannot be obtained
* @throws UnsupportedTemporalTypeException if the field is not supported
*/
default ValueRange range(TemporalField field) {
if (field instanceof ChronoField) {
if (isSupported(field)) {
return field.range();
}
throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
}
Objects.requireNonNull(field, "field");
return field.rangeRefinedBy(this);
}
/**
* Gets the value of the specified field as an {@code int}.
* <p>
* This queries the date-time for the value of the specified field.
* The returned value will always be within the valid range of values for the field.
* If the date-time cannot return the value, because the field is unsupported or for
* some other reason, an exception will be thrown.
*
* @implSpec
* Implementations must check and handle all fields defined in {@link ChronoField}.
* If the field is supported and has an {@code int} range, then the value of
* the field must be returned.
* If unsupported, then an {@code UnsupportedTemporalTypeException} must be thrown.
* <p>
* If the field is not a {@code ChronoField}, then the result of this method
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
* passing {@code this} as the argument.
* <p>
* Implementations must ensure that no observable state is altered when this
* read-only method is invoked.
* <p>
* The default implementation must behave equivalent to this code:
* <pre>
* if (range(field).isIntValue()) {
* return range(field).checkValidIntValue(getLong(field), field);
* }
* throw new UnsupportedTemporalTypeException("Invalid field " + field + " + for get() method, use getLong() instead");
* </pre>
*
* @param field the field to get, not null
* @return the value for the field, within the valid range of values
* @throws DateTimeException if a value for the field cannot be obtained or
* the value is outside the range of valid values for the field
* @throws UnsupportedTemporalTypeException if the field is not supported or
* the range of values exceeds an {@code int}
* @throws ArithmeticException if numeric overflow occurs
*/
default int get(TemporalField field) {
ValueRange range = range(field);
if (range.isIntValue() == false) {
throw new UnsupportedTemporalTypeException("Invalid field " + field + " for get() method, use getLong() instead");
}
long value = getLong(field);
if (range.isValidValue(value) == false) {
throw new DateTimeException("Invalid value for " + field + " (valid values " + range + "): " + value);
}
return (int) value;
}
/**
* Gets the value of the specified field as a {@code long}.
* <p>
* This queries the date-time for the value of the specified field.
* The returned value may be outside the valid range of values for the field.
* If the date-time cannot return the value, because the field is unsupported or for
* some other reason, an exception will be thrown.
*
* @implSpec
* Implementations must check and handle all fields defined in {@link ChronoField}.
* If the field is supported, then the value of the field must be returned.
* If unsupported, then an {@code UnsupportedTemporalTypeException} must be thrown.
* <p>
* If the field is not a {@code ChronoField}, then the result of this method
* is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
* passing {@code this} as the argument.
* <p>
* Implementations must ensure that no observable state is altered when this
* read-only method is invoked.
*
* @param field the field to get, not null
* @return the value for the field
* @throws DateTimeException if a value for the field cannot be obtained
* @throws UnsupportedTemporalTypeException if the field is not supported
* @throws ArithmeticException if numeric overflow occurs
*/
long getLong(TemporalField field);
/**
* Queries this date-time.
* <p>
* This queries this date-time using the specified query strategy object.
* <p>
* Queries are a key tool for extracting information from date-times.
* They exists to externalize the process of querying, permitting different
* approaches, as per the strategy design pattern.
* Examples might be a query that checks if the date is the day before February 29th
* in a leap year, or calculates the number of days to your next birthday.
* <p>
* The most common query implementations are method references, such as
* {@code LocalDate::from} and {@code ZoneId::from}.
* Additional implementations are provided as static methods on {@link TemporalQuery}.
*
* @implSpec
* The default implementation must behave equivalent to this code:
* <pre>
* if (query == TemporalQueries.zoneId() ||
* query == TemporalQueries.chronology() || query == TemporalQueries.precision()) {
* return null;
* }
* return query.queryFrom(this);
* </pre>
* Future versions are permitted to add further queries to the if statement.
* <p>
* All classes implementing this interface and overriding this method must call
* {@code TemporalAccessor.super.query(query)}. JDK classes may avoid calling
* super if they provide behavior equivalent to the default behaviour, however
* non-JDK classes may not utilize this optimization and must call {@code super}.
* <p>
* If the implementation can supply a value for one of the queries listed in the
* if statement of the default implementation, then it must do so.
* For example, an application-defined {@code HourMin} class storing the hour
* and minute must override this method as follows:
* <pre>
* if (query == TemporalQueries.precision()) {
* return MINUTES;
* }
* return TemporalAccessor.super.query(query);
* </pre>
* <p>
* Implementations must ensure that no observable state is altered when this
* read-only method is invoked.
*
* @param <R> the type of the result
* @param query the query to invoke, not null
* @return the query result, null may be returned (defined by the query)
* @throws DateTimeException if unable to query
* @throws ArithmeticException if numeric overflow occurs
*/
default <R> R query(TemporalQuery<R> query) {
if (query == TemporalQueries.zoneId()
|| query == TemporalQueries.chronology()
|| query == TemporalQueries.precision()) {
return null;
}
return query.queryFrom(this);
}
}

View file

@ -0,0 +1,152 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package java.time.temporal;
import java.time.DateTimeException;
/**
* Strategy for adjusting a temporal object.
* <p>
* Adjusters are a key tool for modifying temporal objects.
* They exist to externalize the process of adjustment, permitting different
* approaches, as per the strategy design pattern.
* Examples might be an adjuster that sets the date avoiding weekends, or one that
* sets the date to the last day of the month.
* <p>
* There are two equivalent ways of using a {@code TemporalAdjuster}.
* The first is to invoke the method on this interface directly.
* The second is to use {@link Temporal#with(TemporalAdjuster)}:
* <pre>
* // these two lines are equivalent, but the second approach is recommended
* temporal = thisAdjuster.adjustInto(temporal);
* temporal = temporal.with(thisAdjuster);
* </pre>
* It is recommended to use the second approach, {@code with(TemporalAdjuster)},
* as it is a lot clearer to read in code.
* <p>
* The {@link TemporalAdjusters} class contains a standard set of adjusters,
* available as static methods.
* These include:
* <ul>
* <li>finding the first or last day of the month
* <li>finding the first day of next month
* <li>finding the first or last day of the year
* <li>finding the first day of next year
* <li>finding the first or last day-of-week within a month, such as "first Wednesday in June"
* <li>finding the next or previous day-of-week, such as "next Thursday"
* </ul>
*
* @implSpec
* This interface places no restrictions on the mutability of implementations,
* however immutability is strongly recommended.
*
* @see TemporalAdjusters
* @since 1.8
*/
@FunctionalInterface
public interface TemporalAdjuster {
/**
* Adjusts the specified temporal object.
* <p>
* This adjusts the specified temporal object using the logic
* encapsulated in the implementing class.
* Examples might be an adjuster that sets the date avoiding weekends, or one that
* sets the date to the last day of the month.
* <p>
* There are two equivalent ways of using this method.
* The first is to invoke this method directly.
* The second is to use {@link Temporal#with(TemporalAdjuster)}:
* <pre>
* // these two lines are equivalent, but the second approach is recommended
* temporal = thisAdjuster.adjustInto(temporal);
* temporal = temporal.with(thisAdjuster);
* </pre>
* It is recommended to use the second approach, {@code with(TemporalAdjuster)},
* as it is a lot clearer to read in code.
*
* @implSpec
* The implementation must take the input object and adjust it.
* The implementation defines the logic of the adjustment and is responsible for
* documenting that logic. It may use any method on {@code Temporal} to
* query the temporal object and perform the adjustment.
* The returned object must have the same observable type as the input object
* <p>
* The input object must not be altered.
* Instead, an adjusted copy of the original must be returned.
* This provides equivalent, safe behavior for immutable and mutable temporal objects.
* <p>
* The input temporal object may be in a calendar system other than ISO.
* Implementations may choose to document compatibility with other calendar systems,
* or reject non-ISO temporal objects by {@link TemporalQueries#chronology() querying the chronology}.
* <p>
* This method may be called from multiple threads in parallel.
* It must be thread-safe when invoked.
*
* @param temporal the temporal object to adjust, not null
* @return an object of the same observable type with the adjustment made, not null
* @throws DateTimeException if unable to make the adjustment
* @throws ArithmeticException if numeric overflow occurs
*/
Temporal adjustInto(Temporal temporal);
}

View file

@ -0,0 +1,478 @@
/*
* Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Copyright (c) 2012-2013, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package java.time.temporal;
import static java.time.temporal.ChronoField.DAY_OF_MONTH;
import static java.time.temporal.ChronoField.DAY_OF_WEEK;
import static java.time.temporal.ChronoField.DAY_OF_YEAR;
import static java.time.temporal.ChronoUnit.DAYS;
import static java.time.temporal.ChronoUnit.MONTHS;
import static java.time.temporal.ChronoUnit.YEARS;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.util.Objects;
import java.util.function.UnaryOperator;
/**
* Common and useful TemporalAdjusters.
* <p>
* Adjusters are a key tool for modifying temporal objects.
* They exist to externalize the process of adjustment, permitting different
* approaches, as per the strategy design pattern.
* Examples might be an adjuster that sets the date avoiding weekends, or one that
* sets the date to the last day of the month.
* <p>
* There are two equivalent ways of using a {@code TemporalAdjuster}.
* The first is to invoke the method on the interface directly.
* The second is to use {@link Temporal#with(TemporalAdjuster)}:
* <pre>
* // these two lines are equivalent, but the second approach is recommended
* temporal = thisAdjuster.adjustInto(temporal);
* temporal = temporal.with(thisAdjuster);
* </pre>
* It is recommended to use the second approach, {@code with(TemporalAdjuster)},
* as it is a lot clearer to read in code.
* <p>
* This class contains a standard set of adjusters, available as static methods.
* These include:
* <ul>
* <li>finding the first or last day of the month
* <li>finding the first day of next month
* <li>finding the first or last day of the year
* <li>finding the first day of next year
* <li>finding the first or last day-of-week within a month, such as "first Wednesday in June"
* <li>finding the next or previous day-of-week, such as "next Thursday"
* </ul>
*
* @implSpec
* All the implementations supplied by the static methods are immutable.
*
* @see TemporalAdjuster
* @since 1.8
*/
public final class TemporalAdjusters {
/**
* Private constructor since this is a utility class.
*/
private TemporalAdjusters() {
}
//-----------------------------------------------------------------------
/**
* Obtains a {@code TemporalAdjuster} that wraps a date adjuster.
* <p>
* The {@code TemporalAdjuster} is based on the low level {@code Temporal} interface.
* This method allows an adjustment from {@code LocalDate} to {@code LocalDate}
* to be wrapped to match the temporal-based interface.
* This is provided for convenience to make user-written adjusters simpler.
* <p>
* In general, user-written adjusters should be static constants:
* <pre>{@code
* static TemporalAdjuster TWO_DAYS_LATER =
* TemporalAdjusters.ofDateAdjuster(date -> date.plusDays(2));
* }</pre>
*
* @param dateBasedAdjuster the date-based adjuster, not null
* @return the temporal adjuster wrapping on the date adjuster, not null
*/
public static TemporalAdjuster ofDateAdjuster(UnaryOperator<LocalDate> dateBasedAdjuster) {
Objects.requireNonNull(dateBasedAdjuster, "dateBasedAdjuster");
return (temporal) -> {
LocalDate input = LocalDate.from(temporal);
LocalDate output = dateBasedAdjuster.apply(input);
return temporal.with(output);
};
}
//-----------------------------------------------------------------------
/**
* Returns the "first day of month" adjuster, which returns a new date set to
* the first day of the current month.
* <p>
* The ISO calendar system behaves as follows:<br>
* The input 2011-01-15 will return 2011-01-01.<br>
* The input 2011-02-15 will return 2011-02-01.
* <p>
* The behavior is suitable for use with most calendar systems.
* It is equivalent to:
* <pre>
* temporal.with(DAY_OF_MONTH, 1);
* </pre>
*
* @return the first day-of-month adjuster, not null
*/
public static TemporalAdjuster firstDayOfMonth() {
return (temporal) -> temporal.with(DAY_OF_MONTH, 1);
}
/**
* Returns the "last day of month" adjuster, which returns a new date set to
* the last day of the current month.
* <p>
* The ISO calendar system behaves as follows:<br>
* The input 2011-01-15 will return 2011-01-31.<br>
* The input 2011-02-15 will return 2011-02-28.<br>
* The input 2012-02-15 will return 2012-02-29 (leap year).<br>
* The input 2011-04-15 will return 2011-04-30.
* <p>
* The behavior is suitable for use with most calendar systems.
* It is equivalent to:
* <pre>
* long lastDay = temporal.range(DAY_OF_MONTH).getMaximum();
* temporal.with(DAY_OF_MONTH, lastDay);
* </pre>
*
* @return the last day-of-month adjuster, not null
*/
public static TemporalAdjuster lastDayOfMonth() {
return (temporal) -> temporal.with(DAY_OF_MONTH, temporal.range(DAY_OF_MONTH).getMaximum());
}
/**
* Returns the "first day of next month" adjuster, which returns a new date set to
* the first day of the next month.
* <p>
* The ISO calendar system behaves as follows:<br>
* The input 2011-01-15 will return 2011-02-01.<br>
* The input 2011-02-15 will return 2011-03-01.
* <p>
* The behavior is suitable for use with most calendar systems.
* It is equivalent to:
* <pre>
* temporal.with(DAY_OF_MONTH, 1).plus(1, MONTHS);
* </pre>
*
* @return the first day of next month adjuster, not null
*/
public static TemporalAdjuster firstDayOfNextMonth() {
return (temporal) -> temporal.with(DAY_OF_MONTH, 1).plus(1, MONTHS);
}
//-----------------------------------------------------------------------
/**
* Returns the "first day of year" adjuster, which returns a new date set to
* the first day of the current year.
* <p>
* The ISO calendar system behaves as follows:<br>
* The input 2011-01-15 will return 2011-01-01.<br>
* The input 2011-02-15 will return 2011-01-01.<br>
* <p>
* The behavior is suitable for use with most calendar systems.
* It is equivalent to:
* <pre>
* temporal.with(DAY_OF_YEAR, 1);
* </pre>
*
* @return the first day-of-year adjuster, not null
*/
public static TemporalAdjuster firstDayOfYear() {
return (temporal) -> temporal.with(DAY_OF_YEAR, 1);
}
/**
* Returns the "last day of year" adjuster, which returns a new date set to
* the last day of the current year.
* <p>
* The ISO calendar system behaves as follows:<br>
* The input 2011-01-15 will return 2011-12-31.<br>
* The input 2011-02-15 will return 2011-12-31.<br>
* <p>
* The behavior is suitable for use with most calendar systems.
* It is equivalent to:
* <pre>
* long lastDay = temporal.range(DAY_OF_YEAR).getMaximum();
* temporal.with(DAY_OF_YEAR, lastDay);
* </pre>
*
* @return the last day-of-year adjuster, not null
*/
public static TemporalAdjuster lastDayOfYear() {
return (temporal) -> temporal.with(DAY_OF_YEAR, temporal.range(DAY_OF_YEAR).getMaximum());
}
/**
* Returns the "first day of next year" adjuster, which returns a new date set to
* the first day of the next year.
* <p>
* The ISO calendar system behaves as follows:<br>
* The input 2011-01-15 will return 2012-01-01.
* <p>
* The behavior is suitable for use with most calendar systems.
* It is equivalent to:
* <pre>
* temporal.with(DAY_OF_YEAR, 1).plus(1, YEARS);
* </pre>
*
* @return the first day of next month adjuster, not null
*/
public static TemporalAdjuster firstDayOfNextYear() {
return (temporal) -> temporal.with(DAY_OF_YEAR, 1).plus(1, YEARS);
}
//-----------------------------------------------------------------------
/**
* Returns the first in month adjuster, which returns a new date
* in the same month with the first matching day-of-week.
* This is used for expressions like 'first Tuesday in March'.
* <p>
* The ISO calendar system behaves as follows:<br>
* The input 2011-12-15 for (MONDAY) will return 2011-12-05.<br>
* The input 2011-12-15 for (FRIDAY) will return 2011-12-02.<br>
* <p>
* The behavior is suitable for use with most calendar systems.
* It uses the {@code DAY_OF_WEEK} and {@code DAY_OF_MONTH} fields
* and the {@code DAYS} unit, and assumes a seven day week.
*
* @param dayOfWeek the day-of-week, not null
* @return the first in month adjuster, not null
*/
public static TemporalAdjuster firstInMonth(DayOfWeek dayOfWeek) {
return TemporalAdjusters.dayOfWeekInMonth(1, dayOfWeek);
}
/**
* Returns the last in month adjuster, which returns a new date
* in the same month with the last matching day-of-week.
* This is used for expressions like 'last Tuesday in March'.
* <p>
* The ISO calendar system behaves as follows:<br>
* The input 2011-12-15 for (MONDAY) will return 2011-12-26.<br>
* The input 2011-12-15 for (FRIDAY) will return 2011-12-30.<br>
* <p>
* The behavior is suitable for use with most calendar systems.
* It uses the {@code DAY_OF_WEEK} and {@code DAY_OF_MONTH} fields
* and the {@code DAYS} unit, and assumes a seven day week.
*
* @param dayOfWeek the day-of-week, not null
* @return the first in month adjuster, not null
*/
public static TemporalAdjuster lastInMonth(DayOfWeek dayOfWeek) {
return TemporalAdjusters.dayOfWeekInMonth(-1, dayOfWeek);
}
/**
* Returns the day-of-week in month adjuster, which returns a new date
* with the ordinal day-of-week based on the month.
* This is used for expressions like the 'second Tuesday in March'.
* <p>
* The ISO calendar system behaves as follows:<br>
* The input 2011-12-15 for (1,TUESDAY) will return 2011-12-06.<br>
* The input 2011-12-15 for (2,TUESDAY) will return 2011-12-13.<br>
* The input 2011-12-15 for (3,TUESDAY) will return 2011-12-20.<br>
* The input 2011-12-15 for (4,TUESDAY) will return 2011-12-27.<br>
* The input 2011-12-15 for (5,TUESDAY) will return 2012-01-03.<br>
* The input 2011-12-15 for (-1,TUESDAY) will return 2011-12-27 (last in month).<br>
* The input 2011-12-15 for (-4,TUESDAY) will return 2011-12-06 (3 weeks before last in month).<br>
* The input 2011-12-15 for (-5,TUESDAY) will return 2011-11-29 (4 weeks before last in month).<br>
* The input 2011-12-15 for (0,TUESDAY) will return 2011-11-29 (last in previous month).<br>
* <p>
* For a positive or zero ordinal, the algorithm is equivalent to finding the first
* day-of-week that matches within the month and then adding a number of weeks to it.
* For a negative ordinal, the algorithm is equivalent to finding the last
* day-of-week that matches within the month and then subtracting a number of weeks to it.
* The ordinal number of weeks is not validated and is interpreted leniently
* according to this algorithm. This definition means that an ordinal of zero finds
* the last matching day-of-week in the previous month.
* <p>
* The behavior is suitable for use with most calendar systems.
* It uses the {@code DAY_OF_WEEK} and {@code DAY_OF_MONTH} fields
* and the {@code DAYS} unit, and assumes a seven day week.
*
* @param ordinal the week within the month, unbounded but typically from -5 to 5
* @param dayOfWeek the day-of-week, not null
* @return the day-of-week in month adjuster, not null
*/
public static TemporalAdjuster dayOfWeekInMonth(int ordinal, DayOfWeek dayOfWeek) {
Objects.requireNonNull(dayOfWeek, "dayOfWeek");
int dowValue = dayOfWeek.getValue();
if (ordinal >= 0) {
return (temporal) -> {
Temporal temp = temporal.with(DAY_OF_MONTH, 1);
int curDow = temp.get(DAY_OF_WEEK);
int dowDiff = (dowValue - curDow + 7) % 7;
dowDiff += (ordinal - 1L) * 7L; // safe from overflow
return temp.plus(dowDiff, DAYS);
};
} else {
return (temporal) -> {
Temporal temp = temporal.with(DAY_OF_MONTH, temporal.range(DAY_OF_MONTH).getMaximum());
int curDow = temp.get(DAY_OF_WEEK);
int daysDiff = dowValue - curDow;
daysDiff = (daysDiff == 0 ? 0 : (daysDiff > 0 ? daysDiff - 7 : daysDiff));
daysDiff -= (-ordinal - 1L) * 7L; // safe from overflow
return temp.plus(daysDiff, DAYS);
};
}
}
//-----------------------------------------------------------------------
/**
* Returns the next day-of-week adjuster, which adjusts the date to the
* first occurrence of the specified day-of-week after the date being adjusted.
* <p>
* The ISO calendar system behaves as follows:<br>
* The input 2011-01-15 (a Saturday) for parameter (MONDAY) will return 2011-01-17 (two days later).<br>
* The input 2011-01-15 (a Saturday) for parameter (WEDNESDAY) will return 2011-01-19 (four days later).<br>
* The input 2011-01-15 (a Saturday) for parameter (SATURDAY) will return 2011-01-22 (seven days later).
* <p>
* The behavior is suitable for use with most calendar systems.
* It uses the {@code DAY_OF_WEEK} field and the {@code DAYS} unit,
* and assumes a seven day week.
*
* @param dayOfWeek the day-of-week to move the date to, not null
* @return the next day-of-week adjuster, not null
*/
public static TemporalAdjuster next(DayOfWeek dayOfWeek) {
int dowValue = dayOfWeek.getValue();
return (temporal) -> {
int calDow = temporal.get(DAY_OF_WEEK);
int daysDiff = calDow - dowValue;
return temporal.plus(daysDiff >= 0 ? 7 - daysDiff : -daysDiff, DAYS);
};
}
/**
* Returns the next-or-same day-of-week adjuster, which adjusts the date to the
* first occurrence of the specified day-of-week after the date being adjusted
* unless it is already on that day in which case the same object is returned.
* <p>
* The ISO calendar system behaves as follows:<br>
* The input 2011-01-15 (a Saturday) for parameter (MONDAY) will return 2011-01-17 (two days later).<br>
* The input 2011-01-15 (a Saturday) for parameter (WEDNESDAY) will return 2011-01-19 (four days later).<br>
* The input 2011-01-15 (a Saturday) for parameter (SATURDAY) will return 2011-01-15 (same as input).
* <p>
* The behavior is suitable for use with most calendar systems.
* It uses the {@code DAY_OF_WEEK} field and the {@code DAYS} unit,
* and assumes a seven day week.
*
* @param dayOfWeek the day-of-week to check for or move the date to, not null
* @return the next-or-same day-of-week adjuster, not null
*/
public static TemporalAdjuster nextOrSame(DayOfWeek dayOfWeek) {
int dowValue = dayOfWeek.getValue();
return (temporal) -> {
int calDow = temporal.get(DAY_OF_WEEK);
if (calDow == dowValue) {
return temporal;
}
int daysDiff = calDow - dowValue;
return temporal.plus(daysDiff >= 0 ? 7 - daysDiff : -daysDiff, DAYS);
};
}
/**
* Returns the previous day-of-week adjuster, which adjusts the date to the
* first occurrence of the specified day-of-week before the date being adjusted.
* <p>
* The ISO calendar system behaves as follows:<br>
* The input 2011-01-15 (a Saturday) for parameter (MONDAY) will return 2011-01-10 (five days earlier).<br>
* The input 2011-01-15 (a Saturday) for parameter (WEDNESDAY) will return 2011-01-12 (three days earlier).<br>
* The input 2011-01-15 (a Saturday) for parameter (SATURDAY) will return 2011-01-08 (seven days earlier).
* <p>
* The behavior is suitable for use with most calendar systems.
* It uses the {@code DAY_OF_WEEK} field and the {@code DAYS} unit,
* and assumes a seven day week.
*
* @param dayOfWeek the day-of-week to move the date to, not null
* @return the previous day-of-week adjuster, not null
*/
public static TemporalAdjuster previous(DayOfWeek dayOfWeek) {
int dowValue = dayOfWeek.getValue();
return (temporal) -> {
int calDow = temporal.get(DAY_OF_WEEK);
int daysDiff = dowValue - calDow;
return temporal.minus(daysDiff >= 0 ? 7 - daysDiff : -daysDiff, DAYS);
};
}
/**
* Returns the previous-or-same day-of-week adjuster, which adjusts the date to the
* first occurrence of the specified day-of-week before the date being adjusted
* unless it is already on that day in which case the same object is returned.
* <p>
* The ISO calendar system behaves as follows:<br>
* The input 2011-01-15 (a Saturday) for parameter (MONDAY) will return 2011-01-10 (five days earlier).<br>
* The input 2011-01-15 (a Saturday) for parameter (WEDNESDAY) will return 2011-01-12 (three days earlier).<br>
* The input 2011-01-15 (a Saturday) for parameter (SATURDAY) will return 2011-01-15 (same as input).
* <p>
* The behavior is suitable for use with most calendar systems.
* It uses the {@code DAY_OF_WEEK} field and the {@code DAYS} unit,
* and assumes a seven day week.
*
* @param dayOfWeek the day-of-week to check for or move the date to, not null
* @return the previous-or-same day-of-week adjuster, not null
*/
public static TemporalAdjuster previousOrSame(DayOfWeek dayOfWeek) {
int dowValue = dayOfWeek.getValue();
return (temporal) -> {
int calDow = temporal.get(DAY_OF_WEEK);
if (calDow == dowValue) {
return temporal;
}
int daysDiff = dowValue - calDow;
return temporal.minus(daysDiff >= 0 ? 7 - daysDiff : -daysDiff, DAYS);
};
}
}

View file

@ -0,0 +1,219 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Copyright (c) 2012, 2013 Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package java.time.temporal;
import java.time.DateTimeException;
import java.time.Duration;
import java.time.Period;
import java.util.List;
/**
* Framework-level interface defining an amount of time, such as
* "6 hours", "8 days" or "2 years and 3 months".
* <p>
* This is the base interface type for amounts of time.
* An amount is distinct from a date or time-of-day in that it is not tied
* to any specific point on the time-line.
* <p>
* The amount can be thought of as a {@code Map} of {@link TemporalUnit} to
* {@code long}, exposed via {@link #getUnits()} and {@link #get(TemporalUnit)}.
* A simple case might have a single unit-value pair, such as "6 hours".
* A more complex case may have multiple unit-value pairs, such as
* "7 years, 3 months and 5 days".
* <p>
* There are two common implementations.
* {@link Period} is a date-based implementation, storing years, months and days.
* {@link Duration} is a time-based implementation, storing seconds and nanoseconds,
* but providing some access using other duration based units such as minutes,
* hours and fixed 24-hour days.
* <p>
* This interface is a framework-level interface that should not be widely
* used in application code. Instead, applications should create and pass
* around instances of concrete types, such as {@code Period} and {@code Duration}.
*
* @implSpec
* This interface places no restrictions on the mutability of implementations,
* however immutability is strongly recommended.
*
* @since 1.8
*/
public interface TemporalAmount {
/**
* Returns the value of the requested unit.
* The units returned from {@link #getUnits()} uniquely define the
* value of the {@code TemporalAmount}. A value must be returned
* for each unit listed in {@code getUnits}.
*
* @implSpec
* Implementations may declare support for units not listed by {@link #getUnits()}.
* Typically, the implementation would define additional units
* as conversions for the convenience of developers.
*
* @param unit the {@code TemporalUnit} for which to return the value
* @return the long value of the unit
* @throws DateTimeException if a value for the unit cannot be obtained
* @throws UnsupportedTemporalTypeException if the {@code unit} is not supported
*/
long get(TemporalUnit unit);
/**
* Returns the list of units uniquely defining the value of this TemporalAmount.
* The list of {@code TemporalUnits} is defined by the implementation class.
* The list is a snapshot of the units at the time {@code getUnits}
* is called and is not mutable.
* The units are ordered from longest duration to the shortest duration
* of the unit.
*
* @implSpec
* The list of units completely and uniquely represents the
* state of the object without omissions, overlaps or duplication.
* The units are in order from longest duration to shortest.
*
* @return the List of {@code TemporalUnits}; not null
*/
List<TemporalUnit> getUnits();
/**
* Adds to the specified temporal object.
* <p>
* Adds the amount to the specified temporal object using the logic
* encapsulated in the implementing class.
* <p>
* There are two equivalent ways of using this method.
* The first is to invoke this method directly.
* The second is to use {@link Temporal#plus(TemporalAmount)}:
* <pre>
* // These two lines are equivalent, but the second approach is recommended
* dateTime = amount.addTo(dateTime);
* dateTime = dateTime.plus(adder);
* </pre>
* It is recommended to use the second approach, {@code plus(TemporalAmount)},
* as it is a lot clearer to read in code.
*
* @implSpec
* The implementation must take the input object and add to it.
* The implementation defines the logic of the addition and is responsible for
* documenting that logic. It may use any method on {@code Temporal} to
* query the temporal object and perform the addition.
* The returned object must have the same observable type as the input object
* <p>
* The input object must not be altered.
* Instead, an adjusted copy of the original must be returned.
* This provides equivalent, safe behavior for immutable and mutable temporal objects.
* <p>
* The input temporal object may be in a calendar system other than ISO.
* Implementations may choose to document compatibility with other calendar systems,
* or reject non-ISO temporal objects by {@link TemporalQueries#chronology() querying the chronology}.
* <p>
* This method may be called from multiple threads in parallel.
* It must be thread-safe when invoked.
*
* @param temporal the temporal object to add the amount to, not null
* @return an object of the same observable type with the addition made, not null
* @throws DateTimeException if unable to add
* @throws ArithmeticException if numeric overflow occurs
*/
Temporal addTo(Temporal temporal);
/**
* Subtracts this object from the specified temporal object.
* <p>
* Subtracts the amount from the specified temporal object using the logic
* encapsulated in the implementing class.
* <p>
* There are two equivalent ways of using this method.
* The first is to invoke this method directly.
* The second is to use {@link Temporal#minus(TemporalAmount)}:
* <pre>
* // these two lines are equivalent, but the second approach is recommended
* dateTime = amount.subtractFrom(dateTime);
* dateTime = dateTime.minus(amount);
* </pre>
* It is recommended to use the second approach, {@code minus(TemporalAmount)},
* as it is a lot clearer to read in code.
*
* @implSpec
* The implementation must take the input object and subtract from it.
* The implementation defines the logic of the subtraction and is responsible for
* documenting that logic. It may use any method on {@code Temporal} to
* query the temporal object and perform the subtraction.
* The returned object must have the same observable type as the input object
* <p>
* The input object must not be altered.
* Instead, an adjusted copy of the original must be returned.
* This provides equivalent, safe behavior for immutable and mutable temporal objects.
* <p>
* The input temporal object may be in a calendar system other than ISO.
* Implementations may choose to document compatibility with other calendar systems,
* or reject non-ISO temporal objects by {@link TemporalQueries#chronology() querying the chronology}.
* <p>
* This method may be called from multiple threads in parallel.
* It must be thread-safe when invoked.
*
* @param temporal the temporal object to subtract the amount from, not null
* @return an object of the same observable type with the subtraction made, not null
* @throws DateTimeException if unable to subtract
* @throws ArithmeticException if numeric overflow occurs
*/
Temporal subtractFrom(Temporal temporal);
}

View file

@ -0,0 +1,394 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package java.time.temporal;
import java.time.DateTimeException;
import java.time.chrono.Chronology;
import java.time.format.ResolverStyle;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
/**
* A field of date-time, such as month-of-year or hour-of-minute.
* <p>
* Date and time is expressed using fields which partition the time-line into something
* meaningful for humans. Implementations of this interface represent those fields.
* <p>
* The most commonly used units are defined in {@link ChronoField}.
* Further fields are supplied in {@link IsoFields}, {@link WeekFields} and {@link JulianFields}.
* Fields can also be written by application code by implementing this interface.
* <p>
* The field works using double dispatch. Client code calls methods on a date-time like
* {@code LocalDateTime} which check if the field is a {@code ChronoField}.
* If it is, then the date-time must handle it.
* Otherwise, the method call is re-dispatched to the matching method in this interface.
*
* @implSpec
* This interface must be implemented with care to ensure other classes operate correctly.
* All implementations that can be instantiated must be final, immutable and thread-safe.
* Implementations should be {@code Serializable} where possible.
* An enum is as effective implementation choice.
*
* @since 1.8
*/
public interface TemporalField {
/**
* Gets the display name for the field in the requested locale.
* <p>
* If there is no display name for the locale then a suitable default must be returned.
* <p>
* The default implementation must check the locale is not null
* and return {@code toString()}.
*
* @param locale the locale to use, not null
* @return the display name for the locale or a suitable default, not null
*/
default String getDisplayName(Locale locale) {
Objects.requireNonNull(locale, "locale");
return toString();
}
/**
* Gets the unit that the field is measured in.
* <p>
* The unit of the field is the period that varies within the range.
* For example, in the field 'MonthOfYear', the unit is 'Months'.
* See also {@link #getRangeUnit()}.
*
* @return the unit defining the base unit of the field, not null
*/
TemporalUnit getBaseUnit();
/**
* Gets the range that the field is bound by.
* <p>
* The range of the field is the period that the field varies within.
* For example, in the field 'MonthOfYear', the range is 'Years'.
* See also {@link #getBaseUnit()}.
* <p>
* The range is never null. For example, the 'Year' field is shorthand for
* 'YearOfForever'. It therefore has a unit of 'Years' and a range of 'Forever'.
*
* @return the unit defining the range of the field, not null
*/
TemporalUnit getRangeUnit();
/**
* Gets the range of valid values for the field.
* <p>
* All fields can be expressed as a {@code long} integer.
* This method returns an object that describes the valid range for that value.
* This method is generally only applicable to the ISO-8601 calendar system.
* <p>
* Note that the result only describes the minimum and maximum valid values
* and it is important not to read too much into them. For example, there
* could be values within the range that are invalid for the field.
*
* @return the range of valid values for the field, not null
*/
ValueRange range();
//-----------------------------------------------------------------------
/**
* Checks if this field represents a component of a date.
* <p>
* A field is date-based if it can be derived from
* {@link ChronoField#EPOCH_DAY EPOCH_DAY}.
* Note that it is valid for both {@code isDateBased()} and {@code isTimeBased()}
* to return false, such as when representing a field like minute-of-week.
*
* @return true if this field is a component of a date
*/
boolean isDateBased();
/**
* Checks if this field represents a component of a time.
* <p>
* A field is time-based if it can be derived from
* {@link ChronoField#NANO_OF_DAY NANO_OF_DAY}.
* Note that it is valid for both {@code isDateBased()} and {@code isTimeBased()}
* to return false, such as when representing a field like minute-of-week.
*
* @return true if this field is a component of a time
*/
boolean isTimeBased();
//-----------------------------------------------------------------------
/**
* Checks if this field is supported by the temporal object.
* <p>
* This determines whether the temporal accessor supports this field.
* If this returns false, then the temporal cannot be queried for this field.
* <p>
* There are two equivalent ways of using this method.
* The first is to invoke this method directly.
* The second is to use {@link TemporalAccessor#isSupported(TemporalField)}:
* <pre>
* // these two lines are equivalent, but the second approach is recommended
* temporal = thisField.isSupportedBy(temporal);
* temporal = temporal.isSupported(thisField);
* </pre>
* It is recommended to use the second approach, {@code isSupported(TemporalField)},
* as it is a lot clearer to read in code.
* <p>
* Implementations should determine whether they are supported using the fields
* available in {@link ChronoField}.
*
* @param temporal the temporal object to query, not null
* @return true if the date-time can be queried for this field, false if not
*/
boolean isSupportedBy(TemporalAccessor temporal);
/**
* Get the range of valid values for this field using the temporal object to
* refine the result.
* <p>
* This uses the temporal object to find the range of valid values for the field.
* This is similar to {@link #range()}, however this method refines the result
* using the temporal. For example, if the field is {@code DAY_OF_MONTH} the
* {@code range} method is not accurate as there are four possible month lengths,
* 28, 29, 30 and 31 days. Using this method with a date allows the range to be
* accurate, returning just one of those four options.
* <p>
* There are two equivalent ways of using this method.
* The first is to invoke this method directly.
* The second is to use {@link TemporalAccessor#range(TemporalField)}:
* <pre>
* // these two lines are equivalent, but the second approach is recommended
* temporal = thisField.rangeRefinedBy(temporal);
* temporal = temporal.range(thisField);
* </pre>
* It is recommended to use the second approach, {@code range(TemporalField)},
* as it is a lot clearer to read in code.
* <p>
* Implementations should perform any queries or calculations using the fields
* available in {@link ChronoField}.
* If the field is not supported an {@code UnsupportedTemporalTypeException} must be thrown.
*
* @param temporal the temporal object used to refine the result, not null
* @return the range of valid values for this field, not null
* @throws DateTimeException if the range for the field cannot be obtained
* @throws UnsupportedTemporalTypeException if the field is not supported by the temporal
*/
ValueRange rangeRefinedBy(TemporalAccessor temporal);
/**
* Gets the value of this field from the specified temporal object.
* <p>
* This queries the temporal object for the value of this field.
* <p>
* There are two equivalent ways of using this method.
* The first is to invoke this method directly.
* The second is to use {@link TemporalAccessor#getLong(TemporalField)}
* (or {@link TemporalAccessor#get(TemporalField)}):
* <pre>
* // these two lines are equivalent, but the second approach is recommended
* temporal = thisField.getFrom(temporal);
* temporal = temporal.getLong(thisField);
* </pre>
* It is recommended to use the second approach, {@code getLong(TemporalField)},
* as it is a lot clearer to read in code.
* <p>
* Implementations should perform any queries or calculations using the fields
* available in {@link ChronoField}.
* If the field is not supported an {@code UnsupportedTemporalTypeException} must be thrown.
*
* @param temporal the temporal object to query, not null
* @return the value of this field, not null
* @throws DateTimeException if a value for the field cannot be obtained
* @throws UnsupportedTemporalTypeException if the field is not supported by the temporal
* @throws ArithmeticException if numeric overflow occurs
*/
long getFrom(TemporalAccessor temporal);
/**
* Returns a copy of the specified temporal object with the value of this field set.
* <p>
* This returns a new temporal object based on the specified one with the value for
* this field changed. For example, on a {@code LocalDate}, this could be used to
* set the year, month or day-of-month.
* The returned object has the same observable type as the specified object.
* <p>
* In some cases, changing a field is not fully defined. For example, if the target object is
* a date representing the 31st January, then changing the month to February would be unclear.
* In cases like this, the implementation is responsible for resolving the result.
* Typically it will choose the previous valid date, which would be the last valid
* day of February in this example.
* <p>
* There are two equivalent ways of using this method.
* The first is to invoke this method directly.
* The second is to use {@link Temporal#with(TemporalField, long)}:
* <pre>
* // these two lines are equivalent, but the second approach is recommended
* temporal = thisField.adjustInto(temporal);
* temporal = temporal.with(thisField);
* </pre>
* It is recommended to use the second approach, {@code with(TemporalField)},
* as it is a lot clearer to read in code.
* <p>
* Implementations should perform any queries or calculations using the fields
* available in {@link ChronoField}.
* If the field is not supported an {@code UnsupportedTemporalTypeException} must be thrown.
* <p>
* Implementations must not alter the specified temporal object.
* Instead, an adjusted copy of the original must be returned.
* This provides equivalent, safe behavior for immutable and mutable implementations.
*
* @param <R> the type of the Temporal object
* @param temporal the temporal object to adjust, not null
* @param newValue the new value of the field
* @return the adjusted temporal object, not null
* @throws DateTimeException if the field cannot be set
* @throws UnsupportedTemporalTypeException if the field is not supported by the temporal
* @throws ArithmeticException if numeric overflow occurs
*/
<R extends Temporal> R adjustInto(R temporal, long newValue);
/**
* Resolves this field to provide a simpler alternative or a date.
* <p>
* This method is invoked during the resolve phase of parsing.
* It is designed to allow application defined fields to be simplified into
* more standard fields, such as those on {@code ChronoField}, or into a date.
* <p>
* Applications should not normally invoke this method directly.
*
* @implSpec
* If an implementation represents a field that can be simplified, or
* combined with others, then this method must be implemented.
* <p>
* The specified map contains the current state of the parse.
* The map is mutable and must be mutated to resolve the field and
* any related fields. This method will only be invoked during parsing
* if the map contains this field, and implementations should therefore
* assume this field is present.
* <p>
* Resolving a field will consist of looking at the value of this field,
* and potentially other fields, and either updating the map with a
* simpler value, such as a {@code ChronoField}, or returning a
* complete {@code ChronoLocalDate}. If a resolve is successful,
* the code must remove all the fields that were resolved from the map,
* including this field.
* <p>
* For example, the {@code IsoFields} class contains the quarter-of-year
* and day-of-quarter fields. The implementation of this method in that class
* resolves the two fields plus the {@link ChronoField#YEAR YEAR} into a
* complete {@code LocalDate}. The resolve method will remove all three
* fields from the map before returning the {@code LocalDate}.
* <p>
* A partially complete temporal is used to allow the chronology and zone
* to be queried. In general, only the chronology will be needed.
* Querying items other than the zone or chronology is undefined and
* must not be relied on.
* The behavior of other methods such as {@code get}, {@code getLong},
* {@code range} and {@code isSupported} is unpredictable and the results undefined.
* <p>
* If resolution should be possible, but the data is invalid, the resolver
* style should be used to determine an appropriate level of leniency, which
* may require throwing a {@code DateTimeException} or {@code ArithmeticException}.
* If no resolution is possible, the resolve method must return null.
* <p>
* When resolving time fields, the map will be altered and null returned.
* When resolving date fields, the date is normally returned from the method,
* with the map altered to remove the resolved fields. However, it would also
* be acceptable for the date fields to be resolved into other {@code ChronoField}
* instances that can produce a date, such as {@code EPOCH_DAY}.
* <p>
* Not all {@code TemporalAccessor} implementations are accepted as return values.
* Implementations that call this method must accept {@code ChronoLocalDate},
* {@code ChronoLocalDateTime}, {@code ChronoZonedDateTime} and {@code LocalTime}.
* <p>
* The default implementation must return null.
*
* @param fieldValues the map of fields to values, which can be updated, not null
* @param partialTemporal the partially complete temporal to query for zone and
* chronology; querying for other things is undefined and not recommended, not null
* @param resolverStyle the requested type of resolve, not null
* @return the resolved temporal object; null if resolving only
* changed the map, or no resolve occurred
* @throws ArithmeticException if numeric overflow occurs
* @throws DateTimeException if resolving results in an error. This must not be thrown
* by querying a field on the temporal without first checking if it is supported
*/
default TemporalAccessor resolve(
Map<TemporalField, Long> fieldValues,
TemporalAccessor partialTemporal,
ResolverStyle resolverStyle) {
return null;
}
/**
* Gets a descriptive name for the field.
* <p>
* The should be of the format 'BaseOfRange', such as 'MonthOfYear',
* unless the field has a range of {@code FOREVER}, when only
* the base unit is mentioned, such as 'Year' or 'Era'.
*
* @return the name of the field, not null
*/
@Override
String toString();
}

View file

@ -0,0 +1,458 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Copyright (c) 2007-2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package java.time.temporal;
import static java.time.temporal.ChronoField.EPOCH_DAY;
import static java.time.temporal.ChronoField.NANO_OF_DAY;
import static java.time.temporal.ChronoField.OFFSET_SECONDS;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.chrono.Chronology;
/**
* Common implementations of {@code TemporalQuery}.
* <p>
* This class provides common implementations of {@link TemporalQuery}.
* These are defined here as they must be constants, and the definition
* of lambdas does not guarantee that. By assigning them once here,
* they become 'normal' Java constants.
* <p>
* Queries are a key tool for extracting information from temporal objects.
* They exist to externalize the process of querying, permitting different
* approaches, as per the strategy design pattern.
* Examples might be a query that checks if the date is the day before February 29th
* in a leap year, or calculates the number of days to your next birthday.
* <p>
* The {@link TemporalField} interface provides another mechanism for querying
* temporal objects. That interface is limited to returning a {@code long}.
* By contrast, queries can return any type.
* <p>
* There are two equivalent ways of using a {@code TemporalQuery}.
* The first is to invoke the method on this interface directly.
* The second is to use {@link TemporalAccessor#query(TemporalQuery)}:
* <pre>
* // these two lines are equivalent, but the second approach is recommended
* temporal = thisQuery.queryFrom(temporal);
* temporal = temporal.query(thisQuery);
* </pre>
* It is recommended to use the second approach, {@code query(TemporalQuery)},
* as it is a lot clearer to read in code.
* <p>
* The most common implementations are method references, such as
* {@code LocalDate::from} and {@code ZoneId::from}.
* Additional common queries are provided to return:
* <ul>
* <li> a Chronology,
* <li> a LocalDate,
* <li> a LocalTime,
* <li> a ZoneOffset,
* <li> a precision,
* <li> a zone, or
* <li> a zoneId.
* </ul>
*
* @since 1.8
*/
public final class TemporalQueries {
// note that it is vital that each method supplies a constant, not a
// calculated value, as they will be checked for using ==
// it is also vital that each constant is different (due to the == checking)
// as such, alterations to this code must be done with care
/**
* Private constructor since this is a utility class.
*/
private TemporalQueries() {
}
//-----------------------------------------------------------------------
// special constants should be used to extract information from a TemporalAccessor
// that cannot be derived in other ways
// Javadoc added here, so as to pretend they are more normal than they really are
/**
* A strict query for the {@code ZoneId}.
* <p>
* This queries a {@code TemporalAccessor} for the zone.
* The zone is only returned if the date-time conceptually contains a {@code ZoneId}.
* It will not be returned if the date-time only conceptually has an {@code ZoneOffset}.
* Thus a {@link java.time.ZonedDateTime} will return the result of {@code getZone()},
* but an {@link java.time.OffsetDateTime} will return null.
* <p>
* In most cases, applications should use {@link #zone()} as this query is too strict.
* <p>
* The result from JDK classes implementing {@code TemporalAccessor} is as follows:<br>
* {@code LocalDate} returns null<br>
* {@code LocalTime} returns null<br>
* {@code LocalDateTime} returns null<br>
* {@code ZonedDateTime} returns the associated zone<br>
* {@code OffsetTime} returns null<br>
* {@code OffsetDateTime} returns null<br>
* {@code ChronoLocalDate} returns null<br>
* {@code ChronoLocalDateTime} returns null<br>
* {@code ChronoZonedDateTime} returns the associated zone<br>
* {@code Era} returns null<br>
* {@code DayOfWeek} returns null<br>
* {@code Month} returns null<br>
* {@code Year} returns null<br>
* {@code YearMonth} returns null<br>
* {@code MonthDay} returns null<br>
* {@code ZoneOffset} returns null<br>
* {@code Instant} returns null<br>
*
* @return a query that can obtain the zone ID of a temporal, not null
*/
public static TemporalQuery<ZoneId> zoneId() {
return TemporalQueries.ZONE_ID;
}
/**
* A query for the {@code Chronology}.
* <p>
* This queries a {@code TemporalAccessor} for the chronology.
* If the target {@code TemporalAccessor} represents a date, or part of a date,
* then it should return the chronology that the date is expressed in.
* As a result of this definition, objects only representing time, such as
* {@code LocalTime}, will return null.
* <p>
* The result from JDK classes implementing {@code TemporalAccessor} is as follows:<br>
* {@code LocalDate} returns {@code IsoChronology.INSTANCE}<br>
* {@code LocalTime} returns null (does not represent a date)<br>
* {@code LocalDateTime} returns {@code IsoChronology.INSTANCE}<br>
* {@code ZonedDateTime} returns {@code IsoChronology.INSTANCE}<br>
* {@code OffsetTime} returns null (does not represent a date)<br>
* {@code OffsetDateTime} returns {@code IsoChronology.INSTANCE}<br>
* {@code ChronoLocalDate} returns the associated chronology<br>
* {@code ChronoLocalDateTime} returns the associated chronology<br>
* {@code ChronoZonedDateTime} returns the associated chronology<br>
* {@code Era} returns the associated chronology<br>
* {@code DayOfWeek} returns null (shared across chronologies)<br>
* {@code Month} returns {@code IsoChronology.INSTANCE}<br>
* {@code Year} returns {@code IsoChronology.INSTANCE}<br>
* {@code YearMonth} returns {@code IsoChronology.INSTANCE}<br>
* {@code MonthDay} returns null {@code IsoChronology.INSTANCE}<br>
* {@code ZoneOffset} returns null (does not represent a date)<br>
* {@code Instant} returns null (does not represent a date)<br>
* <p>
* The method {@link java.time.chrono.Chronology#from(TemporalAccessor)} can be used as a
* {@code TemporalQuery} via a method reference, {@code Chronology::from}.
* That method is equivalent to this query, except that it throws an
* exception if a chronology cannot be obtained.
*
* @return a query that can obtain the chronology of a temporal, not null
*/
public static TemporalQuery<Chronology> chronology() {
return TemporalQueries.CHRONO;
}
/**
* A query for the smallest supported unit.
* <p>
* This queries a {@code TemporalAccessor} for the time precision.
* If the target {@code TemporalAccessor} represents a consistent or complete date-time,
* date or time then this must return the smallest precision actually supported.
* Note that fields such as {@code NANO_OF_DAY} and {@code NANO_OF_SECOND}
* are defined to always return ignoring the precision, thus this is the only
* way to find the actual smallest supported unit.
* For example, were {@code GregorianCalendar} to implement {@code TemporalAccessor}
* it would return a precision of {@code MILLIS}.
* <p>
* The result from JDK classes implementing {@code TemporalAccessor} is as follows:<br>
* {@code LocalDate} returns {@code DAYS}<br>
* {@code LocalTime} returns {@code NANOS}<br>
* {@code LocalDateTime} returns {@code NANOS}<br>
* {@code ZonedDateTime} returns {@code NANOS}<br>
* {@code OffsetTime} returns {@code NANOS}<br>
* {@code OffsetDateTime} returns {@code NANOS}<br>
* {@code ChronoLocalDate} returns {@code DAYS}<br>
* {@code ChronoLocalDateTime} returns {@code NANOS}<br>
* {@code ChronoZonedDateTime} returns {@code NANOS}<br>
* {@code Era} returns {@code ERAS}<br>
* {@code DayOfWeek} returns {@code DAYS}<br>
* {@code Month} returns {@code MONTHS}<br>
* {@code Year} returns {@code YEARS}<br>
* {@code YearMonth} returns {@code MONTHS}<br>
* {@code MonthDay} returns null (does not represent a complete date or time)<br>
* {@code ZoneOffset} returns null (does not represent a date or time)<br>
* {@code Instant} returns {@code NANOS}<br>
*
* @return a query that can obtain the precision of a temporal, not null
*/
public static TemporalQuery<TemporalUnit> precision() {
return TemporalQueries.PRECISION;
}
//-----------------------------------------------------------------------
// non-special constants are standard queries that derive information from other information
/**
* A lenient query for the {@code ZoneId}, falling back to the {@code ZoneOffset}.
* <p>
* This queries a {@code TemporalAccessor} for the zone.
* It first tries to obtain the zone, using {@link #zoneId()}.
* If that is not found it tries to obtain the {@link #offset()}.
* Thus a {@link java.time.ZonedDateTime} will return the result of {@code getZone()},
* while an {@link java.time.OffsetDateTime} will return the result of {@code getOffset()}.
* <p>
* In most cases, applications should use this query rather than {@code #zoneId()}.
* <p>
* The method {@link ZoneId#from(TemporalAccessor)} can be used as a
* {@code TemporalQuery} via a method reference, {@code ZoneId::from}.
* That method is equivalent to this query, except that it throws an
* exception if a zone cannot be obtained.
*
* @return a query that can obtain the zone ID or offset of a temporal, not null
*/
public static TemporalQuery<ZoneId> zone() {
return TemporalQueries.ZONE;
}
/**
* A query for {@code ZoneOffset} returning null if not found.
* <p>
* This returns a {@code TemporalQuery} that can be used to query a temporal
* object for the offset. The query will return null if the temporal
* object cannot supply an offset.
* <p>
* The query implementation examines the {@link ChronoField#OFFSET_SECONDS OFFSET_SECONDS}
* field and uses it to create a {@code ZoneOffset}.
* <p>
* The method {@link java.time.ZoneOffset#from(TemporalAccessor)} can be used as a
* {@code TemporalQuery} via a method reference, {@code ZoneOffset::from}.
* This query and {@code ZoneOffset::from} will return the same result if the
* temporal object contains an offset. If the temporal object does not contain
* an offset, then the method reference will throw an exception, whereas this
* query will return null.
*
* @return a query that can obtain the offset of a temporal, not null
*/
public static TemporalQuery<ZoneOffset> offset() {
return TemporalQueries.OFFSET;
}
/**
* A query for {@code LocalDate} returning null if not found.
* <p>
* This returns a {@code TemporalQuery} that can be used to query a temporal
* object for the local date. The query will return null if the temporal
* object cannot supply a local date.
* <p>
* The query implementation examines the {@link ChronoField#EPOCH_DAY EPOCH_DAY}
* field and uses it to create a {@code LocalDate}.
* <p>
* The method {@link ZoneOffset#from(TemporalAccessor)} can be used as a
* {@code TemporalQuery} via a method reference, {@code LocalDate::from}.
* This query and {@code LocalDate::from} will return the same result if the
* temporal object contains a date. If the temporal object does not contain
* a date, then the method reference will throw an exception, whereas this
* query will return null.
*
* @return a query that can obtain the date of a temporal, not null
*/
public static TemporalQuery<LocalDate> localDate() {
return TemporalQueries.LOCAL_DATE;
}
/**
* A query for {@code LocalTime} returning null if not found.
* <p>
* This returns a {@code TemporalQuery} that can be used to query a temporal
* object for the local time. The query will return null if the temporal
* object cannot supply a local time.
* <p>
* The query implementation examines the {@link ChronoField#NANO_OF_DAY NANO_OF_DAY}
* field and uses it to create a {@code LocalTime}.
* <p>
* The method {@link ZoneOffset#from(TemporalAccessor)} can be used as a
* {@code TemporalQuery} via a method reference, {@code LocalTime::from}.
* This query and {@code LocalTime::from} will return the same result if the
* temporal object contains a time. If the temporal object does not contain
* a time, then the method reference will throw an exception, whereas this
* query will return null.
*
* @return a query that can obtain the time of a temporal, not null
*/
public static TemporalQuery<LocalTime> localTime() {
return TemporalQueries.LOCAL_TIME;
}
//-----------------------------------------------------------------------
/**
* A strict query for the {@code ZoneId}.
*/
static final TemporalQuery<ZoneId> ZONE_ID = new TemporalQuery<>() {
@Override
public ZoneId queryFrom(TemporalAccessor temporal) {
return temporal.query(TemporalQueries.ZONE_ID);
}
@Override
public String toString() {
return "ZoneId";
}
};
/**
* A query for the {@code Chronology}.
*/
static final TemporalQuery<Chronology> CHRONO = new TemporalQuery<>() {
@Override
public Chronology queryFrom(TemporalAccessor temporal) {
return temporal.query(TemporalQueries.CHRONO);
}
@Override
public String toString() {
return "Chronology";
}
};
/**
* A query for the smallest supported unit.
*/
static final TemporalQuery<TemporalUnit> PRECISION = new TemporalQuery<>() {
@Override
public TemporalUnit queryFrom(TemporalAccessor temporal) {
return temporal.query(TemporalQueries.PRECISION);
}
@Override
public String toString() {
return "Precision";
}
};
//-----------------------------------------------------------------------
/**
* A query for {@code ZoneOffset} returning null if not found.
*/
static final TemporalQuery<ZoneOffset> OFFSET = new TemporalQuery<>() {
@Override
public ZoneOffset queryFrom(TemporalAccessor temporal) {
if (temporal.isSupported(OFFSET_SECONDS)) {
return ZoneOffset.ofTotalSeconds(temporal.get(OFFSET_SECONDS));
}
return null;
}
@Override
public String toString() {
return "ZoneOffset";
}
};
/**
* A lenient query for the {@code ZoneId}, falling back to the {@code ZoneOffset}.
*/
static final TemporalQuery<ZoneId> ZONE = new TemporalQuery<>() {
@Override
public ZoneId queryFrom(TemporalAccessor temporal) {
ZoneId zone = temporal.query(ZONE_ID);
return (zone != null ? zone : temporal.query(OFFSET));
}
@Override
public String toString() {
return "Zone";
}
};
/**
* A query for {@code LocalDate} returning null if not found.
*/
static final TemporalQuery<LocalDate> LOCAL_DATE = new TemporalQuery<>() {
@Override
public LocalDate queryFrom(TemporalAccessor temporal) {
if (temporal.isSupported(EPOCH_DAY)) {
return LocalDate.ofEpochDay(temporal.getLong(EPOCH_DAY));
}
return null;
}
@Override
public String toString() {
return "LocalDate";
}
};
/**
* A query for {@code LocalTime} returning null if not found.
*/
static final TemporalQuery<LocalTime> LOCAL_TIME = new TemporalQuery<>() {
@Override
public LocalTime queryFrom(TemporalAccessor temporal) {
if (temporal.isSupported(NANO_OF_DAY)) {
return LocalTime.ofNanoOfDay(temporal.getLong(NANO_OF_DAY));
}
return null;
}
@Override
public String toString() {
return "LocalTime";
}
};
}

View file

@ -0,0 +1,145 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package java.time.temporal;
import java.time.DateTimeException;
/**
* Strategy for querying a temporal object.
* <p>
* Queries are a key tool for extracting information from temporal objects.
* They exist to externalize the process of querying, permitting different
* approaches, as per the strategy design pattern.
* Examples might be a query that checks if the date is the day before February 29th
* in a leap year, or calculates the number of days to your next birthday.
* <p>
* The {@link TemporalField} interface provides another mechanism for querying
* temporal objects. That interface is limited to returning a {@code long}.
* By contrast, queries can return any type.
* <p>
* There are two equivalent ways of using a {@code TemporalQuery}.
* The first is to invoke the method on this interface directly.
* The second is to use {@link TemporalAccessor#query(TemporalQuery)}:
* <pre>
* // these two lines are equivalent, but the second approach is recommended
* temporal = thisQuery.queryFrom(temporal);
* temporal = temporal.query(thisQuery);
* </pre>
* It is recommended to use the second approach, {@code query(TemporalQuery)},
* as it is a lot clearer to read in code.
* <p>
* The most common implementations are method references, such as
* {@code LocalDate::from} and {@code ZoneId::from}.
* Additional common queries are provided as static methods in {@link TemporalQueries}.
*
* @implSpec
* This interface places no restrictions on the mutability of implementations,
* however immutability is strongly recommended.
*
* @param <R> the type returned from the query
*
* @since 1.8
*/
@FunctionalInterface
public interface TemporalQuery<R> {
/**
* Queries the specified temporal object.
* <p>
* This queries the specified temporal object to return an object using the logic
* encapsulated in the implementing class.
* Examples might be a query that checks if the date is the day before February 29th
* in a leap year, or calculates the number of days to your next birthday.
* <p>
* There are two equivalent ways of using this method.
* The first is to invoke this method directly.
* The second is to use {@link TemporalAccessor#query(TemporalQuery)}:
* <pre>
* // these two lines are equivalent, but the second approach is recommended
* temporal = thisQuery.queryFrom(temporal);
* temporal = temporal.query(thisQuery);
* </pre>
* It is recommended to use the second approach, {@code query(TemporalQuery)},
* as it is a lot clearer to read in code.
*
* @implSpec
* The implementation must take the input object and query it.
* The implementation defines the logic of the query and is responsible for
* documenting that logic.
* It may use any method on {@code TemporalAccessor} to determine the result.
* The input object must not be altered.
* <p>
* The input temporal object may be in a calendar system other than ISO.
* Implementations may choose to document compatibility with other calendar systems,
* or reject non-ISO temporal objects by {@link TemporalQueries#chronology() querying the chronology}.
* <p>
* This method may be called from multiple threads in parallel.
* It must be thread-safe when invoked.
*
* @param temporal the temporal object to query, not null
* @return the queried value, may return null to indicate not found
* @throws DateTimeException if unable to query
* @throws ArithmeticException if numeric overflow occurs
*/
R queryFrom(TemporalAccessor temporal);
}

View file

@ -0,0 +1,297 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package java.time.temporal;
import java.time.DateTimeException;
import java.time.Duration;
import java.time.LocalTime;
import java.time.Period;
import java.time.chrono.ChronoLocalDate;
import java.time.chrono.ChronoLocalDateTime;
import java.time.chrono.ChronoZonedDateTime;
/**
* A unit of date-time, such as Days or Hours.
* <p>
* Measurement of time is built on units, such as years, months, days, hours, minutes and seconds.
* Implementations of this interface represent those units.
* <p>
* An instance of this interface represents the unit itself, rather than an amount of the unit.
* See {@link Period} for a class that represents an amount in terms of the common units.
* <p>
* The most commonly used units are defined in {@link ChronoUnit}.
* Further units are supplied in {@link IsoFields}.
* Units can also be written by application code by implementing this interface.
* <p>
* The unit works using double dispatch. Client code calls methods on a date-time like
* {@code LocalDateTime} which check if the unit is a {@code ChronoUnit}.
* If it is, then the date-time must handle it.
* Otherwise, the method call is re-dispatched to the matching method in this interface.
*
* @implSpec
* This interface must be implemented with care to ensure other classes operate correctly.
* All implementations that can be instantiated must be final, immutable and thread-safe.
* It is recommended to use an enum where possible.
*
* @since 1.8
*/
public interface TemporalUnit {
/**
* Gets the duration of this unit, which may be an estimate.
* <p>
* All units return a duration measured in standard nanoseconds from this method.
* The duration will be positive and non-zero.
* For example, an hour has a duration of {@code 60 * 60 * 1,000,000,000ns}.
* <p>
* Some units may return an accurate duration while others return an estimate.
* For example, days have an estimated duration due to the possibility of
* daylight saving time changes.
* To determine if the duration is an estimate, use {@link #isDurationEstimated()}.
*
* @return the duration of this unit, which may be an estimate, not null
*/
Duration getDuration();
/**
* Checks if the duration of the unit is an estimate.
* <p>
* All units have a duration, however the duration is not always accurate.
* For example, days have an estimated duration due to the possibility of
* daylight saving time changes.
* This method returns true if the duration is an estimate and false if it is
* accurate. Note that accurate/estimated ignores leap seconds.
*
* @return true if the duration is estimated, false if accurate
*/
boolean isDurationEstimated();
//-----------------------------------------------------------------------
/**
* Checks if this unit represents a component of a date.
* <p>
* A date is time-based if it can be used to imply meaning from a date.
* It must have a {@linkplain #getDuration() duration} that is an integral
* multiple of the length of a standard day.
* Note that it is valid for both {@code isDateBased()} and {@code isTimeBased()}
* to return false, such as when representing a unit like 36 hours.
*
* @return true if this unit is a component of a date
*/
boolean isDateBased();
/**
* Checks if this unit represents a component of a time.
* <p>
* A unit is time-based if it can be used to imply meaning from a time.
* It must have a {@linkplain #getDuration() duration} that divides into
* the length of a standard day without remainder.
* Note that it is valid for both {@code isDateBased()} and {@code isTimeBased()}
* to return false, such as when representing a unit like 36 hours.
*
* @return true if this unit is a component of a time
*/
boolean isTimeBased();
//-----------------------------------------------------------------------
/**
* Checks if this unit is supported by the specified temporal object.
* <p>
* This checks that the implementing date-time can add/subtract this unit.
* This can be used to avoid throwing an exception.
* <p>
* This default implementation derives the value using
* {@link Temporal#plus(long, TemporalUnit)}.
*
* @param temporal the temporal object to check, not null
* @return true if the unit is supported
*/
default boolean isSupportedBy(Temporal temporal) {
if (temporal instanceof LocalTime) {
return isTimeBased();
}
if (temporal instanceof ChronoLocalDate) {
return isDateBased();
}
if (temporal instanceof ChronoLocalDateTime || temporal instanceof ChronoZonedDateTime) {
return true;
}
try {
temporal.plus(1, this);
return true;
} catch (UnsupportedTemporalTypeException ex) {
return false;
} catch (RuntimeException ex) {
try {
temporal.plus(-1, this);
return true;
} catch (RuntimeException ex2) {
return false;
}
}
}
/**
* Returns a copy of the specified temporal object with the specified period added.
* <p>
* The period added is a multiple of this unit. For example, this method
* could be used to add "3 days" to a date by calling this method on the
* instance representing "days", passing the date and the period "3".
* The period to be added may be negative, which is equivalent to subtraction.
* <p>
* There are two equivalent ways of using this method.
* The first is to invoke this method directly.
* The second is to use {@link Temporal#plus(long, TemporalUnit)}:
* <pre>
* // these two lines are equivalent, but the second approach is recommended
* temporal = thisUnit.addTo(temporal);
* temporal = temporal.plus(thisUnit);
* </pre>
* It is recommended to use the second approach, {@code plus(TemporalUnit)},
* as it is a lot clearer to read in code.
* <p>
* Implementations should perform any queries or calculations using the units
* available in {@link ChronoUnit} or the fields available in {@link ChronoField}.
* If the unit is not supported an {@code UnsupportedTemporalTypeException} must be thrown.
* <p>
* Implementations must not alter the specified temporal object.
* Instead, an adjusted copy of the original must be returned.
* This provides equivalent, safe behavior for immutable and mutable implementations.
*
* @param <R> the type of the Temporal object
* @param temporal the temporal object to adjust, not null
* @param amount the amount of this unit to add, positive or negative
* @return the adjusted temporal object, not null
* @throws DateTimeException if the amount cannot be added
* @throws UnsupportedTemporalTypeException if the unit is not supported by the temporal
*/
<R extends Temporal> R addTo(R temporal, long amount);
//-----------------------------------------------------------------------
/**
* Calculates the amount of time between two temporal objects.
* <p>
* This calculates the amount in terms of this unit. The start and end
* points are supplied as temporal objects and must be of compatible types.
* The implementation will convert the second type to be an instance of the
* first type before the calculating the amount.
* The result will be negative if the end is before the start.
* For example, the amount in hours between two temporal objects can be
* calculated using {@code HOURS.between(startTime, endTime)}.
* <p>
* The calculation returns a whole number, representing the number of
* complete units between the two temporals.
* For example, the amount in hours between the times 11:30 and 13:29
* will only be one hour as it is one minute short of two hours.
* <p>
* There are two equivalent ways of using this method.
* The first is to invoke this method directly.
* The second is to use {@link Temporal#until(Temporal, TemporalUnit)}:
* <pre>
* // these two lines are equivalent
* between = thisUnit.between(start, end);
* between = start.until(end, thisUnit);
* </pre>
* The choice should be made based on which makes the code more readable.
* <p>
* For example, this method allows the number of days between two dates to
* be calculated:
* <pre>
* long daysBetween = DAYS.between(start, end);
* // or alternatively
* long daysBetween = start.until(end, DAYS);
* </pre>
* <p>
* Implementations should perform any queries or calculations using the units
* available in {@link ChronoUnit} or the fields available in {@link ChronoField}.
* If the unit is not supported an {@code UnsupportedTemporalTypeException} must be thrown.
* Implementations must not alter the specified temporal objects.
*
* @implSpec
* Implementations must begin by checking to if the two temporals have the
* same type using {@code getClass()}. If they do not, then the result must be
* obtained by calling {@code temporal1Inclusive.until(temporal2Exclusive, this)}.
*
* @param temporal1Inclusive the base temporal object, not null
* @param temporal2Exclusive the other temporal object, exclusive, not null
* @return the amount of time between temporal1Inclusive and temporal2Exclusive
* in terms of this unit; positive if temporal2Exclusive is later than
* temporal1Inclusive, negative if earlier
* @throws DateTimeException if the amount cannot be calculated, or the end
* temporal cannot be converted to the same type as the start temporal
* @throws UnsupportedTemporalTypeException if the unit is not supported by the temporal
* @throws ArithmeticException if numeric overflow occurs
*/
long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive);
//-----------------------------------------------------------------------
/**
* Gets a descriptive name for the unit.
* <p>
* This should be in the plural and upper-first camel case, such as 'Days' or 'Minutes'.
*
* @return the name of this unit, not null
*/
@Override
String toString();
}

View file

@ -0,0 +1,101 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Copyright (c) 2013, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package java.time.temporal;
import java.time.DateTimeException;
/**
* UnsupportedTemporalTypeException indicates that a ChronoField or ChronoUnit is
* not supported for a Temporal class.
*
* @implSpec
* This class is intended for use in a single thread.
*
* @since 1.8
*/
public class UnsupportedTemporalTypeException extends DateTimeException {
/**
* Serialization version.
*/
private static final long serialVersionUID = -6158898438688206006L;
/**
* Constructs a new UnsupportedTemporalTypeException with the specified message.
*
* @param message the message to use for this exception, may be null
*/
public UnsupportedTemporalTypeException(String message) {
super(message);
}
/**
* Constructs a new UnsupportedTemporalTypeException with the specified message and cause.
*
* @param message the message to use for this exception, may be null
* @param cause the cause of the exception, may be null
*/
public UnsupportedTemporalTypeException(String message, Throwable cause) {
super(message, cause);
}
}

View file

@ -0,0 +1,431 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Copyright (c) 2011-2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package java.time.temporal;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.time.DateTimeException;
/**
* The range of valid values for a date-time field.
* <p>
* All {@link TemporalField} instances have a valid range of values.
* For example, the ISO day-of-month runs from 1 to somewhere between 28 and 31.
* This class captures that valid range.
* <p>
* It is important to be aware of the limitations of this class.
* Only the minimum and maximum values are provided.
* It is possible for there to be invalid values within the outer range.
* For example, a weird field may have valid values of 1, 2, 4, 6, 7, thus
* have a range of '1 - 7', despite that fact that values 3 and 5 are invalid.
* <p>
* Instances of this class are not tied to a specific field.
*
* @implSpec
* This class is immutable and thread-safe.
*
* @since 1.8
*/
public final class ValueRange implements Serializable {
/**
* Serialization version.
*/
private static final long serialVersionUID = -7317881728594519368L;
/**
* The smallest minimum value.
*/
private final long minSmallest;
/**
* The largest minimum value.
*/
private final long minLargest;
/**
* The smallest maximum value.
*/
private final long maxSmallest;
/**
* The largest maximum value.
*/
private final long maxLargest;
/**
* Obtains a fixed value range.
* <p>
* This factory obtains a range where the minimum and maximum values are fixed.
* For example, the ISO month-of-year always runs from 1 to 12.
*
* @param min the minimum value
* @param max the maximum value
* @return the ValueRange for min, max, not null
* @throws IllegalArgumentException if the minimum is greater than the maximum
*/
public static ValueRange of(long min, long max) {
if (min > max) {
throw new IllegalArgumentException("Minimum value must be less than maximum value");
}
return new ValueRange(min, min, max, max);
}
/**
* Obtains a variable value range.
* <p>
* This factory obtains a range where the minimum value is fixed and the maximum value may vary.
* For example, the ISO day-of-month always starts at 1, but ends between 28 and 31.
*
* @param min the minimum value
* @param maxSmallest the smallest maximum value
* @param maxLargest the largest maximum value
* @return the ValueRange for min, smallest max, largest max, not null
* @throws IllegalArgumentException if
* the minimum is greater than the smallest maximum,
* or the smallest maximum is greater than the largest maximum
*/
public static ValueRange of(long min, long maxSmallest, long maxLargest) {
return of(min, min, maxSmallest, maxLargest);
}
/**
* Obtains a fully variable value range.
* <p>
* This factory obtains a range where both the minimum and maximum value may vary.
*
* @param minSmallest the smallest minimum value
* @param minLargest the largest minimum value
* @param maxSmallest the smallest maximum value
* @param maxLargest the largest maximum value
* @return the ValueRange for smallest min, largest min, smallest max, largest max, not null
* @throws IllegalArgumentException if
* the smallest minimum is greater than the smallest maximum,
* or the smallest maximum is greater than the largest maximum
* or the largest minimum is greater than the largest maximum
*/
public static ValueRange of(long minSmallest, long minLargest, long maxSmallest, long maxLargest) {
if (minSmallest > minLargest) {
throw new IllegalArgumentException("Smallest minimum value must be less than largest minimum value");
}
if (maxSmallest > maxLargest) {
throw new IllegalArgumentException("Smallest maximum value must be less than largest maximum value");
}
if (minLargest > maxLargest) {
throw new IllegalArgumentException("Minimum value must be less than maximum value");
}
return new ValueRange(minSmallest, minLargest, maxSmallest, maxLargest);
}
/**
* Restrictive constructor.
*
* @param minSmallest the smallest minimum value
* @param minLargest the largest minimum value
* @param maxSmallest the smallest minimum value
* @param maxLargest the largest minimum value
*/
private ValueRange(long minSmallest, long minLargest, long maxSmallest, long maxLargest) {
this.minSmallest = minSmallest;
this.minLargest = minLargest;
this.maxSmallest = maxSmallest;
this.maxLargest = maxLargest;
}
//-----------------------------------------------------------------------
/**
* Is the value range fixed and fully known.
* <p>
* For example, the ISO day-of-month runs from 1 to between 28 and 31.
* Since there is uncertainty about the maximum value, the range is not fixed.
* However, for the month of January, the range is always 1 to 31, thus it is fixed.
*
* @return true if the set of values is fixed
*/
public boolean isFixed() {
return minSmallest == minLargest && maxSmallest == maxLargest;
}
//-----------------------------------------------------------------------
/**
* Gets the minimum value that the field can take.
* <p>
* For example, the ISO day-of-month always starts at 1.
* The minimum is therefore 1.
*
* @return the minimum value for this field
*/
public long getMinimum() {
return minSmallest;
}
/**
* Gets the largest possible minimum value that the field can take.
* <p>
* For example, the ISO day-of-month always starts at 1.
* The largest minimum is therefore 1.
*
* @return the largest possible minimum value for this field
*/
public long getLargestMinimum() {
return minLargest;
}
/**
* Gets the smallest possible maximum value that the field can take.
* <p>
* For example, the ISO day-of-month runs to between 28 and 31 days.
* The smallest maximum is therefore 28.
*
* @return the smallest possible maximum value for this field
*/
public long getSmallestMaximum() {
return maxSmallest;
}
/**
* Gets the maximum value that the field can take.
* <p>
* For example, the ISO day-of-month runs to between 28 and 31 days.
* The maximum is therefore 31.
*
* @return the maximum value for this field
*/
public long getMaximum() {
return maxLargest;
}
//-----------------------------------------------------------------------
/**
* Checks if all values in the range fit in an {@code int}.
* <p>
* This checks that all valid values are within the bounds of an {@code int}.
* <p>
* For example, the ISO month-of-year has values from 1 to 12, which fits in an {@code int}.
* By comparison, ISO nano-of-day runs from 1 to 86,400,000,000,000 which does not fit in an {@code int}.
* <p>
* This implementation uses {@link #getMinimum()} and {@link #getMaximum()}.
*
* @return true if a valid value always fits in an {@code int}
*/
public boolean isIntValue() {
return getMinimum() >= Integer.MIN_VALUE && getMaximum() <= Integer.MAX_VALUE;
}
/**
* Checks if the value is within the valid range.
* <p>
* This checks that the value is within the stored range of values.
*
* @param value the value to check
* @return true if the value is valid
*/
public boolean isValidValue(long value) {
return (value >= getMinimum() && value <= getMaximum());
}
/**
* Checks if the value is within the valid range and that all values
* in the range fit in an {@code int}.
* <p>
* This method combines {@link #isIntValue()} and {@link #isValidValue(long)}.
*
* @param value the value to check
* @return true if the value is valid and fits in an {@code int}
*/
public boolean isValidIntValue(long value) {
return isIntValue() && isValidValue(value);
}
/**
* Checks that the specified value is valid.
* <p>
* This validates that the value is within the valid range of values.
* The field is only used to improve the error message.
*
* @param value the value to check
* @param field the field being checked, may be null
* @return the value that was passed in
* @see #isValidValue(long)
*/
public long checkValidValue(long value, TemporalField field) {
if (isValidValue(value) == false) {
throw new DateTimeException(genInvalidFieldMessage(field, value));
}
return value;
}
/**
* Checks that the specified value is valid and fits in an {@code int}.
* <p>
* This validates that the value is within the valid range of values and that
* all valid values are within the bounds of an {@code int}.
* The field is only used to improve the error message.
*
* @param value the value to check
* @param field the field being checked, may be null
* @return the value that was passed in
* @see #isValidIntValue(long)
*/
public int checkValidIntValue(long value, TemporalField field) {
if (isValidIntValue(value) == false) {
throw new DateTimeException(genInvalidFieldMessage(field, value));
}
return (int) value;
}
private String genInvalidFieldMessage(TemporalField field, long value) {
if (field != null) {
return "Invalid value for " + field + " (valid values " + this + "): " + value;
} else {
return "Invalid value (valid values " + this + "): " + value;
}
}
//-----------------------------------------------------------------------
/**
* Restore the state of an ValueRange from the stream.
* Check that the values are valid.
*
* @param s the stream to read
* @throws InvalidObjectException if
* the smallest minimum is greater than the smallest maximum,
* or the smallest maximum is greater than the largest maximum
* or the largest minimum is greater than the largest maximum
* @throws ClassNotFoundException if a class cannot be resolved
*/
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException, InvalidObjectException
{
s.defaultReadObject();
if (minSmallest > minLargest) {
throw new InvalidObjectException("Smallest minimum value must be less than largest minimum value");
}
if (maxSmallest > maxLargest) {
throw new InvalidObjectException("Smallest maximum value must be less than largest maximum value");
}
if (minLargest > maxLargest) {
throw new InvalidObjectException("Minimum value must be less than maximum value");
}
}
//-----------------------------------------------------------------------
/**
* Checks if this range is equal to another range.
* <p>
* The comparison is based on the four values, minimum, largest minimum,
* smallest maximum and maximum.
* Only objects of type {@code ValueRange} are compared, other types return false.
*
* @param obj the object to check, null returns false
* @return true if this is equal to the other range
*/
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof ValueRange) {
ValueRange other = (ValueRange) obj;
return minSmallest == other.minSmallest && minLargest == other.minLargest &&
maxSmallest == other.maxSmallest && maxLargest == other.maxLargest;
}
return false;
}
/**
* A hash code for this range.
*
* @return a suitable hash code
*/
@Override
public int hashCode() {
long hash = minSmallest + (minLargest << 16) + (minLargest >> 48) +
(maxSmallest << 32) + (maxSmallest >> 32) + (maxLargest << 48) +
(maxLargest >> 16);
return (int) (hash ^ (hash >>> 32));
}
//-----------------------------------------------------------------------
/**
* Outputs this range as a {@code String}.
* <p>
* The format will be '{min}/{largestMin} - {smallestMax}/{max}',
* where the largestMin or smallestMax sections may be omitted, together
* with associated slash, if they are the same as the min or max.
*
* @return a string representation of this range, not null
*/
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append(minSmallest);
if (minSmallest != minLargest) {
buf.append('/').append(minLargest);
}
buf.append(" - ").append(maxSmallest);
if (maxSmallest != maxLargest) {
buf.append('/').append(maxLargest);
}
return buf.toString();
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,159 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file:
*
* Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of JSR-310 nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* <p>
* Access to date and time using fields and units, and date time adjusters.
* </p>
* <p>
* This package expands on the base package to provide additional functionality for
* more powerful use cases. Support is included for:
* </p>
* <ul>
* <li>Units of date-time, such as years, months, days and hours</li>
* <li>Fields of date-time, such as month-of-year, day-of-week or hour-of-day</li>
* <li>Date-time adjustment functions</li>
* <li>Different definitions of weeks</li>
* </ul>
*
* <h3>Fields and Units</h3>
* <p>
* Dates and times are expressed in terms of fields and units.
* A unit is used to measure an amount of time, such as years, days or minutes.
* All units implement {@link java.time.temporal.TemporalUnit}.
* The set of well known units is defined in {@link java.time.temporal.ChronoUnit}, such as {@code DAYS}.
* The unit interface is designed to allow application defined units.
* </p>
* <p>
* A field is used to express part of a larger date-time, such as year, month-of-year or second-of-minute.
* All fields implement {@link java.time.temporal.TemporalField}.
* The set of well known fields are defined in {@link java.time.temporal.ChronoField}, such as {@code HOUR_OF_DAY}.
* Additional fields are defined by {@link java.time.temporal.JulianFields}, {@link java.time.temporal.WeekFields}
* and {@link java.time.temporal.IsoFields}.
* The field interface is designed to allow application defined fields.
* </p>
* <p>
* This package provides tools that allow the units and fields of date and time to be accessed
* in a general way most suited for frameworks.
* {@link java.time.temporal.Temporal} provides the abstraction for date time types that support fields.
* Its methods support getting the value of a field, creating a new date time with the value of
* a field modified, and querying for additional information, typically used to extract the offset or time-zone.
* </p>
* <p>
* One use of fields in application code is to retrieve fields for which there is no convenience method.
* For example, getting the day-of-month is common enough that there is a method on {@code LocalDate}
* called {@code getDayOfMonth()}. However for more unusual fields it is necessary to use the field.
* For example, {@code date.get(ChronoField.ALIGNED_WEEK_OF_MONTH)}.
* The fields also provide access to the range of valid values.
* </p>
*
* <h3>Adjustment and Query</h3>
* <p>
* A key part of the date-time problem space is adjusting a date to a new, related value,
* such as the "last day of the month", or "next Wednesday".
* These are modeled as functions that adjust a base date-time.
* The functions implement {@link java.time.temporal.TemporalAdjuster} and operate on {@code Temporal}.
* A set of common functions are provided in {@link java.time.temporal.TemporalAdjusters}.
* For example, to find the first occurrence of a day-of-week after a given date, use
* {@link java.time.temporal.TemporalAdjusters#next(DayOfWeek)}, such as
* {@code date.with(next(MONDAY))}.
* Applications can also define adjusters by implementing {@link java.time.temporal.TemporalAdjuster}.
* </p>
* <p>
* The {@link java.time.temporal.TemporalAmount} interface models amounts of relative time.
* </p>
* <p>
* In addition to adjusting a date-time, an interface is provided to enable querying via
* {@link java.time.temporal.TemporalQuery}.
* The most common implementations of the query interface are method references.
* The {@code from(TemporalAccessor)} methods on major classes can all be used, such as
* {@code LocalDate::from} or {@code Month::from}.
* Further implementations are provided in {@link java.time.temporal.TemporalQueries} as static methods.
* Applications can also define queries by implementing {@link java.time.temporal.TemporalQuery}.
* </p>
*
* <h3>Weeks</h3>
* <p>
* Different locales have different definitions of the week.
* For example, in Europe the week typically starts on a Monday, while in the US it starts on a Sunday.
* The {@link java.time.temporal.WeekFields} class models this distinction.
* </p>
* <p>
* The ISO calendar system defines an additional week-based division of years.
* This defines a year based on whole Monday to Monday weeks.
* This is modeled in {@link java.time.temporal.IsoFields}.
* </p>
*
* <h3>Package specification</h3>
* <p>
* Unless otherwise noted, passing a null argument to a constructor or method in any class or interface
* in this package will cause a {@link java.lang.NullPointerException NullPointerException} to be thrown.
* The Javadoc "@param" definition is used to summarise the null-behavior.
* The "@throws {@link java.lang.NullPointerException}" is not explicitly documented in each method.
* </p>
* <p>
* All calculations should check for numeric overflow and throw either an {@link java.lang.ArithmeticException}
* or a {@link java.time.DateTimeException}.
* </p>
* @since 1.8
*/
package java.time.temporal;