001/*
002 *  Copyright 2001-2005 Stephen Colebourne
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.joda.time;
017
018/**
019 * Defines a time period specified in terms of individual duration fields
020 * such as years and days.
021 * <p>
022 * The implementation of this interface may be mutable or immutable. This
023 * interface only gives access to retrieve data, never to change it.
024 * <p>
025 * Periods are split up into multiple fields, for example days and seconds.
026 * Implementations are not required to evenly distribute the values across the fields.
027 * The value for each field may be positive or negative.
028 * <p>
029 * When a time period is added to an instant, the effect is to add each field in turn.
030 * For example, a time period could be defined as 3 months, 2 days and -1 hours.
031 * In most circumstances this would be the same as 3 months, 1 day, and 23 hours.
032 * However, when adding across a daylight savings boundary, a day may be 23 or 25 hours long.
033 * Thus, the time period is always added field by field to the datetime.
034 * <p>
035 * Periods are independent of chronology, and can only be treated as durations
036 * when paired with a time via an interval.
037 *
038 * @see ReadableDuration
039 * @see ReadableInterval
040 * @author Brian S O'Neill
041 * @author Stephen Colebourne
042 * @since 1.0
043 */
044public interface ReadablePeriod {
045
046    /**
047     * Gets the period type that defines which fields are included in the period.
048     *
049     * @return the period type
050     */
051    PeriodType getPeriodType();
052
053    /**
054     * Gets the number of fields that this period supports.
055     *
056     * @return the number of fields supported
057     */
058    int size();
059
060    /**
061     * Gets the field type at the specified index.
062     *
063     * @param index  the index to retrieve
064     * @return the field at the specified index
065     * @throws IndexOutOfBoundsException if the index is invalid
066     */
067    DurationFieldType getFieldType(int index);
068
069    /**
070     * Gets the value at the specified index.
071     *
072     * @param index  the index to retrieve
073     * @return the value of the field at the specified index
074     * @throws IndexOutOfBoundsException if the index is invalid
075     */
076    int getValue(int index);
077
078    /**
079     * Gets the value of one of the fields.
080     * <p>
081     * If the field type specified is not supported by the period then zero
082     * is returned.
083     *
084     * @param field  the field type to query, null returns zero
085     * @return the value of that field, zero if field not supported
086     */
087    int get(DurationFieldType field);
088
089    /**
090     * Checks whether the field type specified is supported by this period.
091     *
092     * @param field  the field to check, may be null which returns false
093     * @return true if the field is supported
094     */
095    boolean isSupported(DurationFieldType field);
096
097    //-----------------------------------------------------------------------
098    /**
099     * Get this period as an immutable <code>Period</code> object.
100     * <p>
101     * This will either typecast this instance, or create a new <code>Period</code>.
102     * 
103     * @return a Duration using the same field set and values
104     */
105    Period toPeriod();
106
107    /**
108     * Get this object as a <code>MutablePeriod</code>.
109     * <p>
110     * This will always return a new <code>MutablePeriod</code> with the same fields.
111     * 
112     * @return a MutablePeriod using the same field set and values
113     */
114    MutablePeriod toMutablePeriod();
115
116    //-----------------------------------------------------------------------
117    /**
118     * Compares this object with the specified object for equality based
119     * on the value and type of each supported field.
120     * All ReadablePeriod instances are accepted.
121     * <p>
122     * Note that a period of 1 day is not equal to a period of 24 hours,
123     * nor is 1 hour equal to 60 minutes. Only periods with the same amount
124     * in each field are equal.
125     * <p>
126     * This is because periods represent an abstracted definition of a time
127     * period (eg. a day may not actually be 24 hours, it might be 23 or 25
128     * at daylight savings boundary).
129     * <p>
130     * To compare the actual duration of two periods, convert both to
131     * {@link Duration}s, an operation that emphasises that the result may
132     * differ according to the date you choose.
133     *
134     * @param readablePeriod  a readable period to check against
135     * @return true if all the field values and types are equal, false if
136     *  not or the period is null or of an incorrect type
137     */
138    boolean equals(Object readablePeriod);
139
140    /**
141     * Gets a hash code for the period that is compatible with the equals method.
142     * The hashcode is calculated as follows:
143     * <pre>
144     *  int total = 17;
145     *  for (int i = 0; i < fields.length; i++) {
146     *      total = 27 * total + getValue(i);
147     *      total = 27 * total + getFieldType(i).hashCode();
148     *  }
149     *  return total;
150     * </pre>
151     *
152     * @return a hash code
153     */
154    int hashCode();
155
156    //-----------------------------------------------------------------------
157    /**
158     * Gets the value as a String in the style of the ISO8601 duration format.
159     * Technically, the output can breach the ISO specification as weeks may be included.
160     * <p>
161     * For example, "PT6H3M5S" represents 6 hours, 3 minutes, 5 seconds.
162     *
163     * @return the value as an ISO8601 style string
164     */
165    String toString();
166
167}