Home | History | Annotate | Download | only in chrono
      1 /*
      2  * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
      3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      4  *
      5  * This code is free software; you can redistribute it and/or modify it
      6  * under the terms of the GNU General Public License version 2 only, as
      7  * published by the Free Software Foundation.  Oracle designates this
      8  * particular file as subject to the "Classpath" exception as provided
      9  * by Oracle in the LICENSE file that accompanied this code.
     10  *
     11  * This code is distributed in the hope that it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  * version 2 for more details (a copy is included in the LICENSE file that
     15  * accompanied this code).
     16  *
     17  * You should have received a copy of the GNU General Public License version
     18  * 2 along with this work; if not, write to the Free Software Foundation,
     19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     20  *
     21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     22  * or visit www.oracle.com if you need additional information or have any
     23  * questions.
     24  */
     25 
     26 /*
     27  * This file is available under and governed by the GNU General Public
     28  * License version 2 only, as published by the Free Software Foundation.
     29  * However, the following notice accompanied the original version of this
     30  * file:
     31  *
     32  * Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos
     33  *
     34  * All rights reserved.
     35  *
     36  * Redistribution and use in source and binary forms, with or without
     37  * modification, are permitted provided that the following conditions are met:
     38  *
     39  *  * Redistributions of source code must retain the above copyright notice,
     40  *    this list of conditions and the following disclaimer.
     41  *
     42  *  * Redistributions in binary form must reproduce the above copyright notice,
     43  *    this list of conditions and the following disclaimer in the documentation
     44  *    and/or other materials provided with the distribution.
     45  *
     46  *  * Neither the name of JSR-310 nor the names of its contributors
     47  *    may be used to endorse or promote products derived from this software
     48  *    without specific prior written permission.
     49  *
     50  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     51  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     52  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     53  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     54  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     55  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     56  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     57  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     58  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     59  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     60  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     61  */
     62 package java.time.chrono;
     63 
     64 import static java.time.temporal.ChronoField.ERA;
     65 import static java.time.temporal.ChronoUnit.ERAS;
     66 
     67 import java.time.DateTimeException;
     68 import java.time.temporal.UnsupportedTemporalTypeException;
     69 import java.time.format.DateTimeFormatterBuilder;
     70 import java.time.format.TextStyle;
     71 import java.time.temporal.ChronoField;
     72 import java.time.temporal.Temporal;
     73 import java.time.temporal.TemporalAccessor;
     74 import java.time.temporal.TemporalAdjuster;
     75 import java.time.temporal.TemporalField;
     76 import java.time.temporal.TemporalQueries;
     77 import java.time.temporal.TemporalQuery;
     78 import java.time.temporal.ValueRange;
     79 import java.util.Locale;
     80 
     81 /**
     82  * An era of the time-line.
     83  * <p>
     84  * Most calendar systems have a single epoch dividing the time-line into two eras.
     85  * However, some calendar systems, have multiple eras, such as one for the reign
     86  * of each leader.
     87  * In all cases, the era is conceptually the largest division of the time-line.
     88  * Each chronology defines the Era's that are known Eras and a
     89  * {@link Chronology#eras Chronology.eras} to get the valid eras.
     90  * <p>
     91  * For example, the Thai Buddhist calendar system divides time into two eras,
     92  * before and after a single date. By contrast, the Japanese calendar system
     93  * has one era for the reign of each Emperor.
     94  * <p>
     95  * Instances of {@code Era} may be compared using the {@code ==} operator.
     96  *
     97  * @implSpec
     98  * This interface must be implemented with care to ensure other classes operate correctly.
     99  * All implementations must be singletons - final, immutable and thread-safe.
    100  * It is recommended to use an enum whenever possible.
    101  *
    102  * @since 1.8
    103  */
    104 public interface Era extends TemporalAccessor, TemporalAdjuster {
    105 
    106     /**
    107      * Gets the numeric value associated with the era as defined by the chronology.
    108      * Each chronology defines the predefined Eras and methods to list the Eras
    109      * of the chronology.
    110      * <p>
    111      * All fields, including eras, have an associated numeric value.
    112      * The meaning of the numeric value for era is determined by the chronology
    113      * according to these principles:
    114      * <ul>
    115      * <li>The era in use at the epoch 1970-01-01 (ISO) has the value 1.
    116      * <li>Later eras have sequentially higher values.
    117      * <li>Earlier eras have sequentially lower values, which may be negative.
    118      * </ul>
    119      *
    120      * @return the numeric era value
    121      */
    122     int getValue();
    123 
    124     //-----------------------------------------------------------------------
    125     /**
    126      * Checks if the specified field is supported.
    127      * <p>
    128      * This checks if this era can be queried for the specified field.
    129      * If false, then calling the {@link #range(TemporalField) range} and
    130      * {@link #get(TemporalField) get} methods will throw an exception.
    131      * <p>
    132      * If the field is a {@link ChronoField} then the query is implemented here.
    133      * The {@code ERA} field returns true.
    134      * All other {@code ChronoField} instances will return false.
    135      * <p>
    136      * If the field is not a {@code ChronoField}, then the result of this method
    137      * is obtained by invoking {@code TemporalField.isSupportedBy(TemporalAccessor)}
    138      * passing {@code this} as the argument.
    139      * Whether the field is supported is determined by the field.
    140      *
    141      * @param field  the field to check, null returns false
    142      * @return true if the field is supported on this era, false if not
    143      */
    144     @Override
    145     default boolean isSupported(TemporalField field) {
    146         if (field instanceof ChronoField) {
    147             return field == ERA;
    148         }
    149         return field != null && field.isSupportedBy(this);
    150     }
    151 
    152     /**
    153      * Gets the range of valid values for the specified field.
    154      * <p>
    155      * The range object expresses the minimum and maximum valid values for a field.
    156      * This era is used to enhance the accuracy of the returned range.
    157      * If it is not possible to return the range, because the field is not supported
    158      * or for some other reason, an exception is thrown.
    159      * <p>
    160      * If the field is a {@link ChronoField} then the query is implemented here.
    161      * The {@code ERA} field returns the range.
    162      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
    163      * <p>
    164      * If the field is not a {@code ChronoField}, then the result of this method
    165      * is obtained by invoking {@code TemporalField.rangeRefinedBy(TemporalAccessor)}
    166      * passing {@code this} as the argument.
    167      * Whether the range can be obtained is determined by the field.
    168      * <p>
    169      * The default implementation must return a range for {@code ERA} from
    170      * zero to one, suitable for two era calendar systems such as ISO.
    171      *
    172      * @param field  the field to query the range for, not null
    173      * @return the range of valid values for the field, not null
    174      * @throws DateTimeException if the range for the field cannot be obtained
    175      * @throws UnsupportedTemporalTypeException if the unit is not supported
    176      */
    177     @Override  // override for Javadoc
    178     default ValueRange range(TemporalField field) {
    179         return TemporalAccessor.super.range(field);
    180     }
    181 
    182     /**
    183      * Gets the value of the specified field from this era as an {@code int}.
    184      * <p>
    185      * This queries this era for the value of the specified field.
    186      * The returned value will always be within the valid range of values for the field.
    187      * If it is not possible to return the value, because the field is not supported
    188      * or for some other reason, an exception is thrown.
    189      * <p>
    190      * If the field is a {@link ChronoField} then the query is implemented here.
    191      * The {@code ERA} field returns the value of the era.
    192      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
    193      * <p>
    194      * If the field is not a {@code ChronoField}, then the result of this method
    195      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
    196      * passing {@code this} as the argument. Whether the value can be obtained,
    197      * and what the value represents, is determined by the field.
    198      *
    199      * @param field  the field to get, not null
    200      * @return the value for the field
    201      * @throws DateTimeException if a value for the field cannot be obtained or
    202      *         the value is outside the range of valid values for the field
    203      * @throws UnsupportedTemporalTypeException if the field is not supported or
    204      *         the range of values exceeds an {@code int}
    205      * @throws ArithmeticException if numeric overflow occurs
    206      */
    207     @Override  // override for Javadoc and performance
    208     default int get(TemporalField field) {
    209         if (field == ERA) {
    210             return getValue();
    211         }
    212         return TemporalAccessor.super.get(field);
    213     }
    214 
    215     /**
    216      * Gets the value of the specified field from this era as a {@code long}.
    217      * <p>
    218      * This queries this era for the value of the specified field.
    219      * If it is not possible to return the value, because the field is not supported
    220      * or for some other reason, an exception is thrown.
    221      * <p>
    222      * If the field is a {@link ChronoField} then the query is implemented here.
    223      * The {@code ERA} field returns the value of the era.
    224      * All other {@code ChronoField} instances will throw an {@code UnsupportedTemporalTypeException}.
    225      * <p>
    226      * If the field is not a {@code ChronoField}, then the result of this method
    227      * is obtained by invoking {@code TemporalField.getFrom(TemporalAccessor)}
    228      * passing {@code this} as the argument. Whether the value can be obtained,
    229      * and what the value represents, is determined by the field.
    230      *
    231      * @param field  the field to get, not null
    232      * @return the value for the field
    233      * @throws DateTimeException if a value for the field cannot be obtained
    234      * @throws UnsupportedTemporalTypeException if the field is not supported
    235      * @throws ArithmeticException if numeric overflow occurs
    236      */
    237     @Override
    238     default long getLong(TemporalField field) {
    239         if (field == ERA) {
    240             return getValue();
    241         } else if (field instanceof ChronoField) {
    242             throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
    243         }
    244         return field.getFrom(this);
    245     }
    246 
    247     //-----------------------------------------------------------------------
    248     /**
    249      * Queries this era using the specified query.
    250      * <p>
    251      * This queries this era using the specified query strategy object.
    252      * The {@code TemporalQuery} object defines the logic to be used to
    253      * obtain the result. Read the documentation of the query to understand
    254      * what the result of this method will be.
    255      * <p>
    256      * The result of this method is obtained by invoking the
    257      * {@link TemporalQuery#queryFrom(TemporalAccessor)} method on the
    258      * specified query passing {@code this} as the argument.
    259      *
    260      * @param <R> the type of the result
    261      * @param query  the query to invoke, not null
    262      * @return the query result, null may be returned (defined by the query)
    263      * @throws DateTimeException if unable to query (defined by the query)
    264      * @throws ArithmeticException if numeric overflow occurs (defined by the query)
    265      */
    266     @SuppressWarnings("unchecked")
    267     @Override
    268     default <R> R query(TemporalQuery<R> query) {
    269         if (query == TemporalQueries.precision()) {
    270             return (R) ERAS;
    271         }
    272         return TemporalAccessor.super.query(query);
    273     }
    274 
    275     /**
    276      * Adjusts the specified temporal object to have the same era as this object.
    277      * <p>
    278      * This returns a temporal object of the same observable type as the input
    279      * with the era changed to be the same as this.
    280      * <p>
    281      * The adjustment is equivalent to using {@link Temporal#with(TemporalField, long)}
    282      * passing {@link ChronoField#ERA} as the field.
    283      * <p>
    284      * In most cases, it is clearer to reverse the calling pattern by using
    285      * {@link Temporal#with(TemporalAdjuster)}:
    286      * <pre>
    287      *   // these two lines are equivalent, but the second approach is recommended
    288      *   temporal = thisEra.adjustInto(temporal);
    289      *   temporal = temporal.with(thisEra);
    290      * </pre>
    291      * <p>
    292      * This instance is immutable and unaffected by this method call.
    293      *
    294      * @param temporal  the target object to be adjusted, not null
    295      * @return the adjusted object, not null
    296      * @throws DateTimeException if unable to make the adjustment
    297      * @throws ArithmeticException if numeric overflow occurs
    298      */
    299     @Override
    300     default Temporal adjustInto(Temporal temporal) {
    301         return temporal.with(ERA, getValue());
    302     }
    303 
    304     //-----------------------------------------------------------------------
    305     /**
    306      * Gets the textual representation of this era.
    307      * <p>
    308      * This returns the textual name used to identify the era,
    309      * suitable for presentation to the user.
    310      * The parameters control the style of the returned text and the locale.
    311      * <p>
    312      * If no textual mapping is found then the {@link #getValue() numeric value} is returned.
    313      * <p>
    314      * This default implementation is suitable for all implementations.
    315      *
    316      * @param style  the style of the text required, not null
    317      * @param locale  the locale to use, not null
    318      * @return the text value of the era, not null
    319      */
    320     default String getDisplayName(TextStyle style, Locale locale) {
    321         return new DateTimeFormatterBuilder().appendText(ERA, style).toFormatter(locale).format(this);
    322     }
    323 
    324     // NOTE: methods to convert year-of-era/proleptic-year cannot be here as they may depend on month/day (Japanese)
    325 }
    326