On Oct 20, 2008, at 1:39 PM, Peter Steele wrote:

If you are changing from 8:00 AM PDT to 8:00 AM EDT, you are not just
changing the time zone, but you are also changing the time.

Yes, that's correct, both the time zone and time are being set in one
operation.

Are you changing the timezone using a operating system utility
(control panel etc) or by using a call to TimeZone.setDefault()?

We are using TimeZone.setDefault(). The user sets the time and time zone
in our
GUI and hits an Apply button to invoke the change.

Different JVM's may have different approaches to how a change in the
operating system timezone becomes visible in the JDK. If the JDK only

checks the default timezone at start up, there is nothing log4j can
do.  Knowing the vendor and version of the OS and JVM in use and the
exact method of making the timezone change would be helpful to
understand your observed behavior. It does appear that you are seeing

an immediate effect from changing the time, but the timezone is not
immediately updated in the app by the manner you are making the change.

We are using JDK 1.5 on FreeBSD 7.0. The code we execute does take
immediate effect
on the system itself as far as the local time is concerned, e.g., the
date command
shows the same date/time/time zone as the user sets in the GUI. The
logger timestamps
however still show the time in the original time zone.

I'd suggest using the EnhancedPatternLayout in the extras companion
and output the time in a fixed timezone.  Something like:

%d{yyyy-MM-dd HH:mm:ss}{UTC}Z - %c - %m%n

You could also output the time in local time for convenience, but
you'd always have the time in a known timezone.

I will check this out but I'm not sure if it will solve the problem.
Ideally, when we
change the time from say 8:00 PDT to 8:00 EDT, we'd like the log
timestamps to also
show 8:00, but what we get is 5:00, at least until we restart the
application. We could
add the explicit time zone but will it just end up showing 5:00 EDT
instead of 8:00 EDT?
Is there a log4j function we could call to force it to resync with the
current local time,
similar to what it must be doing when an application starts?




When the PatternLayout is created during configuration, an instance of java.text.SimpleDateFormat (or a log4j-provided DateFormat if you specify %d{ISO8601} or similar) and this format is used for the lifetime of PatternLayout. java.text.SimpleDateFormat apparently caches the default timezone at the time of creation (at least in your JDK's implementation) and does not monitor any subsequent changes.

Date formatting can be a time consuming part of logging. log4j 1.2 has a decent amount code (problematic code though) to cache the results of previous format requests for potential reuse. The caching and design is much cleaner in the EnhancedPatternLayout in the extras companion. The following patch to the extras companion should allow an %d pattern in an EnhancedPatternLayout without a explicit timezone to follow changes to the default timezone without an undue performance hit. The timezone should be updated at most once a second, since CachedDateFormat should handle the more frequent calls. I've run the standard unit tests against it and it didn't break anything, but I haven't attempted to test it while changing the system timezone.

I'd appreciate your feedback. If the works for you, we could consider this for the next release of the extras companion.


Index: src/main/java/org/apache/log4j/pattern/DatePatternConverter.java
===================================================================
--- src/main/java/org/apache/log4j/pattern/DatePatternConverter.java (revision 702979) +++ src/main/java/org/apache/log4j/pattern/DatePatternConverter.java (working copy)
@@ -21,6 +21,9 @@
 import org.apache.log4j.spi.LoggingEvent;

 import java.text.SimpleDateFormat;
+import java.text.DateFormat;
+import java.text.FieldPosition;
+import java.text.ParsePosition;
 import java.util.Date;
 import java.util.TimeZone;

@@ -63,6 +66,41 @@
    */
   private final CachedDateFormat df;

+    /**
+     * This class wraps a DateFormat and forces the time zone to the
+     *   default time zone before each format and parse request.
+     */
+  private class DefaultZoneDateFormat extends DateFormat {
+        /**
+         * Wrapped instance of DateFormat.
+         */
+    private final DateFormat dateFormat;
+
+        /**
+         * Construct new instance.
+         * @param format format, may not be null.
+         */
+    public DefaultZoneDateFormat(final DateFormat format) {
+        dateFormat = format;
+    }
+
+        /**
+         * @{inheritDoc}
+         */
+ public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
+        dateFormat.setTimeZone(TimeZone.getDefault());
+        return dateFormat.format(date, toAppendTo, fieldPosition);
+    }
+
+        /**
+         * @{inheritDoc}
+         */
+    public Date parse(String source, ParsePosition pos) {
+        dateFormat.setTimeZone(TimeZone.getDefault());
+        return dateFormat.parse(source, pos);
+    }
+  }
+
   /**
    * Private constructor.
    * @param options options, may be null.
@@ -95,7 +133,7 @@
     }

     int maximumCacheValidity = 1000;
-    SimpleDateFormat simpleFormat = null;
+    DateFormat simpleFormat = null;

     try {
       simpleFormat = new SimpleDateFormat(pattern);
@@ -113,6 +151,8 @@
     if ((options != null) && (options.length > 1)) {
       TimeZone tz = TimeZone.getTimeZone((String) options[1]);
       simpleFormat.setTimeZone(tz);
+    } else {
+      simpleFormat = new DefaultZoneDateFormat(simpleFormat);
     }

     df = new CachedDateFormat(simpleFormat, maximumCacheValidity);



as it is and there is a fair bit of logic (much better in the EnhancedPatternLayout in extras than in log4j) to cache previous formatted results and reuse them

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

Reply via email to