[ 
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]

Reply via email to