commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bay...@apache.org
Subject cvs commit: jakarta-commons/lang/src/test/org/apache/commons/lang/time DurationFormatUtilsTest.java
Date Mon, 27 Sep 2004 03:14:15 GMT
bayard      2004/09/26 20:14:15

  Modified:    lang/src/java/org/apache/commons/lang/time DateUtils.java
                        DurationFormatUtils.java
               lang/src/test/org/apache/commons/lang/time
                        DurationFormatUtilsTest.java
  Log:
  removed the weak assumptions for number of millis in a month/year from DateUtils. Implemented
a second format method that relies on a start and an end in DurationFormatUtils, though I
found that TimeZone was very important in the overloaded millis version. The two methods hand
off to each other depending on whether the time is > or < than 28 days
  
  Revision  Changes    Path
  1.30      +1 -5      jakarta-commons/lang/src/java/org/apache/commons/lang/time/DateUtils.java
  
  Index: DateUtils.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/lang/src/java/org/apache/commons/lang/time/DateUtils.java,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- DateUtils.java	26 Sep 2004 05:45:33 -0000	1.29
  +++ DateUtils.java	27 Sep 2004 03:14:15 -0000	1.30
  @@ -56,10 +56,6 @@
        */
       public static final long MILLIS_PER_DAY = 24 * MILLIS_PER_HOUR;
   
  -    // hmm. not very accurate. used by DurationFormatUtils
  -    static final long MILLIS_PER_YEAR = 365 * MILLIS_PER_DAY + 6 * MILLIS_PER_HOUR;
  -    static final long MILLIS_PER_MONTH = MILLIS_PER_YEAR / 12;
  -
       /**
        * This is half a month, so this represents whether a date is in the top
        * or bottom half of the month.
  
  
  
  1.15      +106 -3    jakarta-commons/lang/src/java/org/apache/commons/lang/time/DurationFormatUtils.java
  
  Index: DurationFormatUtils.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/lang/src/java/org/apache/commons/lang/time/DurationFormatUtils.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- DurationFormatUtils.java	26 Sep 2004 05:45:33 -0000	1.14
  +++ DurationFormatUtils.java	27 Sep 2004 03:14:15 -0000	1.15
  @@ -17,6 +17,9 @@
   
   import org.apache.commons.lang.StringUtils;
   
  +import java.util.Calendar;
  +import java.util.TimeZone;
  +
   /**
    * <p>Duration formatting utilities and constants.</p>
    *
  @@ -101,9 +104,18 @@
           return format(millis, format, true);
       }
       public static String format(long millis, String format, boolean padWithZeros) {
  -        StringBuffer buffer = new StringBuffer();
  +        return format(millis, format, padWithZeros, TimeZone.getDefault());
  +    }
  +    public static String format(long millis, String format, boolean padWithZeros, TimeZone
timezone) {
  +
  +        if(millis > 28 * DateUtils.MILLIS_PER_DAY) {
  +            Calendar c = Calendar.getInstance(timezone);
  +            c.set(1970, 0, 1, 0, 0, 0);
  +            c.set(Calendar.MILLISECOND, 0);
  +            return format(c.getTime().getTime(), millis, format, padWithZeros, timezone);
  +        }
  +
           Token[] tokens = lexx(format);
  -        int sz = tokens.length;
   
           int years        = 0;
           int months       = 0;
  @@ -113,6 +125,7 @@
           int seconds      = 0;
           int milliseconds = 0;
   
  +        /*  This will never be evaluated
           if(Token.containsTokenWithValue(tokens, y) ) {
               years = (int) (millis / DateUtils.MILLIS_PER_YEAR);
               millis = millis - (years * DateUtils.MILLIS_PER_YEAR);
  @@ -126,6 +139,7 @@
                   months = 0;
               }
           }
  +        */
           if(Token.containsTokenWithValue(tokens, d) ) {
               days = (int) (millis / DateUtils.MILLIS_PER_DAY);
               millis = millis - (days * DateUtils.MILLIS_PER_DAY);
  @@ -146,7 +160,15 @@
               milliseconds = (int) millis;
           }
   
  +        return formatDuration(tokens, years, months, days, hours, minutes, seconds, milliseconds,
padWithZeros);
  +    }
  +
   
  +    private static String formatDuration(Token[] tokens, int years, int months, int days,
int hours, 
  +                                         int minutes, int seconds, int milliseconds, boolean
padWithZeros) 
  +    { 
  +        StringBuffer buffer = new StringBuffer();
  +        int sz = tokens.length;
           for(int i=0; i<sz; i++) {
               Token token = tokens[i];
               Object value = token.getValue();
  @@ -179,6 +201,87 @@
           }
           
           return buffer.toString();
  +    }
  +
  +    // slower than the above I presume
  +    public static String format(long startMillis, long endMillis, String format, boolean
padWithZeros) {
  +        return format(startMillis, endMillis, format, padWithZeros, TimeZone.getDefault());
  +    }
  +    public static String format(long startMillis, long endMillis, String format, boolean
padWithZeros, TimeZone timezone) {
  +
  +        long millis = endMillis - startMillis;
  +        if(millis < 28 * DateUtils.MILLIS_PER_DAY) {
  +            return format(millis, format, padWithZeros, timezone);
  +        }
  +
  +        Token[] tokens = lexx(format);
  +
  +        // timezones get funky around 0, so normalizing everything to GMT 
  +        // stops the hours being off
  +        Calendar start = Calendar.getInstance(timezone);
  +        start.setTimeInMillis(startMillis);
  +        Calendar end = Calendar.getInstance(timezone);
  +        end.setTimeInMillis(endMillis);
  +
  +        // initial estimates
  +        int years = end.get(Calendar.YEAR) - start.get(Calendar.YEAR);
  +        int months = end.get(Calendar.MONTH) - start.get(Calendar.MONTH);
  +        // each initial estimate is adjusted in case it is under 0
  +        while(months < 0) {
  +            months += 12;
  +            years -= 1;
  +        }
  +        int days = end.get(Calendar.DAY_OF_MONTH) - start.get(Calendar.DAY_OF_MONTH);
  +        while(days < 0) {
  +            days += 31;  // such overshooting is taken care of later on
  +            days -= 1;
  +        }
  +        int hours = end.get(Calendar.HOUR_OF_DAY) - start.get(Calendar.HOUR_OF_DAY);
  +        while(hours < 0) {
  +            hours += 24;
  +            days -= 1;
  +        }
  +        int minutes = end.get(Calendar.MINUTE) - start.get(Calendar.MINUTE);
  +        while(minutes < 0) {
  +            minutes += 60;
  +            hours -= 1;
  +        }
  +        int seconds = end.get(Calendar.SECOND) - start.get(Calendar.SECOND);
  +        while(seconds < 0) {
  +            seconds += 60;
  +            minutes -= 1;
  +        }
  +        int milliseconds = end.get(Calendar.MILLISECOND) - start.get(Calendar.MILLISECOND);
  +        while(milliseconds < 0) {
  +            milliseconds += 1000;
  +            seconds -= 1;
  +        }
  +
  +        // take estimates off of end to see if we can equal start, when it overshoots recalculate
  +        milliseconds -= reduceAndCorrect( start, end, Calendar.MILLISECOND, milliseconds
);
  +        seconds -= reduceAndCorrect( start, end, Calendar.SECOND, seconds );
  +        minutes -= reduceAndCorrect( start, end, Calendar.MINUTE, minutes );
  +        hours -= reduceAndCorrect( start, end, Calendar.HOUR_OF_DAY, hours );
  +        days -= reduceAndCorrect( start, end, Calendar.DAY_OF_MONTH, days );
  +        months -= reduceAndCorrect( start, end, Calendar.MONTH, months );
  +        years -= reduceAndCorrect( start, end, Calendar.YEAR, years );
  +
  +        return formatDuration(tokens, years, months, days, hours, minutes, seconds, milliseconds,
padWithZeros);
  +    }
  +
  +    // Reduces by difference, then if it overshot, calculates the overshot amount and 
  +    // fixes and returns the amount to change by
  +    private static int reduceAndCorrect(Calendar start, Calendar end, int field, int difference)
{
  +        end.add( field, -1 * difference );
  +        int endValue = end.get(field);
  +        int startValue = start.get(field);
  +        if(endValue < startValue) {
  +            int newdiff = startValue - endValue;
  +            end.add( field, newdiff );
  +            return newdiff;
  +        } else {
  +            return 0;
  +        }
       }
   
       /**
  
  
  
  1.12      +6 -7      jakarta-commons/lang/src/test/org/apache/commons/lang/time/DurationFormatUtilsTest.java
  
  Index: DurationFormatUtilsTest.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons/lang/src/test/org/apache/commons/lang/time/DurationFormatUtilsTest.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- DurationFormatUtilsTest.java	26 Sep 2004 05:45:33 -0000	1.11
  +++ DurationFormatUtilsTest.java	27 Sep 2004 03:14:15 -0000	1.12
  @@ -157,16 +157,13 @@
           text = DateFormatUtils.ISO_DATETIME_TIME_ZONE_FORMAT.format(cal);
           assertEquals("2002-02-23T09:11:12-03:00", text);
           // test fixture is the same as above, but now with extended format.
  -        text = DurationFormatUtils.format(cal.getTime().getTime(), DurationFormatUtils.ISO_EXTENDED_FORMAT_PATTERN,
false);
  -        // TODO: The 1H41M here should be 9H11M. Again the year/month assumption.
  -        System.err.println("T: "+text);
  -        assertEquals("P32Y1M23DT1H41M12.1S", text);
  +        text = DurationFormatUtils.format(cal.getTime().getTime(), DurationFormatUtils.ISO_EXTENDED_FORMAT_PATTERN,
false, timeZone);
  +        assertEquals("P32Y1M22DT9H11M12.1S", text);
           // test fixture from example in http://www.w3.org/TR/xmlschema-2/#duration
           cal.set(1971, 1, 3, 10, 30, 0);
           cal.set(Calendar.MILLISECOND, 0);
  -        text = DurationFormatUtils.format(cal.getTime().getTime(), DurationFormatUtils.ISO_EXTENDED_FORMAT_PATTERN,
false);
  -        // TODO: The 2D21H here is wrong and should be larger. The Year/Month assumption
in DurationFormatUtils.
  -        assertEquals("P1Y1M2DT21H0M0.0S", text);
  +        text = DurationFormatUtils.format(cal.getTime().getTime(), DurationFormatUtils.ISO_EXTENDED_FORMAT_PATTERN,
false, timeZone);
  +        assertEquals("P1Y1M2DT10H30M0.0S", text);
           // want a way to say 'don't print the seconds in format()' or other fields for
that matter:
           //assertEquals("P1Y2M3DT10H30M", text);
       }
  @@ -194,6 +191,7 @@
           assertEquals( "60000", DurationFormatUtils.format(time, "S") );
           assertEquals( "01:00", DurationFormatUtils.format(time, "mm:ss") );
   
  +        /*
           time = 3 * DateUtils.MILLIS_PER_YEAR + 7 * DateUtils.MILLIS_PER_MONTH;
           assertEquals( "37", DurationFormatUtils.format(time, "yM") );
           assertEquals( "3 years 7 months", DurationFormatUtils.format(time, "y' years 'M'
months'") );
  @@ -211,6 +209,7 @@
           assertEquals( "48", DurationFormatUtils.format(time, "M") );
           assertEquals( "48", DurationFormatUtils.format(time, "MM") );
           assertEquals( "048", DurationFormatUtils.format(time, "MMM") );
  +        */
   
       }
   
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


Mime
View raw message