📄 durationimpl.java
字号:
} /** * Obtains the value of the YEARS field as an integer value, * or 0 if not present. * * <p> * This method is a convenience method around the * {@link #getField(DatatypeConstants.Field)} method. * * <p> * Note that since this method returns <tt>int</tt>, this * method will return an incorrect value for {@link Duration}s * with the year field that goes beyond the range of <tt>int</tt>. * Use <code>getField(YEARS)</code> to avoid possible loss of precision.</p> * * @return * If the YEARS field is present, return * its value as an integer by using the {@link Number#intValue()} * method. If the YEARS field is not present, return 0. */ public int getYears() { return getInt(DatatypeConstants.YEARS); } /** * Obtains the value of the MONTHS field as an integer value, * or 0 if not present. * * This method works just like {@link #getYears()} except * that this method works on the MONTHS field. * * @return Months of this <code>Duration</code>. */ public int getMonths() { return getInt(DatatypeConstants.MONTHS); } /** * Obtains the value of the DAYS field as an integer value, * or 0 if not present. * * This method works just like {@link #getYears()} except * that this method works on the DAYS field. * * @return Days of this <code>Duration</code>. */ public int getDays() { return getInt(DatatypeConstants.DAYS); } /** * Obtains the value of the HOURS field as an integer value, * or 0 if not present. * * This method works just like {@link #getYears()} except * that this method works on the HOURS field. * * @return Hours of this <code>Duration</code>. * */ public int getHours() { return getInt(DatatypeConstants.HOURS); } /** * Obtains the value of the MINUTES field as an integer value, * or 0 if not present. * * This method works just like {@link #getYears()} except * that this method works on the MINUTES field. * * @return Minutes of this <code>Duration</code>. * */ public int getMinutes() { return getInt(DatatypeConstants.MINUTES); } /** * Obtains the value of the SECONDS field as an integer value, * or 0 if not present. * * This method works just like {@link #getYears()} except * that this method works on the SECONDS field. * * @return seconds in the integer value. The fraction of seconds * will be discarded (for example, if the actual value is 2.5, * this method returns 2) */ public int getSeconds() { return getInt(DatatypeConstants.SECONDS); } /** * <p>Return the requested field value as an int.</p> * * <p>If field is not set, i.e. == null, 0 is returned.</p> * * @param field To get value for. * * @return int value of field or 0 if field is not set. */ private int getInt(DatatypeConstants.Field field) { Number n = getField(field); if (n == null) { return 0; } else { return n.intValue(); } } /** * <p>Returns the length of the duration in milli-seconds.</p> * * <p>If the seconds field carries more digits than milli-second order, * those will be simply discarded (or in other words, rounded to zero.) * For example, for any Calendar value <code>x<code>,</p> * <pre> * <code>new Duration("PT10.00099S").getTimeInMills(x) == 10000</code>. * <code>new Duration("-PT10.00099S").getTimeInMills(x) == -10000</code>. * </pre> * * <p> * Note that this method uses the {@link #addTo(Calendar)} method, * which may work incorectly with {@link Duration} objects with * very large values in its fields. See the {@link #addTo(Calendar)} * method for details. * * @param startInstant * The length of a month/year varies. The <code>startInstant</code> is * used to disambiguate this variance. Specifically, this method * returns the difference between <code>startInstant</code> and * <code>startInstant+duration</code> * * @return milliseconds between <code>startInstant</code> and * <code>startInstant</code> plus this <code>Duration</code> * * @throws NullPointerException if <code>startInstant</code> parameter * is null. * */ public long getTimeInMillis(final Calendar startInstant) { Calendar cal = (Calendar) startInstant.clone(); addTo(cal); return getCalendarTimeInMillis(cal) - getCalendarTimeInMillis(startInstant); } /** * <p>Returns the length of the duration in milli-seconds.</p> * * <p>If the seconds field carries more digits than milli-second order, * those will be simply discarded (or in other words, rounded to zero.) * For example, for any <code>Date</code> value <code>x<code>,</p> * <pre> * <code>new Duration("PT10.00099S").getTimeInMills(x) == 10000</code>. * <code>new Duration("-PT10.00099S").getTimeInMills(x) == -10000</code>. * </pre> * * <p> * Note that this method uses the {@link #addTo(Date)} method, * which may work incorectly with {@link Duration} objects with * very large values in its fields. See the {@link #addTo(Date)} * method for details. * * @param startInstant * The length of a month/year varies. The <code>startInstant</code> is * used to disambiguate this variance. Specifically, this method * returns the difference between <code>startInstant</code> and * <code>startInstant+duration</code>. * * @throws NullPointerException * If the startInstant parameter is null. * * @return milliseconds between <code>startInstant</code> and * <code>startInstant</code> plus this <code>Duration</code> * * @see #getTimeInMillis(Calendar) */ public long getTimeInMillis(final Date startInstant) { Calendar cal = new GregorianCalendar(); cal.setTime(startInstant); this.addTo(cal); return getCalendarTimeInMillis(cal) - startInstant.getTime(); } // /**// * Returns an equivalent but "normalized" duration value.// * // * Intuitively, the normalization moves YEARS into// * MONTHS (by x12) and moves DAYS, HOURS, and MINUTES fields// * into SECONDS (by x86400, x3600, and x60 respectively.)// * // * // * Formally, this method satisfies the following conditions:// * <ul>// * <li>x.normalize().equals(x)// * <li>!x.normalize().isSet(Duration.YEARS)// * <li>!x.normalize().isSet(Duration.DAYS)// * <li>!x.normalize().isSet(Duration.HOURS)// * <li>!x.normalize().isSet(Duration.MINUTES)// * </ul>// * // * @return// * always return a non-null valid value. // */// public Duration normalize() {// return null;// } /** * <p>Converts the years and months fields into the days field * by using a specific time instant as the reference point.</p> * * <p>For example, duration of one month normalizes to 31 days * given the start time instance "July 8th 2003, 17:40:32".</p> * * <p>Formally, the computation is done as follows:</p> * <ol> * <li>The given Calendar object is cloned. * <li>The years, months and days fields will be added to * the {@link Calendar} object * by using the {@link Calendar#add(int,int)} method. * <li>The difference between two Calendars are computed in terms of days. * <li>The computed days, along with the hours, minutes and seconds * fields of this duration object is used to construct a new * Duration object. * </ol> * * <p>Note that since the Calendar class uses <code>int</code> to * hold the value of year and month, this method may produce * an unexpected result if this duration object holds * a very large value in the years or months fields.</p> * * @param startTimeInstant <code>Calendar</code> reference point. * * @return <code>Duration</code> of years and months of this <code>Duration</code> as days. * * @throws NullPointerException If the startTimeInstant parameter is null. */ public Duration normalizeWith(Calendar startTimeInstant) { Calendar c = (Calendar) startTimeInstant.clone(); // using int may cause overflow, but // Calendar internally treats value as int anyways. c.add(Calendar.YEAR, getYears() * signum); c.add(Calendar.MONTH, getMonths() * signum); c.add(Calendar.DAY_OF_MONTH, getDays() * signum); // obtain the difference in terms of days long diff = getCalendarTimeInMillis(c) - getCalendarTimeInMillis(startTimeInstant); int days = (int) (diff / (1000L * 60L * 60L * 24L)); return new DurationImpl( days >= 0, null, null, wrap(Math.abs(days)), (BigInteger) getField(DatatypeConstants.HOURS), (BigInteger) getField(DatatypeConstants.MINUTES), (BigDecimal) getField(DatatypeConstants.SECONDS)); } /** * <p>Computes a new duration whose value is <code>factor</code> times * longer than the value of this duration.</p> * * <p>This method is provided for the convenience. * It is functionally equivalent to the following code:</p> * <pre> * multiply(new BigDecimal(String.valueOf(factor))) * </pre> * * @param factor Factor times longer of new <code>Duration</code> to create. * * @return New <code>Duration</code> that is <code>factor</code>times longer than this <code>Duration</code>. * * @see #multiply(BigDecimal) */ public Duration multiply(int factor) { return multiply(BigDecimal.valueOf(factor)); } /** * Computes a new duration whose value is <code>factor</code> times * longer than the value of this duration. * * <p> * For example, * <pre> * "P1M" (1 month) * "12" = "P12M" (12 months) * "PT1M" (1 min) * "0.3" = "PT18S" (18 seconds) * "P1M" (1 month) * "1.5" = IllegalStateException * </pre> * * <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. * * <p> * The operation will be performed field by field with the precision * of {@link BigDecimal}. Since all the fields except seconds are * restricted to hold integers, * any fraction produced by the computation will be * carried down toward the next lower unit. For example, * if you multiply "P1D" (1 day) with "0.5", then it will be 0.5 day, * which will be carried down to "PT12H" (12 hours). * When fractions of month cannot be meaningfully carried down * to days, or year to months, this will cause an * {@link IllegalStateException} to be thrown. * For example if you multiple one month by 0.5.</p> * * <p> * To avoid {@link IllegalStateException}, use * the {@link #normalizeWith(Calendar)} method to remove the years * and months fields. * * @param factor to multiply by * * @return * returns a non-null valid {@link Duration} object * * @throws IllegalStateException if operation produces fraction in * the months field. * * @throws NullPointerException if the <code>factor</code> parameter is * <code>null</code>. * */ public Duration multiply(BigDecimal factor) { BigDecimal carry = ZERO; int factorSign = factor.signum(); factor = factor.abs(); BigDecimal[] buf = new BigDecimal[6]; for (int i = 0; i < 5; i++) { BigDecimal bd = getFieldAsBigDecimal(FIELDS[i]); bd = bd.multiply(factor).add(carry); buf[i] = bd.setScale(0, BigDecimal.ROUND_DOWN); bd = bd.subtract(buf[i]); if (i == 1) { if (bd.signum() != 0) { throw new IllegalStateException(); // illegal carry-down } else { carry = ZERO; } } else { carry = bd.multiply(FACTORS[i]); } } if (seconds != null) { buf[5] = seconds.multiply(factor).add(carry); } else { buf[5] = carry; } return new DurationImpl( this.signum * factorSign >= 0, toBigInteger(buf[0], null == years), toBigInteger(buf[1], null == months),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -