Commons Lang
  1. Commons Lang
  2. LANG-140

[lang] DurationFormatUtils.formatPeriod() returns the wrong result

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 2.2
    • Component/s: None
    • Labels:
      None
    • Environment:

      Operating System: Windows XP
      Platform: PC

      Description

      /**

      • lib: commons-lang-2.1.jar
      • this class run result.
      • Result:
      • Date1->Date2=2006/01/26 18:47:34 000->2006/02/26 10:47:34 000===0000”N01
        ŒŽ-1“ú 16:00:00 000
      • Date1->Date2=2006/01/26 18:47:34 000->2006/02/26 10:47:34 000===0000/01/-
        1 16:00:00 000
      • want result:
      • Date1->Date2=2006/01/26 18:47:34 000->2006/02/26 10:47:34 000===0000”N00ŒŽ
        30“ú 16:00:00
      • Date1->Date2=2006/01/26 18:47:34 000->2006/02/26 10:47:34
        000===0000/00/30 16:00:00
      • the results are wrong.
      • */

      import java.text.SimpleDateFormat;
      import java.util.Calendar;
      import java.util.Date;

      import org.apache.commons.lang.time.DurationFormatUtils;

      public class Test {

      static SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd
      HH:mm:ss SSS");

      public static void main(String[] args)

      { Date date1 = newDate(2006, 1, 26, 18, 47, 34); Date date2 = newDate(2006, 2, 26, 10, 47, 34); System.out.println("Date1->Date2=" + formatter.format(date1) + "->" + formatter.format(date2) + "===" + DurationFormatUtils.formatPeriod(date1.getTime(), date2.getTime (), "yyyy”NMMŒŽdd“ú HH:mm:ss SSS") ); System.out.println("Date1->Date2=" + formatter.format(date1) + "->" + formatter.format(date2) + "===" + DurationFormatUtils.formatPeriod(date1.getTime(), date2.getTime (), "yyyy/MM/dd HH:mm:ss SSS") ); }

      public static Date newDate(int y, int m, int d, int h, int mi, int s)

      { Calendar calendar1 = Calendar.getInstance(); calendar1.clear(); calendar1.set(y, m - 1, d, h, mi, s); Date date1 = calendar1.getTime(); return date1; }

      }

      1. LANG-140.patch
        4 kB
        Henri Yandell
      2. ASF.LICENSE.NOT.GRANTED--Period.java
        4 kB
        yu.peng
      3. ASF.LICENSE.NOT.GRANTED--38401.patch
        1 kB
        Henri Yandell

        Activity

        Mark Thomas made changes -
        Workflow jira [ 12371779 ] Default workflow, editable Closed status [ 12602377 ]
        Henri Yandell made changes -
        Status Resolved [ 5 ] Closed [ 6 ]
        Henri Yandell made changes -
        Resolution Fixed [ 1 ]
        Assignee Henri Yandell [ bayard ]
        Status Open [ 1 ] Resolved [ 5 ]
        Hide
        Henri Yandell added a comment -

        Fix committed. Played with it while on holiday and found that there was a nice simple fix (least all the unit tests pass with this fix and it seems to make sense). The nightly build appears to be down currently, so the way to get to the code would be to svn co https://svn.apache.org/repos/asf/jakarta/commons/proper/lang/trunk and build a jar using ant or maven.

        svn ci -m "Added unit test for LANG-140 - thanks to Yu Peng for the test case" src/t
        est/org/apache/commons/lang/time/DurationFormatUtilsTest.java
        Sending src/test/org/apache/commons/lang/time/DurationFormatUtilsTest.java
        Transmitting file data .
        Committed revision 415316.

        svn ci -m "Committing fix for LANG-140. By reversing the order of field calculation,
        Yu Peng's bug goes away" src/java/org/apache/commons/lang/time/DurationFormatUtils.java
        Sending src/java/org/apache/commons/lang/time/DurationFormatUtils.java
        Transmitting file data .
        Committed revision 415317.

        Show
        Henri Yandell added a comment - Fix committed. Played with it while on holiday and found that there was a nice simple fix (least all the unit tests pass with this fix and it seems to make sense). The nightly build appears to be down currently, so the way to get to the code would be to svn co https://svn.apache.org/repos/asf/jakarta/commons/proper/lang/trunk and build a jar using ant or maven. svn ci -m "Added unit test for LANG-140 - thanks to Yu Peng for the test case" src/t est/org/apache/commons/lang/time/DurationFormatUtilsTest.java Sending src/test/org/apache/commons/lang/time/DurationFormatUtilsTest.java Transmitting file data . Committed revision 415316. svn ci -m "Committing fix for LANG-140 . By reversing the order of field calculation, Yu Peng's bug goes away" src/java/org/apache/commons/lang/time/DurationFormatUtils.java Sending src/java/org/apache/commons/lang/time/DurationFormatUtils.java Transmitting file data . Committed revision 415317.
        Hide
        yu.peng added a comment -

        How can I get the DurationFormatUtilsTest.java and fixed DurationFormatUtils.java.

        Show
        yu.peng added a comment - How can I get the DurationFormatUtilsTest.java and fixed DurationFormatUtils.java.
        Henri Yandell made changes -
        Attachment LANG-140.patch [ 12334216 ]
        Hide
        Henri Yandell added a comment -

        Period.java put into the source. Other tests unfortunately error.

        Show
        Henri Yandell added a comment - Period.java put into the source. Other tests unfortunately error.
        Hide
        Henri Yandell added a comment -

        Hooking Period.java up, it gives a couple of errors:

        Testsuite: org.apache.commons.lang.time.TimeTestSuite
        Tests run: 54, Failures: 2, Errors: 0, Time elapsed: 5.777 sec

        Testcase: testFormatPeriodISO(org.apache.commons.lang.time.DurationFormatUtilsTest): FAILED
        expected:<......> but was:<...3...>
        junit.framework.ComparisonFailure: expected:<......> but was:<...3...>
        at org.apache.commons.lang.time.DurationFormatUtilsTest.testFormatPeriodISO(DurationFormatUtilsTest.java:285)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

        Testcase: testFormatPeriod(org.apache.commons.lang.time.DurationFormatUtilsTest): FAILED
        expected:<6...> but was:<...>
        junit.framework.ComparisonFailure: expected:<6...> but was:<...>
        at org.apache.commons.lang.time.DurationFormatUtilsTest.testFormatPeriod(DurationFormatUtilsTest.java:319)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)

        Show
        Henri Yandell added a comment - Hooking Period.java up, it gives a couple of errors: Testsuite: org.apache.commons.lang.time.TimeTestSuite Tests run: 54, Failures: 2, Errors: 0, Time elapsed: 5.777 sec Testcase: testFormatPeriodISO(org.apache.commons.lang.time.DurationFormatUtilsTest): FAILED expected:<......> but was:<...3...> junit.framework.ComparisonFailure: expected:<......> but was:<...3...> at org.apache.commons.lang.time.DurationFormatUtilsTest.testFormatPeriodISO(DurationFormatUtilsTest.java:285) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) Testcase: testFormatPeriod(org.apache.commons.lang.time.DurationFormatUtilsTest): FAILED expected:<6...> but was:<...> junit.framework.ComparisonFailure: expected:<6...> but was:<...> at org.apache.commons.lang.time.DurationFormatUtilsTest.testFormatPeriod(DurationFormatUtilsTest.java:319) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        Henri Yandell made changes -
        Fix Version/s 2.2 [ 12311702 ]
        Henri Yandell made changes -
        Component/s Lang [ 12311121 ]
        Assignee Jakarta Commons Developers Mailing List [ commons-dev@jakarta.apache.org ]
        Project Commons [ 12310458 ] Commons Lang [ 12310481 ]
        Fix Version/s 2.2 [ 12311686 ]
        Affects Version/s unspecified [ 12311647 ]
        Key COM-2722 LANG-140
        Henri Yandell made changes -
        Field Original Value New Value
        issue.field.bugzillaimportkey 38401 12342874
        Hide
        Henri Yandell added a comment -

        Created an attachment (id=18111)
        Unit test for this bug.

        Show
        Henri Yandell added a comment - Created an attachment (id=18111) Unit test for this bug.
        Hide
        yu.peng added a comment -

        Created an attachment (id=17861)
        period

        there is a "period" method in this file , that method can return the period
        String , can't format it , because the some format methods are use 'package'
        defined. I hope the "period" method can add into the common_lang lib,and
        provides the format function.

        Show
        yu.peng added a comment - Created an attachment (id=17861) period there is a "period" method in this file , that method can return the period String , can't format it , because the some format methods are use 'package' defined. I hope the "period" method can add into the common_lang lib,and provides the format function.
        Hide
        ggregory@seagullsw.com added a comment -

        In the context of Ticket 33825
        (http://issues.apache.org/bugzilla/show_bug.cgi?id=33825), one can consider
        Joda-Time.

        Show
        ggregory@seagullsw.com added a comment - In the context of Ticket 33825 ( http://issues.apache.org/bugzilla/show_bug.cgi?id=33825 ), one can consider Joda-Time.
        Hide
        Henri Yandell added a comment -

        Not that easy though. Needs to be, for this particular case:

        If days = 0, then roll month back (from 1 to 0) and set days to the maximum
        number of days in the preceding month (which is January and thus 30).

        It gets ugly when you get down to the seconds, as their rollback effect becomes
        an increasingly nested loop.

        Show
        Henri Yandell added a comment - Not that easy though. Needs to be, for this particular case: If days = 0, then roll month back (from 1 to 0) and set days to the maximum number of days in the preceding month (which is January and thus 30). It gets ugly when you get down to the seconds, as their rollback effect becomes an increasingly nested loop.
        Hide
        Henri Yandell added a comment -

        So it's claiming it's 1 month minus 1 day and not 30 days. Ugh.

        Looking into it, the issue is that when the code rolls back in hours, it rolls
        the days back - even if 0. It needs to roll months back if days are 0 (and so on
        back up to years).

        Show
        Henri Yandell added a comment - So it's claiming it's 1 month minus 1 day and not 30 days. Ugh. Looking into it, the issue is that when the code rolls back in hours, it rolls the days back - even if 0. It needs to roll months back if days are 0 (and so on back up to years).
        yu.peng created issue -

          People

          • Assignee:
            Henri Yandell
            Reporter:
            yu.peng
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development