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 */
016package org.joda.time;
017
018import java.io.Serializable;
019
020import org.joda.convert.FromString;
021import org.joda.time.base.BaseDuration;
022import org.joda.time.field.FieldUtils;
023
024/**
025 * An immutable duration specifying a length of time in milliseconds.
026 * <p>
027 * A duration is defined by a fixed number of milliseconds.
028 * There is no concept of fields, such as days or seconds, as these fields can vary in length.
029 * A duration may be converted to a {@link Period} to obtain field values.
030 * This conversion will typically cause a loss of precision however.
031 * <p>
032 * Duration is thread-safe and immutable.
033 *
034 * @author Brian S O'Neill
035 * @author Stephen Colebourne
036 * @since 1.0
037 */
038public final class Duration
039        extends BaseDuration
040        implements ReadableDuration, Serializable {
041
042    /** Constant representing zero millisecond duration */
043    public static final Duration ZERO = new Duration(0L);
044
045    /** Serialization version */
046    private static final long serialVersionUID = 2471658376918L;
047
048    //-----------------------------------------------------------------------
049    /**
050     * Parses a {@code Duration} from the specified string.
051     * <p>
052     * This parses the format {@code PTa.bS}, as per {@link #toString()}.
053     * 
054     * @param str  the string to parse, not null
055     * @since 2.0
056     */
057    @FromString
058    public static Duration parse(String str) {
059        return new Duration(str);
060    }
061
062    //-----------------------------------------------------------------------
063    /**
064     * Create a duration with the specified number of days assuming that
065     * there are the standard number of milliseconds in a day.
066     * <p>
067     * This method assumes that there are 24 hours in a day,
068     * 60 minutes in an hour, 60 seconds in a minute and 1000 milliseconds in
069     * a second. This will be true for most days, however days with Daylight
070     * Savings changes will not have 24 hours, so use this method with care.
071     * <p>
072     * A Duration is a representation of an amount of time. If you want to express
073     * the concepts of 'days' you should consider using the {@link Days} class.
074     *
075     * @param days  the number of standard days in this duration
076     * @return the duration, never null
077     * @throws ArithmeticException if the days value is too large
078     * @since 1.6
079     */
080    public static Duration standardDays(long days) {
081        if (days == 0) {
082            return ZERO;
083        }
084        return new Duration(FieldUtils.safeMultiply(days, DateTimeConstants.MILLIS_PER_DAY));
085    }
086
087    /**
088     * Create a duration with the specified number of hours assuming that
089     * there are the standard number of milliseconds in an hour.
090     * <p>
091     * This method assumes that there are 60 minutes in an hour,
092     * 60 seconds in a minute and 1000 milliseconds in a second.
093     * All currently supplied chronologies use this definition.
094     * <p>
095     * A Duration is a representation of an amount of time. If you want to express
096     * the concepts of 'hours' you should consider using the {@link Hours} class.
097     *
098     * @param hours  the number of standard hours in this duration
099     * @return the duration, never null
100     * @throws ArithmeticException if the hours value is too large
101     * @since 1.6
102     */
103    public static Duration standardHours(long hours) {
104        if (hours == 0) {
105            return ZERO;
106        }
107        return new Duration(FieldUtils.safeMultiply(hours, DateTimeConstants.MILLIS_PER_HOUR));
108    }
109
110    /**
111     * Create a duration with the specified number of minutes assuming that
112     * there are the standard number of milliseconds in a minute.
113     * <p>
114     * This method assumes that there are 60 seconds in a minute and
115     * 1000 milliseconds in a second.
116     * All currently supplied chronologies use this definition.
117     * <p>
118     * A Duration is a representation of an amount of time. If you want to express
119     * the concepts of 'minutes' you should consider using the {@link Minutes} class.
120     *
121     * @param minutes  the number of standard minutes in this duration
122     * @return the duration, never null
123     * @throws ArithmeticException if the minutes value is too large
124     * @since 1.6
125     */
126    public static Duration standardMinutes(long minutes) {
127        if (minutes == 0) {
128            return ZERO;
129        }
130        return new Duration(FieldUtils.safeMultiply(minutes, DateTimeConstants.MILLIS_PER_MINUTE));
131    }
132
133    /**
134     * Create a duration with the specified number of seconds assuming that
135     * there are the standard number of milliseconds in a second.
136     * <p>
137     * This method assumes that there are 1000 milliseconds in a second.
138     * All currently supplied chronologies use this definition.
139     * <p>
140     * A Duration is a representation of an amount of time. If you want to express
141     * the concepts of 'seconds' you should consider using the {@link Seconds} class.
142     *
143     * @param seconds  the number of standard seconds in this duration
144     * @return the duration, never null
145     * @throws ArithmeticException if the seconds value is too large
146     * @since 1.6
147     */
148    public static Duration standardSeconds(long seconds) {
149        if (seconds == 0) {
150            return ZERO;
151        }
152        return new Duration(FieldUtils.safeMultiply(seconds, DateTimeConstants.MILLIS_PER_SECOND));
153    }
154
155    /**
156     * Create a duration with the specified number of milliseconds.
157     *
158     * @param millis  the number of standard milliseconds in this duration
159     * @return the duration, never null
160     * @since 2.0
161     */
162    public static Duration millis(long millis) {
163        if (millis == 0) {
164            return ZERO;
165        }
166        return new Duration(millis);
167    }
168
169    //-----------------------------------------------------------------------
170    /**
171     * Creates a duration from the given millisecond duration.
172     *
173     * @param duration  the duration, in milliseconds
174     */
175    public Duration(long duration) {
176        super(duration);
177    }
178
179    /**
180     * Creates a duration from the given interval endpoints.
181     *
182     * @param startInstant  interval start, in milliseconds
183     * @param endInstant  interval end, in milliseconds
184     * @throws ArithmeticException if the duration exceeds a 64 bit long
185     */
186    public Duration(long startInstant, long endInstant) {
187        super(startInstant, endInstant);
188    }
189
190    /**
191     * Creates a duration from the given interval endpoints.
192     *
193     * @param start  interval start, null means now
194     * @param end  interval end, null means now
195     * @throws ArithmeticException if the duration exceeds a 64 bit long
196     */
197    public Duration(ReadableInstant start, ReadableInstant end) {
198        super(start, end);
199    }
200
201    /**
202     * Creates a duration from the specified object using the
203     * {@link org.joda.time.convert.ConverterManager ConverterManager}.
204     *
205     * @param duration  duration to convert
206     * @throws IllegalArgumentException if duration is invalid
207     */
208    public Duration(Object duration) {
209        super(duration);
210    }
211
212    //-----------------------------------------------------------------------
213    /**
214     * Gets the length of this duration in days assuming that there are the
215     * standard number of milliseconds in a day.
216     * <p>
217     * This method assumes that there are 24 hours in a day,
218     * 60 minutes in an hour, 60 seconds in a minute and 1000 milliseconds in
219     * a second. This will be true for most days, however days with Daylight
220     * Savings changes will not have 24 hours, so use this method with care.
221     * <p>
222     * This returns <code>getMillis() / MILLIS_PER_DAY</code>.
223     * The result is an integer division, thus excess milliseconds are truncated.
224     *
225     * @return the length of the duration in standard seconds
226     * @since 2.0
227     */
228    public long getStandardDays() {
229        return getMillis() / DateTimeConstants.MILLIS_PER_DAY;
230    }
231
232    /**
233     * Gets the length of this duration in hours assuming that there are the
234     * standard number of milliseconds in an hour.
235     * <p>
236     * This method assumes that there are 60 minutes in an hour,
237     * 60 seconds in a minute and 1000 milliseconds in a second.
238     * All currently supplied chronologies use this definition.
239     * <p>
240     * This returns <code>getMillis() / MILLIS_PER_HOUR</code>.
241     * The result is an integer division, thus excess milliseconds are truncated.
242     *
243     * @return the length of the duration in standard seconds
244     * @since 2.0
245     */
246    public long getStandardHours() {
247        return getMillis() / DateTimeConstants.MILLIS_PER_HOUR;
248    }
249
250    /**
251     * Gets the length of this duration in minutes assuming that there are the
252     * standard number of milliseconds in a minute.
253     * <p>
254     * This method assumes that there are 60 seconds in a minute and
255     * 1000 milliseconds in a second.
256     * All currently supplied chronologies use this definition.
257     * <p>
258     * This returns <code>getMillis() / 60000</code>.
259     * The result is an integer division, thus excess milliseconds are truncated.
260     *
261     * @return the length of the duration in standard seconds
262     * @since 2.0
263     */
264    public long getStandardMinutes() {
265        return getMillis() / DateTimeConstants.MILLIS_PER_MINUTE;
266    }
267
268    /**
269     * Gets the length of this duration in seconds assuming that there are the
270     * standard number of milliseconds in a second.
271     * <p>
272     * This method assumes that there are 1000 milliseconds in a second.
273     * All currently supplied chronologies use this definition.
274     * <p>
275     * This returns <code>getMillis() / 1000</code>.
276     * The result is an integer division, so 2999 millis returns 2 seconds.
277     *
278     * @return the length of the duration in standard seconds
279     * @since 1.6
280     */
281    public long getStandardSeconds() {
282        return getMillis() / DateTimeConstants.MILLIS_PER_SECOND;
283    }
284
285    //-----------------------------------------------------------------------
286    /**
287     * Get this duration as an immutable <code>Duration</code> object
288     * by returning <code>this</code>.
289     * 
290     * @return <code>this</code>
291     */
292    public Duration toDuration() {
293        return this;
294    }
295
296    /**
297     * Converts this duration to a period in days assuming that there are the
298     * standard number of milliseconds in a day.
299     * <p>
300     * This method assumes that there are 24 hours in a day,
301     * 60 minutes in an hour, 60 seconds in a minute and 1000 milliseconds in
302     * a second. This will be true for most days, however days with Daylight
303     * Savings changes will not have 24 hours, so use this method with care.
304     * 
305     * @return a period representing the number of standard days in this period, never null
306     * @throws ArithmeticException if the number of days is too large to be represented
307     * @since 2.0
308     */
309    public Days toStandardDays() {
310        long days = getStandardDays();
311        return Days.days(FieldUtils.safeToInt(days));
312    }
313
314    /**
315     * Converts this duration to a period in hours assuming that there are the
316     * standard number of milliseconds in an hour.
317     * <p>
318     * This method assumes that there are 60 minutes in an hour,
319     * 60 seconds in a minute and 1000 milliseconds in a second.
320     * All currently supplied chronologies use this definition.
321     * 
322     * @return a period representing the number of standard hours in this period, never null
323     * @throws ArithmeticException if the number of hours is too large to be represented
324     * @since 2.0
325     */
326    public Hours toStandardHours() {
327        long hours = getStandardHours();
328        return Hours.hours(FieldUtils.safeToInt(hours));
329    }
330
331    /**
332     * Converts this duration to a period in minutes assuming that there are the
333     * standard number of milliseconds in a minute.
334     * <p>
335     * This method assumes that there are 60 seconds in a minute and
336     * 1000 milliseconds in a second.
337     * All currently supplied chronologies use this definition.
338     * 
339     * @return a period representing the number of standard minutes in this period, never null
340     * @throws ArithmeticException if the number of minutes is too large to be represented
341     * @since 2.0
342     */
343    public Minutes toStandardMinutes() {
344        long minutes = getStandardMinutes();
345        return Minutes.minutes(FieldUtils.safeToInt(minutes));
346    }
347
348    /**
349     * Converts this duration to a period in seconds assuming that there are the
350     * standard number of milliseconds in a second.
351     * <p>
352     * This method assumes that there are 1000 milliseconds in a second.
353     * All currently supplied chronologies use this definition.
354     * 
355     * @return a period representing the number of standard seconds in this period, never null
356     * @throws ArithmeticException if the number of seconds is too large to be represented
357     * @since 1.6
358     */
359    public Seconds toStandardSeconds() {
360        long seconds = getStandardSeconds();
361        return Seconds.seconds(FieldUtils.safeToInt(seconds));
362    }
363
364    //-----------------------------------------------------------------------
365    /**
366     * Creates a new Duration instance with a different milisecond length.
367     * 
368     * @param duration  the new length of the duration
369     * @return the new duration instance
370     */
371    public Duration withMillis(long duration) {
372        if (duration == getMillis()) {
373            return this;
374        }
375        return new Duration(duration);
376    }
377
378    /**
379     * Returns a new duration with this length plus that specified multiplied by the scalar.
380     * This instance is immutable and is not altered.
381     * <p>
382     * If the addition is zero, this instance is returned.
383     * 
384     * @param durationToAdd  the duration to add to this one
385     * @param scalar  the amount of times to add, such as -1 to subtract once
386     * @return the new duration instance
387     */
388    public Duration withDurationAdded(long durationToAdd, int scalar) {
389        if (durationToAdd == 0 || scalar == 0) {
390            return this;
391        }
392        long add = FieldUtils.safeMultiply(durationToAdd, scalar);
393        long duration = FieldUtils.safeAdd(getMillis(), add);
394        return new Duration(duration);
395    }
396
397    /**
398     * Returns a new duration with this length plus that specified multiplied by the scalar.
399     * This instance is immutable and is not altered.
400     * <p>
401     * If the addition is zero, this instance is returned.
402     * 
403     * @param durationToAdd  the duration to add to this one, null means zero
404     * @param scalar  the amount of times to add, such as -1 to subtract once
405     * @return the new duration instance
406     */
407    public Duration withDurationAdded(ReadableDuration durationToAdd, int scalar) {
408        if (durationToAdd == null || scalar == 0) {
409            return this;
410        }
411        return withDurationAdded(durationToAdd.getMillis(), scalar);
412    }
413
414    //-----------------------------------------------------------------------
415    /**
416     * Returns a new duration with this length plus that specified.
417     * This instance is immutable and is not altered.
418     * <p>
419     * If the addition is zero, this instance is returned.
420     * 
421     * @param amount  the duration to add to this one
422     * @return the new duration instance
423     */
424    public Duration plus(long amount) {
425        return withDurationAdded(amount, 1);
426    }
427
428    /**
429     * Returns a new duration with this length plus that specified.
430     * This instance is immutable and is not altered.
431     * <p>
432     * If the amount is zero, this instance is returned.
433     * 
434     * @param amount  the duration to add to this one, null means zero
435     * @return the new duration instance
436     */
437    public Duration plus(ReadableDuration amount) {
438        if (amount == null) {
439            return this;
440        }
441        return withDurationAdded(amount.getMillis(), 1);
442    }
443
444    /**
445     * Returns a new duration with this length minus that specified.
446     * This instance is immutable and is not altered.
447     * <p>
448     * If the addition is zero, this instance is returned.
449     * 
450     * @param amount  the duration to take away from this one
451     * @return the new duration instance
452     */
453    public Duration minus(long amount) {
454        return withDurationAdded(amount, -1);
455    }
456
457    /**
458     * Returns a new duration with this length minus that specified.
459     * This instance is immutable and is not altered.
460     * <p>
461     * If the amount is zero, this instance is returned.
462     * 
463     * @param amount  the duration to take away from this one, null means zero
464     * @return the new duration instance
465     */
466    public Duration minus(ReadableDuration amount) {
467        if (amount == null) {
468            return this;
469        }
470        return withDurationAdded(amount.getMillis(), -1);
471    }
472
473}