001 /* 002 * Copyright 2001-2010 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 */ 016 package org.joda.time.base; 017 018 import org.joda.convert.ToString; 019 import org.joda.time.Duration; 020 import org.joda.time.Period; 021 import org.joda.time.ReadableDuration; 022 import org.joda.time.ReadableInstant; 023 import org.joda.time.format.FormatUtils; 024 025 /** 026 * AbstractDuration provides the common behaviour for duration classes. 027 * <p> 028 * This class should generally not be used directly by API users. The 029 * {@link ReadableDuration} interface should be used when different 030 * kinds of durations are to be referenced. 031 * <p> 032 * AbstractDuration subclasses may be mutable and not thread-safe. 033 * 034 * @author Brian S O'Neill 035 * @author Stephen Colebourne 036 * @since 1.0 037 */ 038 public abstract class AbstractDuration implements ReadableDuration { 039 040 /** 041 * Constructor. 042 */ 043 protected AbstractDuration() { 044 super(); 045 } 046 047 //----------------------------------------------------------------------- 048 /** 049 * Get this duration as an immutable <code>Duration</code> object. 050 * 051 * @return a Duration created using the millisecond duration from this instance 052 */ 053 public Duration toDuration() { 054 return new Duration(getMillis()); 055 } 056 057 //----------------------------------------------------------------------- 058 /** 059 * Converts this duration to a Period instance using the standard period type 060 * and the ISO chronology. 061 * <p> 062 * Only precise fields in the period type will be used. Thus, only the hour, 063 * minute, second and millisecond fields on the period will be used. 064 * The year, month, week and day fields will not be populated. 065 * <p> 066 * If the duration is small, less than one day, then this method will perform 067 * as you might expect and split the fields evenly. 068 * If the duration is larger than one day then all the remaining duration will 069 * be stored in the largest available field, hours in this case. 070 * <p> 071 * For example, a duration effectively equal to (365 + 60 + 5) days will be 072 * converted to ((365 + 60 + 5) * 24) hours by this constructor. 073 * <p> 074 * For more control over the conversion process, you must pair the duration with 075 * an instant, see {@link Period#Period(ReadableInstant,ReadableDuration)}. 076 * 077 * @return a Period created using the millisecond duration from this instance 078 */ 079 public Period toPeriod() { 080 return new Period(getMillis()); 081 } 082 083 //----------------------------------------------------------------------- 084 /** 085 * Compares this duration with the specified duration based on length. 086 * 087 * @param other a duration to check against 088 * @return negative value if this is less, 0 if equal, or positive value if greater 089 * @throws NullPointerException if the object is null 090 * @throws ClassCastException if the given object is not supported 091 */ 092 public int compareTo(ReadableDuration other) { 093 long thisMillis = this.getMillis(); 094 long otherMillis = other.getMillis(); 095 096 // cannot do (thisMillis - otherMillis) as it can overflow 097 if (thisMillis < otherMillis) { 098 return -1; 099 } 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 }