1 /* 2 * Copyright 2001-2011 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 java.io.Serializable; 19 20 import org.joda.time.Chronology; 21 import org.joda.time.DateTimeUtils; 22 import org.joda.time.Interval; 23 import org.joda.time.Period; 24 import org.joda.time.PeriodType; 25 import org.joda.time.ReadableDuration; 26 import org.joda.time.ReadableInstant; 27 import org.joda.time.convert.ConverterManager; 28 import org.joda.time.convert.DurationConverter; 29 import org.joda.time.field.FieldUtils; 30 31 /** 32 * BaseDuration is an abstract implementation of ReadableDuration that stores 33 * data in a <code>long</code> duration milliseconds field. 34 * <p> 35 * This class should generally not be used directly by API users. 36 * The {@link ReadableDuration} interface should be used when different 37 * kinds of duration objects are to be referenced. 38 * <p> 39 * BaseDuration subclasses may be mutable and not thread-safe. 40 * 41 * @author Brian S O'Neill 42 * @author Stephen Colebourne 43 * @since 1.0 44 */ 45 public abstract class BaseDuration 46 extends AbstractDuration 47 implements ReadableDuration, Serializable { 48 49 /** Serialization version */ 50 private static final long serialVersionUID = 2581698638990L; 51 52 /** The duration length */ 53 private volatile long iMillis; 54 55 /** 56 * Creates a duration from the given millisecond duration. 57 * 58 * @param duration the duration, in milliseconds 59 */ 60 protected BaseDuration(long duration) { 61 super(); 62 iMillis = duration; 63 } 64 65 /** 66 * Creates a duration from the given interval endpoints. 67 * 68 * @param startInstant interval start, in milliseconds 69 * @param endInstant interval end, in milliseconds 70 * @throws ArithmeticException if the duration exceeds a 64 bit long 71 */ 72 protected BaseDuration(long startInstant, long endInstant) { 73 super(); 74 iMillis = FieldUtils.safeAdd(endInstant, -startInstant); 75 } 76 77 /** 78 * Creates a duration from the given interval endpoints. 79 * 80 * @param start interval start, null means now 81 * @param end interval end, null means now 82 * @throws ArithmeticException if the duration exceeds a 64 bit long 83 */ 84 protected BaseDuration(ReadableInstant start, ReadableInstant end) { 85 super(); 86 if (start == end) { 87 iMillis = 0L; 88 } else { 89 long startMillis = DateTimeUtils.getInstantMillis(start); 90 long endMillis = DateTimeUtils.getInstantMillis(end); 91 iMillis = FieldUtils.safeAdd(endMillis, -startMillis); 92 } 93 } 94 95 /** 96 * Creates a duration from the specified object using the 97 * {@link org.joda.time.convert.ConverterManager ConverterManager}. 98 * 99 * @param duration duration to convert 100 * @throws IllegalArgumentException if duration is invalid 101 */ 102 protected BaseDuration(Object duration) { 103 super(); 104 DurationConverter converter = ConverterManager.getInstance().getDurationConverter(duration); 105 iMillis = converter.getDurationMillis(duration); 106 } 107 108 //----------------------------------------------------------------------- 109 /** 110 * Gets the length of this duration in milliseconds. 111 * 112 * @return the length of the duration in milliseconds. 113 */ 114 public long getMillis() { 115 return iMillis; 116 } 117 118 //----------------------------------------------------------------------- 119 /** 120 * Sets the length of this duration in milliseconds. 121 * 122 * @param duration the new length of the duration 123 */ 124 protected void setMillis(long duration) { 125 iMillis = duration; 126 } 127 128 //----------------------------------------------------------------------- 129 /** 130 * Converts this duration to a Period instance using the specified period type 131 * and the ISO chronology. 132 * <p> 133 * Only precise fields in the period type will be used. 134 * At most these are hours, minutes, seconds and millis - the period 135 * type may restrict the selection further. 136 * <p> 137 * For more control over the conversion process, you must pair the duration with 138 * an instant, see {@link #toPeriodFrom(ReadableInstant, PeriodType)}. 139 * 140 * @param type the period type to use, null means standard 141 * @return a Period created using the millisecond duration from this instance 142 */ 143 public Period toPeriod(PeriodType type) { 144 return new Period(getMillis(), type); 145 } 146 147 /** 148 * Converts this duration to a Period instance using the standard period type 149 * and the specified chronology. 150 * <p> 151 * Only precise fields in the period type will be used. 152 * Exactly which fields are precise depends on the chronology. 153 * Only the time fields are precise for ISO chronology with a time zone. 154 * However, ISO UTC also has precise days and weeks. 155 * <p> 156 * For more control over the conversion process, you must pair the duration with 157 * an instant, see {@link #toPeriodFrom(ReadableInstant)} and 158 * {@link #toPeriodTo(ReadableInstant)} 159 * 160 * @param chrono the chronology to use, null means ISO default 161 * @return a Period created using the millisecond duration from this instance 162 */ 163 public Period toPeriod(Chronology chrono) { 164 return new Period(getMillis(), chrono); 165 } 166 167 /** 168 * Converts this duration to a Period instance using the specified period type 169 * and chronology. 170 * <p> 171 * Only precise fields in the period type will be used. 172 * Exactly which fields are precise depends on the chronology. 173 * Only the time fields are precise for ISO chronology with a time zone. 174 * However, ISO UTC also has precise days and weeks. 175 * <p> 176 * For more control over the conversion process, you must pair the duration with 177 * an instant, see {@link #toPeriodFrom(ReadableInstant, PeriodType)} and 178 * {@link #toPeriodTo(ReadableInstant, PeriodType)} 179 * 180 * @param type the period type to use, null means standard 181 * @param chrono the chronology to use, null means ISO default 182 * @return a Period created using the millisecond duration from this instance 183 */ 184 public Period toPeriod(PeriodType type, Chronology chrono) { 185 return new Period(getMillis(), type, chrono); 186 } 187 188 /** 189 * Converts this duration to a Period instance by adding the duration to a start 190 * instant to obtain an interval using the standard period type. 191 * <p> 192 * This conversion will determine the fields of a period accurately. 193 * The results are based on the instant millis, the chronology of the instant, 194 * the standard period type and the length of this duration. 195 * 196 * @param startInstant the instant to calculate the period from, null means now 197 * @return a Period created using the millisecond duration from this instance 198 */ 199 public Period toPeriodFrom(ReadableInstant startInstant) { 200 return new Period(startInstant, this); 201 } 202 203 /** 204 * Converts this duration to a Period instance by adding the duration to a start 205 * instant to obtain an interval. 206 * <p> 207 * This conversion will determine the fields of a period accurately. 208 * The results are based on the instant millis, the chronology of the instant, 209 * the period type and the length of this duration. 210 * 211 * @param startInstant the instant to calculate the period from, null means now 212 * @param type the period type determining how to split the duration into fields, null means All type 213 * @return a Period created using the millisecond duration from this instance 214 */ 215 public Period toPeriodFrom(ReadableInstant startInstant, PeriodType type) { 216 return new Period(startInstant, this, type); 217 } 218 219 /** 220 * Converts this duration to a Period instance by subtracting the duration 221 * from an end instant to obtain an interval using the standard period 222 * type. 223 * <p> 224 * This conversion will determine the fields of a period accurately. 225 * The results are based on the instant millis, the chronology of the instant, 226 * the standard period type and the length of this duration. 227 * 228 * @param endInstant the instant to calculate the period to, null means now 229 * @return a Period created using the millisecond duration from this instance 230 */ 231 public Period toPeriodTo(ReadableInstant endInstant) { 232 return new Period(this, endInstant); 233 } 234 235 /** 236 * Converts this duration to a Period instance by subtracting the duration 237 * from an end instant to obtain an interval using the standard period 238 * type. 239 * <p> 240 * This conversion will determine the fields of a period accurately. 241 * The results are based on the instant millis, the chronology of the instant, 242 * the period type and the length of this duration. 243 * 244 * @param endInstant the instant to calculate the period to, null means now 245 * @param type the period type determining how to split the duration into fields, null means All type 246 * @return a Period created using the millisecond duration from this instance 247 */ 248 public Period toPeriodTo(ReadableInstant endInstant, PeriodType type) { 249 return new Period(this, endInstant, type); 250 } 251 252 /** 253 * Converts this duration to an Interval starting at the specified instant. 254 * 255 * @param startInstant the instant to start the interval at, null means now 256 * @return an Interval starting at the specified instant 257 */ 258 public Interval toIntervalFrom(ReadableInstant startInstant) { 259 return new Interval(startInstant, this); 260 } 261 262 /** 263 * Converts this duration to an Interval ending at the specified instant. 264 * 265 * @param endInstant the instant to end the interval at, null means now 266 * @return an Interval ending at the specified instant 267 */ 268 public Interval toIntervalTo(ReadableInstant endInstant) { 269 return new Interval(this, endInstant); 270 } 271 272 }