Spec-Zone .ru
спецификации, руководства, описания, API
001/*
002 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.  Oracle designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Oracle in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
022 * or visit www.oracle.com if you need additional information or have any
023 * questions.
024 */
025
026package javafx.util;
027
028import java.io.Serializable;
029
030/**
031 * <p>
032 *     A class that defines a duration of time. Duration instances are immutable,
033 *     and are therefore replaced rather than modified, similar to {@link java.math.BigDecimal}.
034 *     Duration's can be created using the constructor, or one of the static construction
035 *     methods such as {@link #seconds} or {@link #minutes}.
036 * </p>
037 */
038public class Duration implements Comparable<Duration>, Serializable {
039    /**
040     * A Duration of 0 (no time).
041     */
042    public static final Duration ZERO = new Duration(0);
043
044    /**
045     * A Duration of 1 millisecond.
046     */
047    public static final Duration ONE = new Duration(1);
048
049    /**
050     * An Infinite Duration.
051     */
052    public static final Duration INDEFINITE = new Duration(Double.POSITIVE_INFINITY);
053
054    /**
055     * A Duration of some unknown amount of time.
056     */
057    public static final Duration UNKNOWN = new Duration(Double.NaN);
058
059    /**
060     * Factory method that returns a Duration instance for a specified
061     * amount of time. The syntax is "[number][ms|s|m|h]".
062     *
063     * @param time A non-null string properly formatted. Leading or trailing
064     * spaces will not parse correctly. Throws a NullPointerException if
065     * time is null.
066     * @return a Duration which is represented by the <code>time</code>
067     */
068    public static Duration valueOf(String time) {
069        int index = -1;
070        for (int i=0; i<time.length(); i++) {
071            char c = time.charAt(i);
072            if (!Character.isDigit(c) && c != '.' && c != '-') {
073                index = i;
074                break;
075            }
076        }
077
078        if (index == -1) {
079            // Never found the suffix!
080            throw new IllegalArgumentException("The time parameter must have a suffix of [ms|s|m|h]");
081        }
082
083        double value = Double.parseDouble(time.substring(0, index));
084        String suffix = time.substring(index);
085        if ("ms".equals(suffix)) {
086            return millis(value);
087        } else if ("s".equals(suffix)) {
088            return seconds(value);
089        } else if ("m".equals(suffix)) {
090            return minutes(value);
091        } else if ("h".equals(suffix)) {
092            return hours(value);
093        } else {
094            // Malformed suffix
095            throw new IllegalArgumentException("The time parameter must have a suffix of [ms|s|m|h]");
096        }
097    }
098
099    /**
100     * Factory method that returns a Duration instance for a specified
101     * number of milliseconds.
102     *
103     * @param ms the number of milliseconds
104     * @return a Duration instance of the specified number of milliseconds
105     */
106    public static Duration millis(double ms) {
107        if (ms == 0) {
108            return ZERO;
109        } else if (ms == 1) {
110            return ONE;
111        } else if (ms == Double.POSITIVE_INFINITY) {
112            return INDEFINITE;
113        } else if (Double.isNaN(ms)) {
114            return UNKNOWN;
115        } else {
116            return new Duration(ms);
117        }
118    }
119
120    /**
121     * Factory method that returns a Duration instance representing the specified
122     * number of seconds.
123     *
124     * @param s the number of seconds
125     * @return a Duration instance of the specified number of seconds
126     */
127    public static Duration seconds(double s) {
128        if (s == 0) {
129            return ZERO;
130        } else if (s == Double.POSITIVE_INFINITY) {
131            return INDEFINITE;
132        } else if (Double.isNaN(s)) {
133            return UNKNOWN;
134        } else {
135            return new Duration(s * 1000.0);
136        }
137    }
138
139    /**
140     * Factory method that returns a Duration instance representing the specified
141     * number of minutes.
142     *
143     * @param m the number of minutes
144     * @return a Duration instance of the specified number of minutes
145     */
146    public static Duration minutes(double m) {
147        if (m == 0) {
148            return ZERO;
149        } else if (m == Double.POSITIVE_INFINITY) {
150            return INDEFINITE;
151        } else if (Double.isNaN(m)) {
152            return UNKNOWN;
153        } else {
154            return new Duration(m * (1000.0 * 60.0));
155        }
156    }
157
158    /**
159     * Factory method that returns a Duration instance representing the specified
160     * number of hours.
161     *
162     * @param h the number of hours
163     * @return a Duration instance representing the specified number of hours
164     */
165    public static Duration hours(double h) {
166        if (h == 0) {
167            return ZERO;
168        } else if (h == Double.POSITIVE_INFINITY) {
169            return INDEFINITE;
170        } else if (Double.isNaN(h)) {
171            return UNKNOWN;
172        } else {
173            return new Duration(h * (1000.0 * 60.0 * 60.0));
174        }
175    }
176
177    /**
178     * The value of this duration, in fractional milliseconds
179     */
180    private final double millis;
181
182    /**
183     * Creates a new Duration with potentially fractional millisecond resolution.
184     * @param millis The number of milliseconds
185     */
186    public Duration(double millis) {
187        this.millis = millis;
188    }
189
190    /**
191     * Returns the number of milliseconds in this period or Double.POSITIVE_INFINITY
192     * if the period is INDEFINITE or NaN if the period is UNKNOWN.
193     * @return the Duration in fractional milliseconds
194     */
195    public double toMillis() {
196        return millis;
197    }
198
199    /**
200     * Returns the number of seconds in this period or Double.POSITIVE_INFINITY
201     * if the period is INDEFINITE or NaN if the period is UNKNOWN.
202     * @return the Duration in fractional seconds
203     */
204    public double toSeconds() {
205        return millis / 1000.0;
206    }
207
208    /**
209     * Returns the number of minutes in this period or Double.POSITIVE_INFINITY
210     * if the period is INDEFINITE or NaN if the period is UNKNOWN.
211     * @return the Duration in fractional minutes
212     */
213    public double toMinutes() {
214        return millis / (60 * 1000.0);
215    }
216
217    /**
218     * Returns the number of hours in this period or Double.POSITIVE_INFINITY
219     * if the period is INDEFINITE or NaN if the period is UNKNOWN.
220     * @return the Duration in fractional hours
221     */
222    public double toHours() {
223        return millis / (60 * 60 * 1000.0);
224    }
225
226    /**
227     * Add this instance and another Duration instance to return a new Duration instance.
228     * If either instance is INDEFINITE, return INDEFINITE.
229     * If either instance is UNKNOWN, return UNKNOWN.
230     * This method does not change the value of the called Duration instance.
231     *
232     * @param other must not be null
233     * @return the result of adding this duration to the other duration. This is
234     *         the same as millis + other.millis using double arithmetic
235     */
236    public Duration add(Duration other) {
237        // Note that several of these functions assume that the value of millis in INDEFINITE
238        // is Double.POSITIVE_INFINITY.
239        return millis(millis + other.millis);
240    }
241
242    /**
243     * Subtract other Duration instance from this instance to return a new Duration instance.
244     * If either instance is UNKNOWN, return UNKNOWN.
245     * Otherwise, if either instance is INDEFINITE, return INDEFINITE.
246     * This method does not change the value of the called Duration instance.
247     *
248     * @param other must not be null
249     * @return the result of subtracting the other duration from this duration. This is
250     *         the same as millis - other.millis using double arithmetic
251     */
252    public Duration subtract(Duration other) {
253        return millis(millis - other.millis);
254    }
255
256    /**
257     * Multiply this instance with a number to return a new Duration instance.
258     * If either instance is INDEFINITE, return INDEFINITE.
259     * If either Duration instance is UNKNOWN, return UNKNOWN.
260     * This method does not change the value of the called Duration instance.
261     *
262     * @deprecated This method produces surprising results by not taking units into
263     *             account. Use {@link #multiply(double)} instead.
264     * @param other must not be null
265     * @return the result of multiplying this duration with the other duration. This is
266     *         the same as millis * other.millis using double arithmetic
267     */
268    @Deprecated
269    public Duration multiply(Duration other) {
270        return millis(millis * other.millis);
271    }
272
273    /**
274     * Multiply this instance with a number representing millis and return a new Duration.
275     * If the called Duration instance is INDEFINITE, return INDEFINITE.
276     * If the called Duration instance is UNKNOWN, return UNKNOWN.
277     * This method does not change the value of the called Duration instance.
278     *
279     * @param n the amount to multiply by in fractional milliseconds
280     * @return the result of multiplying this duration with n. This is
281     *         the same as millis * n using double arithmetic
282     */
283    public Duration multiply(double n) {
284        return millis(millis * n);
285    }
286
287    /**
288     * Divide this instance by a number to return a new Duration instance.
289     * If the called Duration instance is INDEFINITE, return INDEFINITE.
290     * If the called Duration instance is UNKNOWN, return UNKNOWN.
291     * This method does not change the value of the called Duration instance.
292     *
293     * @param n the amount to divide by in fractional milliseconds
294     * @return the result of dividing this duration with n. This is
295     *         the same as millis / n using double arithmetic
296     */
297    public Duration divide(double n) {
298        return millis(millis / n);
299    }
300
301    /**
302     * Divide this instance by another Duration to return the ratio.
303     * If both instances are INDEFINITE, return NaN.
304     * If this instance is INDEFINITE, return POSITIVE_INFINITY
305     * If the other instance is INDEFINITE, return 0.0.
306     * This function does not change the value of the called Duration instance.
307     *
308     * @deprecated This method produces surprising results by not taking units into
309     *             account. Use {@link #divide(double)} instead.
310     * @param other must not be null
311     * @return the result of dividing this duration by the other duration. This is
312     *         the same as millis / other.millis using double arithmetic
313     */
314    @Deprecated
315    public Duration divide(Duration other) {
316        return millis(millis / other.millis);
317    }
318
319    /**
320     * Return a new Duration instance which has a negative number of milliseconds
321     * from this instance.  For example, <code>Duration.millis(50).negate()</code> returns
322     * a Duration of -50 milliseconds.
323     * If the called Duration instance is INDEFINITE, return INDEFINITE.
324     * This function does not change the value of the called Duration instance.
325     *
326     * @return the result of negating this duration. This is
327     *         the same as -millis using double arithmetic
328     */
329    public Duration negate() {
330        return millis(-millis);
331    }
332
333    /**
334     * Gets whether this Duration instance is Indefinite. A Duration is Indefinite
335     * if it equals Duration.INDEFINITE.
336     * @return true if this Duration is equivalent to Duration.INDEFINITE or Double.POSITIVE_INFINITY.
337     */
338    public boolean isIndefinite() {
339        return millis == Double.POSITIVE_INFINITY;
340    }
341
342    /**
343     * Gets whether this Duration instance is Unknown. A Duration is Unknown
344     * if it equals Duration.UNKNOWN.
345     * @return true if this Duration is equivalent to Duration.UNKNOWN or Double.isNaN(millis)
346     */
347    public boolean isUnknown() {
348        return Double.isNaN(millis);
349    }
350
351    /**
352     * Returns true if the specified duration is less than (&lt;) this instance.
353     * INDEFINITE is treated as if it were positive infinity.
354     *
355     * @param other cannot be null
356     * @return true if millis < other.millis using double arithmetic
357     */
358    public boolean lessThan(Duration other) {
359        return millis < other.millis;
360    }
361
362    /**
363     * Returns true if the specified duration is less than or equal to (&lt;=) this instance.
364     * INDEFINITE is treated as if it were positive infinity.
365     *
366     * @param other cannot be null
367     * @return true if millis <= other.millis using double arithmetic
368     */
369    public boolean lessThanOrEqualTo(Duration other) {
370        return millis <= other.millis;
371    }
372
373    /**
374     * Returns true if the specified duration is greater than (&gt;) this instance.
375     * INDEFINITE is treated as if it were positive infinity.
376     *
377     * @param other cannot be null
378     * @return true if millis > other.millis using double arithmetic
379     */
380    public boolean greaterThan(Duration other) {
381        return millis > other.millis;
382    }
383
384    /**
385     * Returns true if the specified duration is greater than or equal to (&gt;=) this instance.
386     * INDEFINITE is treated as if it were positive infinity.
387     *
388     * @param other cannot be null
389     * @return true if millis >= other.millis using double arithmetic
390     */
391    public boolean greaterThanOrEqualTo(Duration other) {
392        return millis >= other.millis;
393    }
394
395    /**
396     * Returns a string representation of this {@code Duration} object.
397     * @return a string representation of this {@code Duration} object.
398     */ 
399    @Override public String toString() {
400        return isIndefinite() ? "INDEFINITE" : (isUnknown() ? "UNKNOWN" : millis + " ms");
401    }
402
403    /**
404     * Compares durations represented by this object and the specified object. 
405     * Returns a negative integer, zero, or a positive integer as this duration 
406     * is less than, equal to, or greater than the specified duration.
407     * @param d the duration to be compared.
408     * @return a negative integer, zero, or a positive integer as this duration 
409     * is less than, equal to, or greater than the specified duration.
410     */
411    @Override public int compareTo(Duration d) {
412        // Reuse the Double.compare implementation
413        return Double.compare(millis, d.millis);
414    }
415
416    /**
417     * Indicates whether some other object is "equal to" this one.
418     * @param obj the reference object with which to compare.
419     * @return {@code true} if this object is equal to the {@code obj} argument; {@code false} otherwise.
420     */
421    @Override public boolean equals(Object obj) {
422        // Rely on Java's handling of double == double
423        return obj == this || obj instanceof Duration && millis == ((Duration) obj).millis;
424    }
425
426    /**
427     * Returns a hash code for this {@code Duration} object.
428     * @return a hash code for this {@code Duration} object.
429     */ 
430    @Override public int hashCode() {
431        // Uses the same implementation as Double.hashCode
432        long bits = Double.doubleToLongBits(millis);
433        return (int)(bits ^ (bits >>> 32));
434    }
435}