ceki        2004/12/23 06:07:58

  Modified:    src/java/org/apache/log4j/helpers
                        AbsoluteTimeDateFormat.java
               src/java/org/apache/log4j/pattern CachedDateFormat.java
               tests/src/java/org/apache/log4j/pattern
                        CachedDateFormatTest.java
  Log:
  Simplified but still untested version of CacheDateFormat
  
  Revision  Changes    Path
  1.6       +2 -0      
logging-log4j/src/java/org/apache/log4j/helpers/AbsoluteTimeDateFormat.java
  
  Index: AbsoluteTimeDateFormat.java
  ===================================================================
  RCS file: 
/home/cvs/logging-log4j/src/java/org/apache/log4j/helpers/AbsoluteTimeDateFormat.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- AbsoluteTimeDateFormat.java       21 Dec 2004 04:19:47 -0000      1.5
  +++ AbsoluteTimeDateFormat.java       23 Dec 2004 14:07:58 -0000      1.6
  @@ -36,6 +36,8 @@
        value is <b>ABSOLUTE</b>.  */
     public static final String ABS_TIME_DATE_FORMAT = "ABSOLUTE";
   
  +  public static final String ABS_TIME_DATE_PATTERN = "HH:mm:ss,SSS";
  +  
     /**
        String constant used to specify [EMAIL PROTECTED]
        org.apache.log4j.helpers.DateTimeDateFormat} in layouts.  Current
  
  
  
  1.3       +90 -68    
logging-log4j/src/java/org/apache/log4j/pattern/CachedDateFormat.java
  
  Index: CachedDateFormat.java
  ===================================================================
  RCS file: 
/home/cvs/logging-log4j/src/java/org/apache/log4j/pattern/CachedDateFormat.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- CachedDateFormat.java     23 Dec 2004 13:00:58 -0000      1.2
  +++ CachedDateFormat.java     23 Dec 2004 14:07:58 -0000      1.3
  @@ -16,45 +16,73 @@
   
   package org.apache.log4j.pattern;
   
  -import java.util.Date;
  -import java.text.FieldPosition;
  -import java.text.ParsePosition;
   import java.text.DateFormat;
  +import java.text.FieldPosition;
   import java.text.NumberFormat;
  +import java.text.ParsePosition;
  +import java.text.SimpleDateFormat;
  +
  +import java.util.Date;
  +import java.util.Locale;
   import java.util.TimeZone;
   
  +
   /**
    * Caches the results of a DateFormat.
    *  @author Curt Arnold
    *  @since 1.3
    */
   final class CachedDateFormat extends DateFormat {
  +  private static final int UNRECOGNIZED_MILLISECOND_PATTERN = -2;
  +  private static final int NO_MILLISECOND_PATTERN = -1;
  +
  +  // We take advantage of structure of the sentinel, in particular
  +  // the incremental decrease in the digits 9, 8, and 7.
  +  private static final int SENTINEL = 987;
     private DateFormat formatter;
     private int millisecondStart;
     private StringBuffer cache = new StringBuffer();
  -  private long previousTime;
  +  private long slotBegin;
  +  private int milliDigits;
  +  private StringBuffer milliBuf = new StringBuffer(3);
     private NumberFormat numberFormat;
  -  private static final int UNRECOGNIZED_MILLISECOND_PATTERN = -2;
  -  private static final int NO_MILLISECOND_PATTERN = -1;
  -  
  -  public CachedDateFormat(final DateFormat formatter) {
  -    if (formatter == null) {
  -      throw new NullPointerException("formatter");
  +
  +  public CachedDateFormat(String pattern) {
  +    this(pattern, null);
  +  }
  +
  +  public CachedDateFormat(String pattern, Locale locale) {
  +    if (pattern == null) {
  +      throw new IllegalArgumentException("Pattern cannot be null");
  +    }
  +    if (locale == null) {
  +      this.formatter = new SimpleDateFormat(pattern);
  +    } else {
  +      this.formatter = new SimpleDateFormat(pattern, locale);
  +    }
  +    milliDigits = CacheUtil.computeSuccessiveS(pattern);
  +
  +    // if the number if millisecond digits is 4 or more, we can safely reduce
  +    // the precision to 3, because the values for the extra digits will 
always
  +    // be 0, thus immutable across iterations.
  +    if (milliDigits >= 4) {
  +      milliDigits = 3;
       }
  -    this.formatter = formatter;
       numberFormat = formatter.getNumberFormat();
       if (numberFormat == null) {
         throw new NullPointerException("numberFormat");
       }
  +    // delegate zero padding to numberFormat
  +    numberFormat.setMinimumIntegerDigits(milliDigits);
  +    
       Date now = new Date();
       long nowTime = now.getTime();
  -    previousTime = (nowTime / 1000L) * 1000L;
  +    slotBegin = (nowTime / 1000L) * 1000L;
   
  -    Date lastSecond = new Date(previousTime);
  -    String formatted = formatter.format(lastSecond);
  +    Date slotBegingDate = new Date(slotBegin);
  +    String formatted = formatter.format(slotBegingDate);
       cache.append(formatted);
  -    millisecondStart = findMillisecondStart(previousTime, formatted,
  -                                            formatter);
  +    millisecondStart = findMillisecondStart(slotBegin, formatted, formatter);
     }
   
     /**
  @@ -66,31 +94,38 @@
      *    -1 indicates no millisecond field, -2 indicates unrecognized
      *    field (likely RelativeTimeDateFormat)
      */
  -  private static int findMillisecondStart(final long time,
  -                                          final String formatted,
  -                                          final DateFormat formatter) {
  -      String plus987 = formatter.format(new Date(time + 987));
  -      //
  -      //    find first difference between values
  -      //
  -      for (int i = 0; i < formatted.length(); i++) {
  -        if (formatted.charAt(i) != plus987.charAt(i)) {
  -          //
  -          //   if one string has "000" and the other "987"
  -          //      we have found the millisecond field
  -          //
  -          if (i + 3 <= formatted.length() 
  -              && formatted.substring(i, i + 3) == "000" 
  -              && plus987.substring(i, i + 3) == "987") {
  -            return i;
  -          } else {
  +  private int findMillisecondStart(
  +    final long time, final String formatted, final DateFormat formatter) {
  +    // the following code assume that the value of the SENTINEL is
  +    // 987. It won't work corectly if the SENTINEL is not 987.
  +    String plus987 = formatter.format(new Date(time + SENTINEL));
  +
  +    //
  +    //    find first difference between values
  +    //
  +    for (int i = 0; i < formatted.length(); i++) {
  +      if (formatted.charAt(i) != plus987.charAt(i)) {
  +        //
  +        //   if one string has "000" and the other "987"
  +        //      we have found the millisecond field
  +        //
  +        if ((i + milliDigits) <= formatted.length()) {
  +          for (int j = 0; j < milliDigits; j++) {
  +            if (
  +              (formatted.charAt(i + j) != '0')
  +                || (formatted.charAt(i + j) != ('9' - j))) {
  +              ;
  +            }
               return UNRECOGNIZED_MILLISECOND_PATTERN;
             }
  +          return i;
  +        } else {
  +          return UNRECOGNIZED_MILLISECOND_PATTERN;
           }
         }
  +    }
       return NO_MILLISECOND_PATTERN;
  -}
  -
  +  }
   
     /**
      * Converts a Date utilizing a previously converted
  @@ -100,46 +135,36 @@
        @param sbuf the string buffer to write to
        @param fieldPosition remains untouched
      */
  -  public
  -      StringBuffer format(Date date, StringBuffer sbuf,
  -                          FieldPosition fieldPosition) {
  -
  +  public StringBuffer format(
  +    Date date, StringBuffer sbuf, FieldPosition fieldPosition) {
       if (millisecondStart == UNRECOGNIZED_MILLISECOND_PATTERN) {
         return formatter.format(date, sbuf, fieldPosition);
       }
       long now = date.getTime();
  -    if (now < previousTime + 1000L && now >= previousTime) {
  +    if ((now < (slotBegin + 1000L)) && (now >= slotBegin)) {
         if (millisecondStart >= 0) {
  -        cache.delete(millisecondStart, millisecondStart + 3);
  -        int millis = (int) (now - previousTime);
  +        int millis = (int) (now - slotBegin);
           int cacheLength = cache.length();
  -        //
  -        //   append milliseconds to the end of the cache
  -        numberFormat.format(millis, cache, fieldPosition);
  -        int milliLength = cache.length() - cacheLength;
  -        //
  -        //   if it didn't belong at the end, then move it
  -        if (cacheLength != millisecondStart) {
  -          String milli = cache.substring(cacheLength);
  -          cache.setLength(cacheLength);
  -          cache.insert(millisecondStart, milli);
  -        }
  -        for (int i = milliLength; i < 3; i++) {
  -          cache.insert(millisecondStart, "0");
  +
  +        milliBuf.setLength(0);
  +        numberFormat.format(millis, milliBuf, fieldPosition);
  +        for(int j = 0; j < milliDigits; j++) {
  +          cache.setCharAt(millisecondStart+j, milliBuf.charAt(j));
           }
         }
         sbuf.append(cache);
       } else {
  -      previousTime = (now / 1000L) * 1000L;
  +      slotBegin = (now / 1000L) * 1000L;
         //
         //   if earlier than 1970 and rounded toward 1970
         //      then move back one second
  -      if (now - previousTime < 0) {
  -        previousTime -= 1000;
  +      if ((now - slotBegin) < 0) {
  +        slotBegin -= 1000;
         }
         cache.setLength(0);
  -      formatter.format(new Date(previousTime), cache, fieldPosition);
  -      millisecondStart = findMillisecondStart(previousTime, 
cache.toString(), formatter);
  +      formatter.format(new Date(slotBegin), cache, fieldPosition);
  +      millisecondStart =
  +        findMillisecondStart(slotBegin, cache.toString(), formatter);
         //
         //  calling ourself should be safe and faster
         //     but why risk it
  @@ -148,7 +173,6 @@
       return sbuf;
     }
   
  -
     /**
      * Set timezone.
      *
  @@ -160,18 +184,16 @@
       formatter.setTimeZone(timeZone);
       int prevLength = cache.length();
       cache.setLength(0);
  -    cache.append(formatter.format(new Date(previousTime)));
  -    millisecondStart = findMillisecondStart(previousTime,
  -                                              cache.toString(),
  -                                              formatter);
  +    cache.append(formatter.format(new Date(slotBegin)));
  +    millisecondStart =
  +      findMillisecondStart(slotBegin, cache.toString(), formatter);
     }
   
     /**
        This method is delegated to the formatter which most
        likely returns null.
      */
  -  public
  -      Date parse(String s, ParsePosition pos) {
  +  public Date parse(String s, ParsePosition pos) {
       return formatter.parse(s, pos);
     }
   
  
  
  
  1.2       +23 -14    
logging-log4j/tests/src/java/org/apache/log4j/pattern/CachedDateFormatTest.java
  
  Index: CachedDateFormatTest.java
  ===================================================================
  RCS file: 
/home/cvs/logging-log4j/tests/src/java/org/apache/log4j/pattern/CachedDateFormatTest.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- CachedDateFormatTest.java 23 Dec 2004 12:16:22 -0000      1.1
  +++ CachedDateFormatTest.java 23 Dec 2004 14:07:58 -0000      1.2
  @@ -76,7 +76,8 @@
       //   subsequent calls within one minute
       //     are optimized to reuse previous formatted value
       //     make a couple of nearly spaced calls
  -    DateFormat gmtFormat = new CachedDateFormat(new 
AbsoluteTimeDateFormat(GMT));
  +    DateFormat gmtFormat = new 
CachedDateFormat(AbsoluteTimeDateFormat.ABS_TIME_DATE_PATTERN);
  +    gmtFormat.setTimeZone(GMT);
       long ticks = 12601L * 86400000L;
       Date jul1 = new Date(ticks);
       assertEquals("00:00:00,000", gmtFormat.format(jul1));
  @@ -96,8 +97,10 @@
   
     public void test2() {
         Date jul2 = new Date(12602L * 86400000L);
  -      DateFormat gmtFormat = new CachedDateFormat(new 
AbsoluteTimeDateFormat(GMT));
  -      DateFormat chicagoFormat = new CachedDateFormat(new 
AbsoluteTimeDateFormat(CHICAGO));
  +      DateFormat gmtFormat = new 
CachedDateFormat(AbsoluteTimeDateFormat.ABS_TIME_DATE_PATTERN);
  +      gmtFormat.setTimeZone(GMT);
  +      DateFormat chicagoFormat = new 
CachedDateFormat(AbsoluteTimeDateFormat.ABS_TIME_DATE_PATTERN);
  +      chicagoFormat.setTimeZone(CHICAGO);
         assertEquals("00:00:00,000", gmtFormat.format(jul2));
         assertEquals("19:00:00,000", chicagoFormat.format(jul2));
         assertEquals("00:00:00,000", gmtFormat.format(jul2));
  @@ -110,8 +113,8 @@
       //   subsequent calls within one minute
       //     are optimized to reuse previous formatted value
       //     make a couple of nearly spaced calls
  -    DateFormat gmtFormat = new CachedDateFormat(
  -       new AbsoluteTimeDateFormat(GMT));
  +    DateFormat gmtFormat = new 
CachedDateFormat(AbsoluteTimeDateFormat.ABS_TIME_DATE_PATTERN);
  +    gmtFormat.setTimeZone(GMT);
       long ticks = -7L * 86400000L;
       Date jul1 = new Date(ticks);
       assertEquals("00:00:00,000", gmtFormat.format(jul1));
  @@ -130,8 +133,10 @@
       //     are optimized to reuse previous formatted value
       //     make a couple of nearly spaced calls
       SimpleDateFormat baseFormat =
  -         new SimpleDateFormat("EEE, MMM dd, HH:mm:ss.SSS Z", Locale.ENGLISH);
  -    DateFormat cachedFormat = new CachedDateFormat(baseFormat);
  +         new SimpleDateFormat("EEE, MMM dd, HH:mm:ss.SSS Z");
  +    //     new SimpleDateFormat("EEE, MMM dd, HH:mm:ss.SSS Z", 
Locale.ENGLISH);
  +
  +    DateFormat cachedFormat = new CachedDateFormat("EEE, MMM dd, 
HH:mm:ss.SSS Z");
       //
       //   use a date in 2000 to attempt to confuse the millisecond locator
       long ticks = 11141L * 86400000L;
  @@ -154,9 +159,10 @@
       //     are optimized to reuse previous formatted value
       //     make a couple of nearly spaced calls
       Locale thai = new Locale("th");
  +    String pattern = "EEE, MMM dd, HH:mm:ss.SSS Z";
       SimpleDateFormat baseFormat =
            new SimpleDateFormat("EEE, MMM dd, HH:mm:ss.SSS Z", thai);
  -    DateFormat cachedFormat = new CachedDateFormat(baseFormat);
  +    DateFormat cachedFormat = new CachedDateFormat(pattern, thai);
       //
       //   use a date in 2000 to attempt to confuse the millisecond locator
       long ticks = 11141L * 86400000L;
  @@ -176,7 +182,7 @@
      * Checks that getNumberFormat does not return null.
      */
     public void test6() {
  -    assertNotNull(new CachedDateFormat(new 
SimpleDateFormat()).getNumberFormat());
  +    assertNotNull(new SimpleDateFormat().getNumberFormat());
     }
   
     /**
  @@ -203,8 +209,9 @@
      * Set time zone on cached and check that it is effective.
      */
     public void test8() {
  -    DateFormat baseFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");
  -    DateFormat cachedFormat = new CachedDateFormat(baseFormat);
  +    String pattern = "yyyy-MM-dd HH:mm:ss,SSS";
  +    DateFormat baseFormat = new SimpleDateFormat(pattern);
  +    DateFormat cachedFormat = new CachedDateFormat(pattern);
       cachedFormat.setTimeZone(TimeZone.getTimeZone("GMT-6"));
       Date jul4 = new Date(12603L * 86400000L);
       assertEquals("2004-07-03 18:00:00,000", cachedFormat.format(jul4));
  @@ -215,8 +222,9 @@
      * Test of caching when less than three millisecond digits are specified.
      */
     public void test9() {
  -    DateFormat baseFormat = new SimpleDateFormat("yyyy-MMMM-dd HH:mm:ss,SS 
Z", Locale.US);
  -    DateFormat cachedFormat = new CachedDateFormat(baseFormat);
  +    String pattern = "yyyy-MMMM-dd HH:mm:ss,SS Z";
  +    DateFormat baseFormat = new SimpleDateFormat(pattern, Locale.US);
  +    DateFormat cachedFormat = new CachedDateFormat(pattern);
       TimeZone cet = TimeZone.getTimeZone("GMT+1");
       cachedFormat.setTimeZone(cet);
       
  @@ -242,8 +250,9 @@
      * Test when millisecond position moves but length remains constant.
      */
     public void test10() {
  +    String pattern = "MMMM SSS EEEEEE";
       DateFormat baseFormat = new SimpleDateFormat("MMMM SSS EEEEEE", 
Locale.US);
  -    DateFormat cachedFormat = new CachedDateFormat(baseFormat);
  +    DateFormat cachedFormat = new CachedDateFormat(pattern);
       TimeZone cet = TimeZone.getTimeZone("GMT+1");
       cachedFormat.setTimeZone(cet);
       
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to