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 */ 016 package org.joda.time.base; 017 018 import org.joda.time.Duration; 019 import org.joda.time.Period; 020 import org.joda.time.ReadableDuration; 021 import org.joda.time.format.FormatUtils; 022 023 /** 024 * AbstractDuration provides the common behaviour for duration classes. 025 * <p> 026 * This class should generally not be used directly by API users. The 027 * {@link ReadableDuration} interface should be used when different 028 * kinds of durations are to be referenced. 029 * <p> 030 * AbstractDuration subclasses may be mutable and not thread-safe. 031 * 032 * @author Brian S O'Neill 033 * @author Stephen Colebourne 034 * @since 1.0 035 */ 036 public abstract class AbstractDuration implements ReadableDuration { 037 038 /** 039 * Constructor. 040 */ 041 protected AbstractDuration() { 042 super(); 043 } 044 045 //----------------------------------------------------------------------- 046 /** 047 * Get this duration as an immutable <code>Duration</code> object. 048 * 049 * @return a Duration created using the millisecond duration from this instance 050 */ 051 public Duration toDuration() { 052 return new Duration(getMillis()); 053 } 054 055 //----------------------------------------------------------------------- 056 /** 057 * Converts this duration to a Period instance using the standard period type 058 * and the ISO chronology. 059 * <p> 060 * Only precise fields in the period type will be used. Thus, only the hour, 061 * minute, second and millisecond fields on the period will be used. 062 * The year, month, week and day fields will not be populated. 063 * <p> 064 * If the duration is small, less than one day, then this method will perform 065 * as you might expect and split the fields evenly. 066 * If the duration is larger than one day then all the remaining duration will 067 * be stored in the largest available field, hours in this case. 068 * <p> 069 * For example, a duration effectively equal to (365 + 60 + 5) days will be 070 * converted to ((365 + 60 + 5) * 24) hours by this constructor. 071 * <p> 072 * For more control over the conversion process, you must pair the duration with 073 * an instant, see {@link Period#Period(ReadableInstant,ReadableDuration)}. 074 * 075 * @return a Period created using the millisecond duration from this instance 076 */ 077 public Period toPeriod() { 078 return new Period(getMillis()); 079 } 080 081 //----------------------------------------------------------------------- 082 /** 083 * Compares this duration with the specified duration based on length. 084 * 085 * @param obj a duration to check against 086 * @return negative value if this is less, 0 if equal, or positive value if greater 087 * @throws NullPointerException if the object is null 088 * @throws ClassCastException if the given object is not supported 089 */ 090 public int compareTo(Object obj) { 091 // Comparable contract means we cannot handle null or other types gracefully 092 ReadableDuration thisDuration = (ReadableDuration) this; 093 ReadableDuration otherDuration = (ReadableDuration) obj; 094 095 long thisMillis = thisDuration.getMillis(); 096 long otherMillis = otherDuration.getMillis(); 097 098 // cannot do (thisMillis - otherMillis) as it can overflow 099 if (thisMillis < otherMillis) { 100 return -1; 101 } 102 if (thisMillis > otherMillis) { 103 return 1; 104 } 105 return 0; 106 } 107 108 /** 109 * Is the length of this duration equal to the duration passed in. 110 * 111 * @param duration another duration to compare to, null means zero milliseconds 112 * @return true if this duration is equal to than the duration passed in 113 */ 114 public boolean isEqual(ReadableDuration duration) { 115 if (duration == null) { 116 duration = Duration.ZERO; 117 } 118 return compareTo(duration) == 0; 119 } 120 121 /** 122 * Is the length of this duration longer than the duration passed in. 123 * 124 * @param duration another duration to compare to, null means zero milliseconds 125 * @return true if this duration is equal to than the duration passed in 126 */ 127 public boolean isLongerThan(ReadableDuration duration) { 128 if (duration == null) { 129 duration = Duration.ZERO; 130 } 131 return compareTo(duration) > 0; 132 } 133 134 /** 135 * Is the length of this duration shorter than the duration passed in. 136 * 137 * @param duration another duration to compare to, null means zero milliseconds 138 * @return true if this duration is equal to than the duration passed in 139 */ 140 public boolean isShorterThan(ReadableDuration duration) { 141 if (duration == null) { 142 duration = Duration.ZERO; 143 } 144 return compareTo(duration) < 0; 145 } 146 147 //----------------------------------------------------------------------- 148 /** 149 * Compares this object with the specified object for equality based 150 * on the millisecond length. All ReadableDuration instances are accepted. 151 * 152 * @param duration a readable duration to check against 153 * @return true if the length of the duration is equal 154 */ 155 public boolean equals(Object duration) { 156 if (this == duration) { 157 return true; 158 } 159 if (duration instanceof ReadableDuration == false) { 160 return false; 161 } 162 ReadableDuration other = (ReadableDuration) duration; 163 return (getMillis() == other.getMillis()); 164 } 165 166 /** 167 * Gets a hash code for the duration that is compatible with the 168 * equals method. 169 * 170 * @return a hash code 171 */ 172 public int hashCode() { 173 long len = getMillis(); 174 return (int) (len ^ (len >>> 32)); 175 } 176 177 //----------------------------------------------------------------------- 178 /** 179 * Gets the value as a String in the ISO8601 duration format including 180 * only seconds and milliseconds. 181 * <p> 182 * For example, "PT72.345S" represents 1 minute, 12 seconds and 345 milliseconds. 183 * <p> 184 * For more control over the output, see 185 * {@link org.joda.time.format.PeriodFormatterBuilder PeriodFormatterBuilder}. 186 * 187 * @return the value as an ISO8601 string 188 */ 189 public String toString() { 190 long millis = getMillis(); 191 StringBuffer buf = new StringBuffer(); 192 buf.append("PT"); 193 FormatUtils.appendUnpaddedInteger(buf, millis / 1000); 194 long part = Math.abs(millis % 1000); 195 if (part > 0) { 196 buf.append('.'); 197 FormatUtils.appendPaddedInteger(buf, part, 3); 198 } 199 buf.append('S'); 200 return buf.toString(); 201 } 202 203 }