📄 durationimpl.java
字号:
// negating 0x8000000000000000L causes an overflow l++; is0x8000000000000000L = true; } l *= -1; } else { signum = 0; } this.years = null; this.months = null; this.seconds = BigDecimal.valueOf((l % 60000L) + (is0x8000000000000000L ? 1 : 0), 3); l /= 60000L; this.minutes = (l == 0) ? null : BigInteger.valueOf(l % 60L); l /= 60L; this.hours = (l == 0) ? null : BigInteger.valueOf(l % 24L); l /= 24L; this.days = (l == 0) ? null : BigInteger.valueOf(l); } /** * Constructs a new Duration object by * parsing its string representation * "PnYnMnDTnHnMnS" as defined in XML Schema 1.0 section 3.2.6.1. * * <p> * The string representation may not have any leading * and trailing whitespaces. * * <p> * For example, this method parses strings like * "P1D" (1 day), "-PT100S" (-100 sec.), "P1DT12H" (1 days and 12 hours). * * <p> * The parsing is done field by field so that * the following holds for any lexically correct string x: * <pre> * new Duration(x).toString().equals(x) * </pre> * * Returns a non-null valid duration object that holds the value * indicated by the lexicalRepresentation parameter. * * @param lexicalRepresentation * Lexical representation of a duration. * @throws IllegalArgumentException * If the given string does not conform to the aforementioned * specification. * @throws NullPointerException * If the given string is null. */ protected DurationImpl(String lexicalRepresentation) throws IllegalArgumentException { // only if I could use the JDK1.4 regular expression .... final String s = lexicalRepresentation; boolean positive; int[] idx = new int[1]; int length = s.length(); boolean timeRequired = false; if (lexicalRepresentation == null) { throw new NullPointerException(); } idx[0] = 0; if (length != idx[0] && s.charAt(idx[0]) == '-') { idx[0]++; positive = false; } else { positive = true; } if (length != idx[0] && s.charAt(idx[0]++) != 'P') { throw new IllegalArgumentException(s); //,idx[0]-1); } // phase 1: chop the string into chunks // (where a chunk is '<number><a symbol>' //-------------------------------------- int dateLen = 0; String[] dateParts = new String[3]; int[] datePartsIndex = new int[3]; while (length != idx[0] && isDigit(s.charAt(idx[0])) && dateLen < 3) { datePartsIndex[dateLen] = idx[0]; dateParts[dateLen++] = parsePiece(s, idx); } if (length != idx[0]) { if (s.charAt(idx[0]++) == 'T') { timeRequired = true; } else { throw new IllegalArgumentException(s); // ,idx[0]-1); } } int timeLen = 0; String[] timeParts = new String[3]; int[] timePartsIndex = new int[3]; while (length != idx[0] && isDigitOrPeriod(s.charAt(idx[0])) && timeLen < 3) { timePartsIndex[timeLen] = idx[0]; timeParts[timeLen++] = parsePiece(s, idx); } if (timeRequired && timeLen == 0) { throw new IllegalArgumentException(s); // ,idx[0]); } if (length != idx[0]) { throw new IllegalArgumentException(s); // ,idx[0]); } if (dateLen == 0 && timeLen == 0) { throw new IllegalArgumentException(s); // ,idx[0]); } // phase 2: check the ordering of chunks //-------------------------------------- organizeParts(s, dateParts, datePartsIndex, dateLen, "YMD"); organizeParts(s, timeParts, timePartsIndex, timeLen, "HMS"); // parse into numbers years = parseBigInteger(s, dateParts[0], datePartsIndex[0]); months = parseBigInteger(s, dateParts[1], datePartsIndex[1]); days = parseBigInteger(s, dateParts[2], datePartsIndex[2]); hours = parseBigInteger(s, timeParts[0], timePartsIndex[0]); minutes = parseBigInteger(s, timeParts[1], timePartsIndex[1]); seconds = parseBigDecimal(s, timeParts[2], timePartsIndex[2]); signum = calcSignum(positive); } /** * TODO: Javadoc * * @param ch char to test. * * @return true if ch is a digit, else false. */ private static boolean isDigit(char ch) { return '0' <= ch && ch <= '9'; } /** * TODO: Javadoc * * @param ch to test. * * @return true if ch is a digit or a period, else false. */ private static boolean isDigitOrPeriod(char ch) { return isDigit(ch) || ch == '.'; } /** * TODO: Javadoc * * @param whole String to parse. * @param idx TODO: ??? * * @return Result of parsing. * * @throws IllegalArgumentException If whole cannot be parsed. */ private static String parsePiece(String whole, int[] idx) throws IllegalArgumentException { int start = idx[0]; while (idx[0] < whole.length() && isDigitOrPeriod(whole.charAt(idx[0]))) { idx[0]++; } if (idx[0] == whole.length()) { throw new IllegalArgumentException(whole); // ,idx[0]); } idx[0]++; return whole.substring(start, idx[0]); } /** * TODO: Javadoc. * * @param whole TODO: ??? * @param parts TODO: ??? * @param partsIndex TODO: ??? * @param len TODO: ??? * @param tokens TODO: ??? * * @throws IllegalArgumentException TODO: ??? */ private static void organizeParts( String whole, String[] parts, int[] partsIndex, int len, String tokens) throws IllegalArgumentException { int idx = tokens.length(); for (int i = len - 1; i >= 0; i--) { int nidx = tokens.lastIndexOf( parts[i].charAt(parts[i].length() - 1), idx - 1); if (nidx == -1) { throw new IllegalArgumentException(whole); // ,partsIndex[i]+parts[i].length()-1); } for (int j = nidx + 1; j < idx; j++) { parts[j] = null; } idx = nidx; parts[idx] = parts[i]; partsIndex[idx] = partsIndex[i]; } for (idx--; idx >= 0; idx--) { parts[idx] = null; } } /** * TODO: Javadoc * * @param whole TODO: ???. * @param part TODO: ???. * @param index TODO: ???. * * @return TODO: ???. * * @throws IllegalArgumentException TODO: ???. */ private static BigInteger parseBigInteger( String whole, String part, int index) throws IllegalArgumentException { if (part == null) { return null; } part = part.substring(0, part.length() - 1); // try { return new BigInteger(part); // } catch( NumberFormatException e ) { // throw new ParseException( whole, index ); // } } /** * TODO: Javadoc. * * @param whole TODO: ???. * @param part TODO: ???. * @param index TODO: ???. * * @return TODO: ???. * * @throws IllegalArgumentException TODO: ???. */ private static BigDecimal parseBigDecimal( String whole, String part, int index) throws IllegalArgumentException { if (part == null) { return null; } part = part.substring(0, part.length() - 1); // NumberFormatException is IllegalArgumentException // try { return new BigDecimal(part); // } catch( NumberFormatException e ) { // throw new ParseException( whole, index ); // } } /** * <p>Four constants defined for the comparison of durations.</p> */ private static final XMLGregorianCalendar[] TEST_POINTS = new XMLGregorianCalendar[] { XMLGregorianCalendarImpl.parse("1696-09-01T00:00:00Z"), XMLGregorianCalendarImpl.parse("1697-02-01T00:00:00Z"), XMLGregorianCalendarImpl.parse("1903-03-01T00:00:00Z"), XMLGregorianCalendarImpl.parse("1903-07-01T00:00:00Z") }; /** * <p>Partial order relation comparison with this <code>Duration</code> instance.</p> * * <p>Comparison result must be in accordance with * <a href="http://www.w3.org/TR/xmlschema-2/#duration-order">W3C XML Schema 1.0 Part 2, Section 3.2.7.6.2, * <i>Order relation on duration</i></a>.</p> * * <p>Return:</p> * <ul> * <li>{@link DatatypeConstants#LESSER} if this <code>Duration</code> is shorter than <code>duration</code> parameter</li> * <li>{@link DatatypeConstants#EQUAL} if this <code>Duration</code> is equal to <code>duration</code> parameter</li> * <li>{@link DatatypeConstants#GREATER} if this <code>Duration</code> is longer than <code>duration</code> parameter</li> * <li>{@link DatatypeConstants#INDETERMINATE} if a conclusive partial order relation cannot be determined</li> * </ul> * * @param duration to compare * * @return the relationship between <code>this</code> <code>Duration</code>and <code>duration</code> parameter as * {@link DatatypeConstants#LESSER}, {@link DatatypeConstants#EQUAL}, {@link DatatypeConstants#GREATER} * or {@link DatatypeConstants#INDETERMINATE}. * * @throws UnsupportedOperationException If the underlying implementation * cannot reasonably process the request, e.g. W3C XML Schema allows for * arbitrarily large/small/precise values, the request may be beyond the * implementations capability. * @throws NullPointerException if <code>duration</code> is <code>null</code>. * * @see #isShorterThan(Duration) * @see #isLongerThan(Duration) */ public int compare(Duration rhs) { BigInteger maxintAsBigInteger = BigInteger.valueOf((long) Integer.MAX_VALUE); BigInteger minintAsBigInteger = BigInteger.valueOf((long) Integer.MIN_VALUE); // check for fields that are too large in this Duration if (years != null && years.compareTo(maxintAsBigInteger) == 1) { throw new UnsupportedOperationException( DatatypeMessageFormatter.formatMessage(null, "TooLarge", new Object[]{this.getClass().getName() + "#compare(Duration duration)" + DatatypeConstants.YEARS.toString(), years.toString()}) //this.getClass().getName() + "#compare(Duration duration)" //+ " years too large to be supported by this implementation " //+ years.toString() ); } if (months != null && months.compareTo(maxintAsBigInteger) == 1) { throw new UnsupportedOperationException( DatatypeMessageFormatter.formatMessage(null, "TooLarge", new Object[]{this.getClass().getName() + "#compare(Duration duration)" + DatatypeConstants.MONTHS.toString(), months.toString()}) //this.getClass().getName() + "#compare(Duration duration)" //+ " months too large to be supported by this implementation " //+ months.toString() ); } if (days != null && days.compareTo(maxintAsBigInteger) == 1) { throw new UnsupportedOperationException( DatatypeMessageFormatter.formatMessage(null, "TooLarge", new Object[]{this.getClass().getName() + "#compare(Duration duration)" + DatatypeConstants.DAYS.toString(), days.toString()}) //this.getClass().getName() + "#compare(Duration duration)" //+ " days too large to be supported by this implementation " //+ days.toString() ); } if (hours != null && hours.compareTo(maxintAsBigInteger) == 1) { throw new UnsupportedOperationException( DatatypeMessageFormatter.formatMessage(null, "TooLarge", new Object[]{this.getClass().getName() + "#compare(Duration duration)" + DatatypeConstants.HOURS.toString(), hours.toString()}) //this.getClass().getName() + "#compare(Duration duration)"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -