📄 durationimpl.java
字号:
// $Id: DurationImpl.java,v 1.8 2004/06/25 10:09:34 nb131165 Exp $/* * @(#)DurationImpl.java 1.6 04/07/26 * * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package com.sun.org.apache.xerces.internal.jaxp.datatype;import java.io.IOException;import java.io.ObjectStreamException;import java.io.Serializable;import java.math.BigDecimal;import java.math.BigInteger;import java.util.Calendar;import java.util.Date;import java.util.GregorianCalendar;import javax.xml.datatype.DatatypeConstants;import javax.xml.datatype.Duration;import javax.xml.datatype.XMLGregorianCalendar;import javax.xml.namespace.QName;import com.sun.org.apache.xerces.internal.util.DatatypeMessageFormatter;/** * <p>Immutable representation of a time span as defined in * the W3C XML Schema 1.0 specification.</p> * * <p>A Duration object represents a period of Gregorian time, * which consists of six fields (years, months, days, hours, * minutes, and seconds) plus a sign (+/-) field.</p> * * <p>The first five fields have non-negative (>=0) integers or null * (which represents that the field is not set), * and the seconds field has a non-negative decimal or null. * A negative sign indicates a negative duration.</p> * * <p>This class provides a number of methods that make it easy * to use for the duration datatype of XML Schema 1.0 with * the errata.</p> * * <h2>Order relationship</h2> * <p>Duration objects only have partial order, where two values A and B * maybe either:</p> * <ol> * <li>A<B (A is shorter than B) * <li>A>B (A is longer than B) * <li>A==B (A and B are of the same duration) * <li>A<>B (Comparison between A and B is indeterminate) * </ol> * <p>For example, 30 days cannot be meaningfully compared to one month. * The {@link #compare(Duration)} method implements this * relationship.</p> * * <p>See the {@link #isLongerThan(Duration)} method for details about * the order relationship among {@link Duration} objects.</p> * * * * <h2>Operations over Duration</h2> * <p>This class provides a set of basic arithmetic operations, such * as addition, subtraction and multiplication. * Because durations don't have total order, an operation could * fail for some combinations of operations. For example, you cannot * subtract 15 days from 1 month. See the javadoc of those methods * for detailed conditions where this could happen.</p> * * <p>Also, division of a duration by a number is not provided because * the {@link Duration} class can only deal with finite precision * decimal numbers. For example, one cannot represent 1 sec divided by 3.</p> * * <p>However, you could substitute a division by 3 with multiplying * by numbers such as 0.3 or 0.333.</p> * * * * <h2>Range of allowed values</h2> * <p> * Because some operations of {@link Duration} rely on {@link Calendar} * even though {@link Duration} can hold very large or very small values, * some of the methods may not work correctly on such {@link Duration}s. * The impacted methods document their dependency on {@link Calendar}. * * * @author <a href="mailto:Kohsuke.Kawaguchi@Sun.com">Kohsuke Kawaguchi</a> * @author <a href="mailto:Joseph.Fialli@Sun.com">Joseph Fialli</a> * @version $Revision: 1.8 $, $Date: 2004/06/25 10:09:34 $ * @see XMLGregorianCalendar#add(Duration) * @since 1.5 */public class DurationImpl extends Duration implements Serializable { /** * <p>Number of Fields.</p> */ private static final int FIELD_NUM = 6; /** * <p>Internal array of value Fields.</p> */ private static final DatatypeConstants.Field[] FIELDS = new DatatypeConstants.Field[]{ DatatypeConstants.YEARS, DatatypeConstants.MONTHS, DatatypeConstants.DAYS, DatatypeConstants.HOURS, DatatypeConstants.MINUTES, DatatypeConstants.SECONDS }; /** * <p>Internal array of value Field ids.</p> */ private static final int[] FIELD_IDS = { DatatypeConstants.YEARS.getId(), DatatypeConstants.MONTHS.getId(), DatatypeConstants.DAYS.getId(), DatatypeConstants.HOURS.getId(), DatatypeConstants.MINUTES.getId(), DatatypeConstants.SECONDS.getId() }; /** * <p>BigDecimal value of 0.</p> */ private static final BigDecimal ZERO = BigDecimal.valueOf((long) 0); /** * <p>Indicates the sign. -1, 0 or 1 if the duration is negative, * zero, or positive.</p> */ private final int signum; /** * <p>Years of this <code>Duration</code>.</p> */ private final BigInteger years; /** * <p>Months of this <code>Duration</code>.</p> */ private final BigInteger months; /** * <p>Days of this <code>Duration</code>.</p> */ private final BigInteger days; /** * <p>Hours of this <code>Duration</code>.</p> */ private final BigInteger hours; /** * <p>Minutes of this <code>Duration</code>.</p> */ private final BigInteger minutes; /** * <p>Seconds of this <code>Duration</code>.</p> */ private final BigDecimal 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 getSign() { return signum; } /** * TODO: Javadoc * @param isPositive Sign. * * @return 1 if positive, else -1. */ private int calcSignum(boolean isPositive) { if ((years == null || years.signum() == 0) && (months == null || months.signum() == 0) && (days == null || days.signum() == 0) && (hours == null || hours.signum() == 0) && (minutes == null || minutes.signum() == 0) && (seconds == null || seconds.signum() == 0)) { return 0; } if (isPositive) { return 1; } else { return -1; } } /** * <p>Constructs a new Duration object by specifying each field individually.</p> * * <p>All the parameters are optional as long as at least one field is present. * If specified, parameters have to be zero or positive.</p> * * @param isPositive Set to <code>false</code> to create a negative duration. When the length * of the duration is zero, this parameter will be ignored. * @param years of this <code>Duration</code> * @param months of this <code>Duration</code> * @param days of this <code>Duration</code> * @param hours of this <code>Duration</code> * @param minutes of this <code>Duration</code> * @param seconds of this <code>Duration</code> * * @throws IllegalArgumentException * If years, months, days, hours, minutes and * seconds parameters are all <code>null</code>. Or if any * of those parameters are negative. */ protected DurationImpl( boolean isPositive, BigInteger years, BigInteger months, BigInteger days, BigInteger hours, BigInteger minutes, BigDecimal seconds) { this.years = years; this.months = months; this.days = days; this.hours = hours; this.minutes = minutes; this.seconds = seconds; this.signum = calcSignum(isPositive); // sanity check if (years == null && months == null && days == null && hours == null && minutes == null && seconds == null) { throw new IllegalArgumentException( //"all the fields are null" DatatypeMessageFormatter.formatMessage(null, "AllFieldsNull", null) ); } testNonNegative(years, DatatypeConstants.YEARS); testNonNegative(months, DatatypeConstants.MONTHS); testNonNegative(days, DatatypeConstants.DAYS); testNonNegative(hours, DatatypeConstants.HOURS); testNonNegative(minutes, DatatypeConstants.MINUTES); testNonNegative(seconds, DatatypeConstants.SECONDS); } /** * <p>Makes sure that the given number is non-negative. If it is not, * throw {@link IllegalArgumentException}.</p> * * @param n Number to test. * @param f Field to test. */ private static void testNonNegative(BigInteger n, DatatypeConstants.Field f) { if (n != null && n.signum() < 0) { throw new IllegalArgumentException( DatatypeMessageFormatter.formatMessage(null, "NegativeField", new Object[]{f.toString()}) ); } } /** * <p>Makes sure that the given number is non-negative. If it is not, * throw {@link IllegalArgumentException}.</p> * * @param n Number to test. * @param f Field to test. */ private static void testNonNegative(BigDecimal n, DatatypeConstants.Field f) { if (n != null && n.signum() < 0) { throw new IllegalArgumentException( DatatypeMessageFormatter.formatMessage(null, "NegativeField", new Object[]{f.toString()}) ); } } /** * <p>Constructs a new Duration object by specifying each field * individually.</p> * * <p>This method is functionally equivalent to * invoking another constructor by wrapping * all non-zero parameters into {@link BigInteger} and {@link BigDecimal}. * Zero value of int parameter is equivalent of null value of * the corresponding field.</p> * * @see #DurationImpl(boolean, BigInteger, BigInteger, BigInteger, BigInteger, * BigInteger, BigDecimal) */ protected DurationImpl( final boolean isPositive, final int years, final int months, final int days, final int hours, final int minutes, final int seconds) { this( isPositive, wrap(years), wrap(months), wrap(days), wrap(hours), wrap(minutes), seconds != 0 ? new BigDecimal(String.valueOf(seconds)) : null); } /** * TODO: Javadoc * * @param i int to convert to BigInteger. * * @return BigInteger representation of int. */ private static BigInteger wrap(final int i) { // field may not be set if (i == DatatypeConstants.FIELD_UNDEFINED) { return null; } // int -> BigInteger return new BigInteger(String.valueOf(i)); } /** * <p>Constructs a new Duration object by specifying the duration * in milliseconds.</p> * * <p>The DAYS, HOURS, MINUTES and SECONDS fields are used to * represent the specifed duration in a reasonable way. * That is, the constructed object <code>x</code> satisfies * the following conditions:</p> * <ul> * <li>x.getHours()<24 * <li>x.getMinutes()<60 * <li>x.getSeconds()<60 * </ul> * * @param durationInMilliSeconds * The length of the duration in milliseconds. */ protected DurationImpl(final long durationInMilliSeconds) { boolean is0x8000000000000000L = false; long l = durationInMilliSeconds; if (l > 0) { signum = 1; } else if (l < 0) { signum = -1; if (l == 0x8000000000000000L) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -