You are viewing a plain text version of this content. The canonical link for it is here.
Posted to j-dev@xerces.apache.org by "Benjamin Tenne (JIRA)" <xe...@xml.apache.org> on 2016/06/07 09:37:21 UTC

[jira] [Created] (XERCESJ-1669) Duration arithmetic can give the wrong result when fractional seconds are used

Benjamin Tenne created XERCESJ-1669:
---------------------------------------

             Summary: 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
    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: j-dev-unsubscribe@xerces.apache.org
For additional commands, e-mail: j-dev-help@xerces.apache.org