View Javadoc

1   /*
2    *  Copyright 2001-2010 Stephen Colebourne
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  package org.joda.time.base;
17  
18  import org.joda.convert.ToString;
19  import org.joda.time.Duration;
20  import org.joda.time.Period;
21  import org.joda.time.ReadableDuration;
22  import org.joda.time.ReadableInstant;
23  import org.joda.time.format.FormatUtils;
24  
25  /**
26   * AbstractDuration provides the common behaviour for duration classes.
27   * <p>
28   * This class should generally not be used directly by API users. The 
29   * {@link ReadableDuration} interface should be used when different 
30   * kinds of durations are to be referenced.
31   * <p>
32   * AbstractDuration subclasses may be mutable and not thread-safe.
33   *
34   * @author Brian S O'Neill
35   * @author Stephen Colebourne
36   * @since 1.0
37   */
38  public abstract class AbstractDuration implements ReadableDuration {
39  
40      /**
41       * Constructor.
42       */
43      protected AbstractDuration() {
44          super();
45      }
46  
47      //-----------------------------------------------------------------------
48      /**
49       * Get this duration as an immutable <code>Duration</code> object.
50       * 
51       * @return a Duration created using the millisecond duration from this instance
52       */
53      public Duration toDuration() {
54          return new Duration(getMillis());
55      }
56  
57      //-----------------------------------------------------------------------
58      /**
59       * Converts this duration to a Period instance using the standard period type
60       * and the ISO chronology.
61       * <p>
62       * Only precise fields in the period type will be used. Thus, only the hour,
63       * minute, second and millisecond fields on the period will be used.
64       * The year, month, week and day fields will not be populated.
65       * <p>
66       * If the duration is small, less than one day, then this method will perform
67       * as you might expect and split the fields evenly.
68       * If the duration is larger than one day then all the remaining duration will
69       * be stored in the largest available field, hours in this case.
70       * <p>
71       * For example, a duration effectively equal to (365 + 60 + 5) days will be
72       * converted to ((365 + 60 + 5) * 24) hours by this constructor.
73       * <p>
74       * For more control over the conversion process, you must pair the duration with
75       * an instant, see {@link Period#Period(ReadableInstant,ReadableDuration)}.
76       * 
77       * @return a Period created using the millisecond duration from this instance
78       */
79      public Period toPeriod() {
80          return new Period(getMillis());
81      }
82  
83      //-----------------------------------------------------------------------
84      /**
85       * Compares this duration with the specified duration based on length.
86       *
87       * @param other  a duration to check against
88       * @return negative value if this is less, 0 if equal, or positive value if greater
89       * @throws NullPointerException if the object is null
90       * @throws ClassCastException if the given object is not supported
91       */
92      public int compareTo(ReadableDuration other) {
93          long thisMillis = this.getMillis();
94          long otherMillis = other.getMillis();
95          
96          // cannot do (thisMillis - otherMillis) as it can overflow
97          if (thisMillis < otherMillis) {
98              return -1;
99          }
100         if (thisMillis > otherMillis) {
101             return 1;
102         }
103         return 0;
104     }
105 
106     /**
107      * Is the length of this duration equal to the duration passed in.
108      *
109      * @param duration  another duration to compare to, null means zero milliseconds
110      * @return true if this duration is equal to than the duration passed in
111      */
112     public boolean isEqual(ReadableDuration duration) {
113         if (duration == null) {
114             duration = Duration.ZERO;
115         }
116         return compareTo(duration) == 0;
117     }
118 
119     /**
120      * Is the length of this duration longer than the duration passed in.
121      *
122      * @param duration  another duration to compare to, null means zero milliseconds
123      * @return true if this duration is equal to than the duration passed in
124      */
125     public boolean isLongerThan(ReadableDuration duration) {
126         if (duration == null) {
127             duration = Duration.ZERO;
128         }
129         return compareTo(duration) > 0;
130     }
131 
132     /**
133      * Is the length of this duration shorter than the duration passed in.
134      *
135      * @param duration  another duration to compare to, null means zero milliseconds
136      * @return true if this duration is equal to than the duration passed in
137      */
138     public boolean isShorterThan(ReadableDuration duration) {
139         if (duration == null) {
140             duration = Duration.ZERO;
141         }
142         return compareTo(duration) < 0;
143     }
144 
145     //-----------------------------------------------------------------------
146     /**
147      * Compares this object with the specified object for equality based
148      * on the millisecond length. All ReadableDuration instances are accepted.
149      *
150      * @param duration  a readable duration to check against
151      * @return true if the length of the duration is equal
152      */
153     public boolean equals(Object duration) {
154         if (this == duration) {
155             return true;
156         }
157         if (duration instanceof ReadableDuration == false) {
158             return false;
159         }
160         ReadableDuration other = (ReadableDuration) duration;
161         return (getMillis() == other.getMillis());
162     }
163 
164     /**
165      * Gets a hash code for the duration that is compatible with the 
166      * equals method.
167      *
168      * @return a hash code
169      */
170     public int hashCode() {
171         long len = getMillis();
172         return (int) (len ^ (len >>> 32));
173     }
174 
175     //-----------------------------------------------------------------------
176     /**
177      * Gets the value as a String in the ISO8601 duration format including
178      * only seconds and milliseconds.
179      * <p>
180      * For example, "PT72.345S" represents 1 minute, 12 seconds and 345 milliseconds.
181      * <p>
182      * For more control over the output, see
183      * {@link org.joda.time.format.PeriodFormatterBuilder PeriodFormatterBuilder}.
184      *
185      * @return the value as an ISO8601 string
186      */
187     @ToString
188     public String toString() {
189         long millis = getMillis();
190         StringBuffer buf = new StringBuffer();
191         buf.append("PT");
192         boolean negative = (millis < 0);
193         FormatUtils.appendUnpaddedInteger(buf, millis);
194         while (buf.length() < (negative ? 7 : 6)) {
195             buf.insert(negative ? 3 : 2, "0");
196         }
197         if ((millis / 1000) * 1000 == millis) {
198             buf.setLength(buf.length() - 3);
199         } else {
200             buf.insert(buf.length() - 3, ".");
201         }
202         buf.append('S');
203         return buf.toString();
204     }
205 
206 }