All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.xmlbeans.GDuration Maven / Gradle / Ivy

There is a newer version: 5.0.22
Show newest version
/*   Copyright 2004 The Apache Software Foundation
 *
 *   Licensed under the Apache License, Version 2.0 (the "License");
 *   you may not use this file except in compliance with the License.
 *   You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *   See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.xmlbeans;

import java.math.BigDecimal;

/**
 * Represents an XML Schema-compatible duration.
 * 

* A duration is made up of a number of years, months, days, hours, * minutes, seconds, and fractions of seconds. See the * XML Schema specification * section on xs:duration * for details on the rules for * comparing durations and * adding durations to dates. */ public final class GDuration implements GDurationSpecification, java.io.Serializable { private static final long serialVersionUID = 1L; private int _sign; private int _CY; private int _M; private int _D; private int _h; private int _m; private int _s; private BigDecimal _fs; /** * Constructs an empty GDuration representing zero seconds. */ public GDuration() { _sign = +1; _fs = GDate._zero; } private static final int SEEN_NOTHING = 0; private static final int SEEN_YEAR = 1; private static final int SEEN_MONTH = 2; private static final int SEEN_DAY = 3; private static final int SEEN_HOUR = 4; private static final int SEEN_MINUTE = 5; private static final int SEEN_SECOND = 6; /** * Constructs a GDuration from a lexical * representation. The lexical space contains the * union of the lexical spaces of all the schema * date/time types (except for duration). */ public GDuration(CharSequence str) { // Form: -PnYnMnDTnHnMnS // (where each n may be unsigned integer, i.e., an integer that conforms to the pattern [0-9]+ // {was: preceded by a - for us}, and the whole may be -) // first trim XML whitespace int len = str.length(); int start = 0; while (len > 0 && GDate.isSpace(str.charAt(len - 1))) len -= 1; while (start < len && GDate.isSpace(str.charAt(start))) start += 1; _sign = 1; boolean tmark = false; if (start < len && str.charAt(start) == '-') { _sign = -1; start += 1; } if (start >= len || str.charAt(start) != 'P') throw new IllegalArgumentException("duration must begin with P"); start += 1; int seen = SEEN_NOTHING; _fs = GDate._zero; for (;start < len; start += 1) { char ch = str.charAt(start); if (ch == 'T') { if (tmark) throw new IllegalArgumentException("duration must have no more than one T'"); if (seen > SEEN_DAY) throw new IllegalArgumentException("T in duration must precede time fields"); seen = SEEN_DAY; tmark = true; start += 1; if (start >= len) throw new IllegalArgumentException("illegal duration"); ch = str.charAt(start); } if (!GDate.isDigit(ch)) throw new IllegalArgumentException("illegal duration at char[" + start + "]: '" + ch + "'"); int value = GDate.digitVal(ch); for (;;) { start += 1; ch = (start < len) ? str.charAt(start) : '\0'; if (!GDate.isDigit(ch)) break; value = value * 10 + GDate.digitVal(ch); } if (ch == '.') { int i = start; do i += 1; while (i < len && GDate.isDigit(ch = str.charAt(i))); _fs = new BigDecimal(str.subSequence(start, i).toString()); if (i >= len || ch != 'S') throw new IllegalArgumentException("illegal duration"); start = i; } switch (seen) { case SEEN_NOTHING: if (ch == 'Y') { seen = SEEN_YEAR; _CY = value; break; } // fallthrough case SEEN_YEAR: if (ch == 'M') { seen = SEEN_MONTH; _M = value; break; } // fallthrough case SEEN_MONTH: if (ch == 'D') { seen = SEEN_DAY; _D = value; break; } // fallthrough case SEEN_DAY: if (ch == 'H') { if (!tmark) throw new IllegalArgumentException("time in duration must follow T"); seen = SEEN_HOUR; _h = value; break; } // fallthrough case SEEN_HOUR: if (ch == 'M') { if (!tmark) throw new IllegalArgumentException("time in duration must follow T"); seen = SEEN_MINUTE; _m = value; break; } // fallthrough case SEEN_MINUTE: if (ch == 'S') { if (!tmark) throw new IllegalArgumentException("time in duration must follow T"); seen = SEEN_SECOND; _s = value; break; } // fallthrough default: throw new IllegalArgumentException("duration must specify Y M D T H M S in order"); } } if ( seen == SEEN_NOTHING ) throw new IllegalArgumentException("duration must contain at least one number and its designator: " + str); } /** * Constructs a GDuration with the specified sign, * year, month, day, hours, minutes, seconds, and optional * fractional seconds. * @param sign +1 for a positive duration, -1 for a negative duration * @throws java.lang.IllegalArgumentException if the sign is not 1 or -1 */ public GDuration( int sign, int year, int month, int day, int hour, int minute, int second, BigDecimal fraction) { if (sign != 1 && sign != -1) throw new IllegalArgumentException(); _sign = sign; _CY = year; _M = month; _D = day; _h = hour; _m = minute; _s = second; _fs = fraction == null ? GDate._zero : fraction; } /** * Constructs a GDuration from another GDurationSpecification. */ public GDuration(GDurationSpecification gDuration) { _sign = gDuration.getSign(); _CY = gDuration.getYear(); _M = gDuration.getMonth(); _D = gDuration.getDay(); _h = gDuration.getHour(); _m = gDuration.getMinute(); _s = gDuration.getSecond(); _fs = gDuration.getFraction(); } /** * Builds another GDate with the same value * as this one. */ public Object clone() { return new GDuration(this); } /** * All GDuration instances return true. */ public final boolean isImmutable() { return true; } /** * Returns the sign of the duration: +1 is forwards * and -1 is backwards in time. */ public final int getSign() { return _sign; } /** * Gets the year component. */ public final int getYear() { return _CY; } /** * Gets the month-of-year component. */ public final int getMonth() { return _M; } /** * Gets the day-of-month component. */ public final int getDay() { return _D; } /** * Gets the hour-of-day component. */ public final int getHour() { return _h; } /** * Gets the minute-of-hour component. */ public final int getMinute() { return _m; } /** * Gets the second-of-minute component. */ public final int getSecond() { return _s; } /** * Gets the fraction-of-second. Range from 0 (inclusive) to 1 (exclusive). */ public BigDecimal getFraction() { return _fs; } /** * Returns true if all of the individual components * of the duration are nonnegative. */ public boolean isValid() { return GDurationBuilder.isValidDuration(this); } /** * Comparison to another GDuration. *

    *
  • Returns -1 if this < duration. (less-than) *
  • Returns 0 if this == duration. (equal) *
  • Returns 1 if this > duration. (greater-than) *
  • Returns 2 if this <> duration. (incomparable) *
* Two instances are incomparable if they have different amounts * of information. */ public final int compareToGDuration(GDurationSpecification duration) { return GDurationBuilder.compareDurations(this, duration); } /** * The natural string representation of the duration. *

* Any components that are zero are omitted. Note that if the duration * is invalid, i.e., it has negative components, those negative * components are serialized out here. To check for validity, use * the isValid() method; and to normalize most durations to a valid * form use the normalize() method. */ public String toString() { return GDurationBuilder.formatDuration(this); } /** * Returns a new GDuration which is the sum of this one and the * supplied duration. Does a fieldwise addition, with no normalization. */ public GDuration add(GDurationSpecification duration) { int sign = _sign * duration.getSign(); return _add(duration, sign); } /** * Returns a new GDuration which is the result of subtracting * the supplied duration from this one. Does a fieldwise * subtraction, with no normalization. */ public GDuration subtract(GDurationSpecification duration) { int sign = -_sign * duration.getSign(); return _add(duration, sign); } private GDuration _add(GDurationSpecification duration, int sign) { GDuration result = new GDuration(this); result._CY += sign * duration.getYear(); result._M += sign * duration.getMonth(); result._D += sign * duration.getDay(); result._h += sign * duration.getHour(); result._m += sign * duration.getMinute(); result._s += sign * duration.getSecond(); if (duration.getFraction().signum() == 0) return result; if (result._fs.signum() == 0 && sign == 1) result._fs = duration.getFraction(); else result._fs = sign > 0 ? result._fs.add(duration.getFraction()) : result._fs.subtract(duration.getFraction()); return result; } /** * Two GDurations are equal if all their fields are equal. * The equals function does not apply normalizatin. */ public boolean equals(Object obj) { if (obj == this) return true; if (!(obj instanceof GDuration)) return false; GDuration duration = (GDuration)obj; return (_sign == duration.getSign() && _CY == duration.getYear() && _M == duration.getMonth() && _D == duration.getDay() && _h == duration.getHour() && _m == duration.getMinute() && _s == duration.getSecond() && _fs.equals(duration.getFraction())); } public int hashCode() { return (_s + _m * (60 + 7) + _h * (60 * 60 + 7) + _D * (60 * 60 * 24 + 7) + _M * (60 * 60 * 24 * 31 + 7) + _CY *(60 * 60 * 24 * 372 + 7) + _sign * 11917049); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy