Search code examples
javagroovyjasper-reports

Cut the Milliseconds from the BigDecimal value


I have the following value '4.6144444444' in the database as BigDecimal which conforms '04:36:51' in time pattern.

4.6144444444* 3600 0000 = 16611999.99984/1000 = 16611.99999984 seconds = 276.866666664 minutes.

This value 0.866666664*60 = 51.99999984 seconds also the total is '04:36:51.99999984'. Is there a way to cut the time value of '0.99999984' from '4.6144444444'?

Since I am adding up these values in the Jasper Report to calculate the sum.

0.1197222222 + 4.6144444444 + 0.7480555555 + 0.9475000000 = 6.4297222221 ==> 06:25:46 999 999 56

00:07:10 + 04:36:51 + 00:44:52 + 00:56:51 = 06:25:44

also there is two seconds difference in the result. Is there a way to manage that in Java or in Jasper?

Code

        def duration = rowTemp[7];
        def durationMiliseconds = duration * 3600000;
        def durationSeconds = durationMiliseconds/1000;
        def durationMinutes = (durationSeconds/60).toString();

        String[] durationMinutesSplitt = durationMinutes.split(".");
        def secondsPart = Double.parseDouble("0." + durationMinutesSplitt[1]);
        def secondWithMiliSeconds = secondsPart * 60;

In Jasper

In jasper I am rendering the vlaue as the following:

        <textField isStretchWithOverflow="true" isBlankWhenNull="true">
            <reportElement stretchType="RelativeToTallestObject" x="252" y="2" width="149" height="18" />
            <box topPadding="2" leftPadding="2" bottomPadding="2" rightPadding="2"/>
            <textElement textAlignment="Right" verticalAlignment="Middle">
                <font size="8" isBold="true" pdfFontName="Helvetica-Bold"/>
                <paragraph lineSpacing="Single"/>
            </textElement>
            <textFieldExpression><![CDATA[org.apache.commons.lang.time.DurationFormatUtils.formatDuration((long)$V{group1DurationStay}.doubleValue() * 3600000, "HH:mm:ss")]]></textFieldExpression>
        </textField>

Solution

  • So floats are difficult cause they are not precise, but well, floats. A nice explanation can be found on e.g. wikipedia https://en.wikipedia.org/wiki/Floating-point_arithmetic.

    In your case you would intuitively want to remove 0.99999984/3600=0.00027777773333333334 from the initial number, which gives 4.614166666666667. But that will result in 51.000000000001364 (because of how floats work).

    If you just care about the final result, then consider

    def duration = rowTemp[7];
    def durationSeconds = duration*3600;
    def durationMinutes = (durationSeconds/60);
    def secondsPart = durationMinutes - floor(durationMinutes)
    def secondWithMiliSeconds = secondsPart * 60;
    def secondWithoutMiliSeconds = floor(secondsPart * 60);
    

    (Code is untested)