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]