001/*
002 *    GeoAPI - Java interfaces for OGC/ISO standards
003 *    Copyright © 2004-2024 Open Geospatial Consortium, Inc.
004 *    http://www.geoapi.org
005 *
006 *    Licensed under the Apache License, Version 2.0 (the "License");
007 *    you may not use this file except in compliance with the License.
008 *    You may obtain a copy of the License at
009 *
010 *        http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *    Unless required by applicable law or agreed to in writing, software
013 *    distributed under the License is distributed on an "AS IS" BASIS,
014 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 *    See the License for the specific language governing permissions and
016 *    limitations under the License.
017 */
018package org.opengis.referencing.cs;
019
020import java.util.Map;
021import java.time.temporal.ChronoUnit;
022import java.time.temporal.TemporalUnit;
023import javax.measure.quantity.Time;
024import org.opengis.annotation.UML;
025
026import static org.opengis.annotation.Obligation.*;
027import static org.opengis.annotation.Specification.*;
028
029
030/**
031 * A 1-dimensional coordinate system containing a single time axis.
032 * This coordinate system is used to describe the temporal position of a point
033 * in the specified time units from a time origin implied by the temporal datum.
034 * ISO 19111 defines three forms of temporal coordinate system:
035 *
036 * <ul>
037 *   <li>Measure of a temporal quantity as real numbers.</li>
038 *   <li>Count of a temporal quantity as integer numbers.</li>
039 *   <li>Numbers related to dates or times expressed in the proleptic Gregorian calendar.</li>
040 * </ul>
041 *
042 * Those forms are specified by {@link #getCoordinateType()}.
043 * GeoAPI does not define specialized sub-interfaces for each form.
044 *
045 * <p>This type of CS can be used by coordinate reference systems of type
046 * {@link org.opengis.referencing.crs.TemporalCRS}, potentially in combination with
047 * {@link org.opengis.referencing.crs.DerivedCRS}.</p>
048 *
049 * @author  OGC Topic 2 (for abstract model and documentation)
050 * @author  Martin Desruisseaux (IRD, Geomatys)
051 * @version 3.1
052 * @since   2.0
053 *
054 * @see CSAuthorityFactory#createTimeCS(String)
055 * @see CSFactory#createTimeCS(Map, CoordinateSystemAxis)
056 *
057 * @departure integration
058 *   ISO 19111:2019 renamed this interface from {@code TimeCS} to {@code TemporalCS}.
059 *   GeoAPI has kept the ISO 19111:2007 interface name for historical reasons,
060 *   but also to emphasize the relationship with the {@link java.time} package.
061 */
062@UML(identifier="TemporalCS", specification=ISO_19111)
063public interface TimeCS extends CoordinateSystem {
064    /**
065     * Returns the number of dimensions, which is 1 for this type of coordinate system.
066     *
067     * @return always 1.
068     */
069    @Override
070    default int getDimension() {
071        return 1;
072    }
073
074    /**
075     * Returns the type (measure, integer or data-time) of coordinate values.
076     * If the time interval between two integer values is constant and interpolations are allowed,
077     * then the returned value will typically be {@link CoordinateDataType#MEASURE}.
078     * If the time interval is not constant but can be related to some field of the Gregorian calendar
079     * (e.g., months or years), then the returned value can be {@link CoordinateDataType#DATE_TIME}.
080     *
081     * @return the type of coordinate values.
082     *
083     * @since 3.1
084     */
085    @UML(identifier="coordinateType", obligation=MANDATORY, specification=ISO_19111)
086    CoordinateDataType getCoordinateType();
087
088    /**
089     * Returns the unit of measurement of coordinate values. The returned unit is equivalent to the unit
090     * returned by {@link CoordinateSystemAxis#getUnit()}, but expressed as a {@link java.time} object,
091     * preferably an instance from the {@link ChronoUnit} enumeration.
092     *
093     * <p>Note that contrarily to the usual units of measurement, the duration of {@link java.time} units can vary.
094     * For example {@link ChronoUnit#DAYS} is <em>estimated</em> to be about 24 hours long, because the actual
095     * duration can vary due to daylight saving time changes. Implementations can specify whether the temporal
096     * unit is estimated or exact with {@link TemporalUnit#isDurationEstimated()}.</p>
097     *
098     * <h4>Default implementation</h4>
099     * The default implementation returns a {@link ChronoUnit} or a multiple of a {@code ChronoUnit} with a
100     * {@linkplain ChronoUnit#getDuration() duration} equals to 1 {@linkplain CoordinateSystemAxis#getUnit() axis unit}.
101     * If and only if the {@linkplain #getCoordinateType() coordinate type} is {@link CoordinateDataType#DATE_TIME},
102     * the search for {@link ChronoUnit} is relaxed with an arbitrary tolerance of one hour per month for units
103     * equal or longer than {@link ChronoUnit#MONTHS}.
104     * The intend is to accept different definitions of years, for example, 365.2425 days according Java
105     * versus 365.24219265 days according the <abbr>IUGS</abbr> definition of tropical year.
106     *
107     * @return unit measurement of coordinate values, preferably as a {@link ChronoUnit} enumeration value.
108     *
109     * @see ChronoUnit#SECONDS
110     * @see ChronoUnit#DAYS
111     * @see ChronoUnit#YEARS
112     *
113     * @since 3.1
114     */
115    default TemporalUnit getTemporalUnit() {
116        return TimeUnit.valueOf(getAxis(0).getUnit().asType(Time.class),
117                CoordinateDataType.DATE_TIME.equals(getCoordinateType()));
118    }
119}