[
https://issues.apache.org/jira/browse/XERCESJ-1669?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Benjamin Tenne updated XERCESJ-1669:
------------------------------------
Component/s: JAXP (javax.xml.datatype)
> Duration arithmetic can give the wrong result when fractional seconds are used
> ------------------------------------------------------------------------------
>
> Key: XERCESJ-1669
> URL: https://issues.apache.org/jira/browse/XERCESJ-1669
> Project: Xerces2-J
> Issue Type: Bug
> Components: JAXP (javax.xml.datatype)
> Affects Versions: 2.11.0
> Reporter: Benjamin Tenne
> Priority: Minor
>
> Consider the following:
> {code}
> DatatypeFactory fac = DatatypeFactory.newInstance();
>
> Duration a1 = fac.newDuration("PT4H");
> Duration a2 = fac.newDuration("PT1S");
> System.out.println(a1.subtract(a2));
> {code}
> As expected, subtracting a second from four hours results in:
> PT3H59M59S
> However, if fractional seconds are used...
> {code}
> DatatypeFactory fac = DatatypeFactory.newInstance();
>
> Duration a1 = fac.newDuration("PT4H");
> Duration a2 = fac.newDuration("PT1.0S");
> System.out.println(a1.subtract(a2));
> {code}
> This gives the unexpected result of:
> PT39H59M5.0S
> This appears to be due to a bug in DurationImpl. The subtraction gives an
> intermediate result of PT4H-1.0S, which is then normalized in the alignSigns
> method to eliminate the negative seconds. The logic that calculates "How may
> minutes do we need to borrow from the minutes column to eliminate the
> negative seconds?" should result in 1, but actually results in 0.1. This is
> due to the use of the divide(BigDecimal divisor, int roundingMode) method.
> The code appears to be expecting this method to return an integer, but it
> doesn't; it inherits the scale of the original BigDecimal, which in this case
> has one decimal place.
> I believe the fix would be to call the three-arg method that takes a scale,
> setting it to zero, thus forcing the desired behaviour of getting an integer
> back:
> {code}
> // compute the number of unit that needs to be borrowed.
> BigDecimal borrow =
> buf[i].abs().divide(
> FACTORS[i - 1],
> 0, // Division must result in an integer
> BigDecimal.ROUND_UP);
> {code}
--
This message was sent by Atlassian JIRA
(v6.3.4#6332)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]