⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 durationimpl.java

📁 JAVA的一些源码 JAVA2 STANDARD EDITION DEVELOPMENT KIT 5.0
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
            toBigInteger(buf[2], null == days),            toBigInteger(buf[3], null == hours),            toBigInteger(buf[4], null == minutes),            (buf[5].signum() == 0 && seconds == null) ? null : buf[5]);    }        /**     * <p>Gets the value of the field as a {@link BigDecimal}.</p>     *      * <p>If the field is unset, return 0.</p>     *      * @param f Field to get value for.     *      * @return  non-null valid {@link BigDecimal}.     */    private BigDecimal getFieldAsBigDecimal(DatatypeConstants.Field f) {        if (f == DatatypeConstants.SECONDS) {            if (seconds != null) {                return seconds;            } else {                return ZERO;            }        } else {            BigInteger bi = (BigInteger) getField(f);            if (bi == null) {                return ZERO;            } else {                return new BigDecimal(bi);            }        }    }        /**     * <p>BigInteger value of BigDecimal value.</p>     *      * @param value Value to convert.     * @param canBeNull Can returned value be null?     *      * @return BigInteger value of BigDecimal, possibly null.     */    private static BigInteger toBigInteger(        BigDecimal value,        boolean canBeNull) {        if (canBeNull && value.signum() == 0) {            return null;        } else {            return value.unscaledValue();        }    }        /**     * 1 unit of FIELDS[i] is equivalent to <code>FACTORS[i]</code> unit of     * FIELDS[i+1].     */    private static final BigDecimal[] FACTORS = new BigDecimal[]{        BigDecimal.valueOf(12),        null/*undefined*/,        BigDecimal.valueOf(24),        BigDecimal.valueOf(60),        BigDecimal.valueOf(60)    };            /**     * <p>Computes a new duration whose value is <code>this+rhs</code>.</p>     *      * <p>For example,</p>     * <pre>     * "1 day" + "-3 days" = "-2 days"     * "1 year" + "1 day" = "1 year and 1 day"     * "-(1 hour,50 minutes)" + "-20 minutes" = "-(1 hours,70 minutes)"     * "15 hours" + "-3 days" = "-(2 days,9 hours)"     * "1 year" + "-1 day" = IllegalStateException     * </pre>     *      * <p>Since there's no way to meaningfully subtract 1 day from 1 month,     * there are cases where the operation fails in     * {@link IllegalStateException}.</p>      *      * <p>     * Formally, the computation is defined as follows.</p>     * <p>     * Firstly, we can assume that two {@link Duration}s to be added     * are both positive without losing generality (i.e.,     * <code>(-X)+Y=Y-X</code>, <code>X+(-Y)=X-Y</code>,     * <code>(-X)+(-Y)=-(X+Y)</code>)     *      * <p>     * Addition of two positive {@link Duration}s are simply defined as       * field by field addition where missing fields are treated as 0.     * <p>     * A field of the resulting {@link Duration} will be unset if and     * only if respective fields of two input {@link Duration}s are unset.      * <p>     * Note that <code>lhs.add(rhs)</code> will be always successful if     * <code>lhs.signum()*rhs.signum()!=-1</code> or both of them are     * normalized.</p>     *      * @param rhs <code>Duration</code> to add to this <code>Duration</code>     *      * @return     *      non-null valid Duration object.     *      * @throws NullPointerException     *      If the rhs parameter is null.     * @throws IllegalStateException     *      If two durations cannot be meaningfully added. For     *      example, adding negative one day to one month causes     *      this exception.     *      *      * @see #subtract(Duration)     */    public Duration add(final Duration rhs) {        Duration lhs = this;        BigDecimal[] buf = new BigDecimal[6];                buf[0] = sanitize((BigInteger) lhs.getField(DatatypeConstants.YEARS),        	lhs.getSign()).add(sanitize((BigInteger) rhs.getField(DatatypeConstants.YEARS),  rhs.getSign()));        buf[1] = sanitize((BigInteger) lhs.getField(DatatypeConstants.MONTHS),        	lhs.getSign()).add(sanitize((BigInteger) rhs.getField(DatatypeConstants.MONTHS), rhs.getSign()));        buf[2] = sanitize((BigInteger) lhs.getField(DatatypeConstants.DAYS),        	lhs.getSign()).add(sanitize((BigInteger) rhs.getField(DatatypeConstants.DAYS),   rhs.getSign()));        buf[3] = sanitize((BigInteger) lhs.getField(DatatypeConstants.HOURS),        	lhs.getSign()).add(sanitize((BigInteger) rhs.getField(DatatypeConstants.HOURS),  rhs.getSign()));        buf[4] = sanitize((BigInteger) lhs.getField(DatatypeConstants.MINUTES),        	lhs.getSign()).add(sanitize((BigInteger) rhs.getField(DatatypeConstants.MINUTES), rhs.getSign()));        buf[5] = sanitize((BigDecimal) lhs.getField(DatatypeConstants.SECONDS),        	lhs.getSign()).add(sanitize((BigDecimal) rhs.getField(DatatypeConstants.SECONDS), rhs.getSign()));                // align sign        alignSigns(buf, 0, 2); // Y,M        alignSigns(buf, 2, 6); // D,h,m,s                // make sure that the sign bit is consistent across all 6 fields.        int s = 0;        for (int i = 0; i < 6; i++) {            if (s * buf[i].signum() < 0) {                throw new IllegalStateException();            }            if (s == 0) {                s = buf[i].signum();            }        }                return new DurationImpl(            s >= 0,            toBigInteger(sanitize(buf[0], s),            	lhs.getField(DatatypeConstants.YEARS) == null && rhs.getField(DatatypeConstants.YEARS) == null),            toBigInteger(sanitize(buf[1], s),            	lhs.getField(DatatypeConstants.MONTHS) == null && rhs.getField(DatatypeConstants.MONTHS) == null),            toBigInteger(sanitize(buf[2], s),            	lhs.getField(DatatypeConstants.DAYS) == null && rhs.getField(DatatypeConstants.DAYS) == null),            toBigInteger(sanitize(buf[3], s),            	lhs.getField(DatatypeConstants.HOURS) == null && rhs.getField(DatatypeConstants.HOURS) == null),            toBigInteger(sanitize(buf[4], s),            	lhs.getField(DatatypeConstants.MINUTES) == null && rhs.getField(DatatypeConstants.MINUTES) == null),             (buf[5].signum() == 0             && lhs.getField(DatatypeConstants.SECONDS) == null             && rhs.getField(DatatypeConstants.SECONDS) == null) ? null : sanitize(buf[5], s));    }        private static void alignSigns(BigDecimal[] buf, int start, int end) {        // align sign        boolean touched;                do { // repeat until all the sign bits become consistent            touched = false;            int s = 0; // sign of the left fields            for (int i = start; i < end; i++) {                if (s * buf[i].signum() < 0) {                    // this field has different sign than its left field.                    touched = true;                    // compute the number of unit that needs to be borrowed.                    BigDecimal borrow =                        buf[i].abs().divide(                            FACTORS[i - 1],                            BigDecimal.ROUND_UP);                    if (buf[i].signum() > 0) {                        borrow = borrow.negate();                    }                    // update values                    buf[i - 1] = buf[i - 1].subtract(borrow);                    buf[i] = buf[i].add(borrow.multiply(FACTORS[i - 1]));                }                if (buf[i].signum() != 0) {                    s = buf[i].signum();                }            }        } while (touched);    }        /**     * Compute <code>value*signum</code> where value==null is treated as     * value==0.     * @param value Value to sanitize.     * @param signum 0 to sanitize to 0, > 0 to sanitize to <code>value</code>, < 0 to sanitize to negative <code>value</code>.     *     * @return non-null {@link BigDecimal}.     */    private static BigDecimal sanitize(BigInteger value, int signum) {        if (signum == 0 || value == null) {            return ZERO;        }        if (signum > 0) {            return new BigDecimal(value);        }        return new BigDecimal(value.negate());    }            /**     * <p>Compute <code>value*signum</code> where <code>value==null</code> is treated as <code>value==0</code></p>.     *      * @param value Value to sanitize.     * @param signum 0 to sanitize to 0, > 0 to sanitize to <code>value</code>, < 0 to sanitize to negative <code>value</code>.     *      * @return non-null {@link BigDecimal}.     */    static BigDecimal sanitize(BigDecimal value, int signum) {        if (signum == 0 || value == null) {            return ZERO;        }        if (signum > 0) {            return value;        }        return value.negate();    }        /**     * <p>Computes a new duration whose value is <code>this-rhs</code>.</p>     *      * <p>For example:</p>     * <pre>     * "1 day" - "-3 days" = "4 days"     * "1 year" - "1 day" = IllegalStateException     * "-(1 hour,50 minutes)" - "-20 minutes" = "-(1hours,30 minutes)"     * "15 hours" - "-3 days" = "3 days and 15 hours"     * "1 year" - "-1 day" = "1 year and 1 day"     * </pre>     *      * <p>Since there's no way to meaningfully subtract 1 day from 1 month,     * there are cases where the operation fails in {@link IllegalStateException}.</p>      *      * <p>Formally the computation is defined as follows.     * First, we can assume that two {@link Duration}s are both positive     * without losing generality.  (i.e.,     * <code>(-X)-Y=-(X+Y)</code>, <code>X-(-Y)=X+Y</code>,     * <code>(-X)-(-Y)=-(X-Y)</code>)</p>     *       * <p>Then two durations are subtracted field by field.     * If the sign of any non-zero field <tt>F</tt> is different from     * the sign of the most significant field,     * 1 (if <tt>F</tt> is negative) or -1 (otherwise)     * will be borrowed from the next bigger unit of <tt>F</tt>.</p>     *      * <p>This process is repeated until all the non-zero fields have     * the same sign.</p>      *      * <p>If a borrow occurs in the days field (in other words, if     * the computation needs to borrow 1 or -1 month to compensate     * days), then the computation fails by throwing an     * {@link IllegalStateException}.</p>     *      * @param rhs <code>Duration</code> to substract from this <code>Duration</code>.     *       * @return New <code>Duration</code> created from subtracting <code>rhs</code> from this <code>Duration</code>.     *      * @throws IllegalStateException     *      If two durations cannot be meaningfully subtracted. For     *      example, subtracting one day from one month causes     *      this exception.     *      * @throws NullPointerException     *      If the rhs parameter is null.     *      * @see #add(Duration)     */    public Duration subtract(final Duration rhs) {        return add(rhs.negate());    }        /**     * Returns a new {@link Duration} object whose     * value is <code>-this</code>.     *      * <p>     * Since the {@link Duration} class is immutable, this method     * doesn't change the value of this object. It simply computes     * a new Duration object and returns it.     *      * @return     *      always return a non-null valid {@link Duration} object.     */    public Duration negate() {        return new DurationImpl(            signum <= 0,            years,            months,            days,            hours,            minutes,            seconds);    }        /**     * Returns the sign of this duration in -1,0, or 1.     *      * @return     *      -1 if this duration is negative, 0 if the duration is zero,     *      and 1 if the duration is postive.     */    public int signum() {        return signum;    }            /**     * Adds this duration to a {@link Calendar} object.     *      * <p>     * Calls {@link java.util.Calendar#add(int,int)} in the     * order of YEARS, MONTHS, DAYS, HOURS, MINUTES, SECONDS, and MILLISECONDS     * if those fields are present. Because the {@link Calendar} class     * uses int to hold values, there are cases where this method     * won't work correctly (for example if values of fields     * exceed the range of int.)      * </p>     *      * <p>     * Also, since this duration class is a Gregorian duration, this     * method will not work correctly if the given {@link Calendar}     * object is based on some other calendar systems.      * </p>     *      * <p>     * Any fractional parts of this {@link Duration} object     * beyond milliseconds will be simply ignored. For example, if     * this duration is "P1.23456S", then 1 is added to SECONDS,     * 234 is added to MILLISECONDS, and the rest will be unused.      * </p>     *      * <p>     * Note that because {@link Calendar#add(int, int)} is using     * <tt>int</tt>, {@link Duration} with values beyond the     * range of <tt>int</tt> in its fields     * will cause overflow/underflow to the given {@link Calendar}.     * {@link XMLGregorianCalendar#add(Duration)} provides the same     * basic operation as this method while avoiding     * the overflow/underflow issues.     *      * @param calendar     *      A calendar object whose value will be modified.     * @throws NullPointerException     *      if the calendar parameter is null.     */    public void addTo(Calendar calendar) {        calendar.add(Calendar.YEAR, getYears() * signum);        calendar.add(Calendar.MONTH, getMonths() * signum);        calendar.add(Calendar.DAY_OF_MONTH, getDays() * signum);        calendar.add(Calendar.HOUR, getHours() * signum);        calendar.add(Calendar.MINUTE, getMinutes() * signum);        calendar.add(Calendar.SECOND, getSeconds() * signum);        if (seconds != null) {            BigDecimal fraction =          

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -