[ 
https://issues.apache.org/jira/browse/LOG4J2-385?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13887524#comment-13887524
 ] 

Remko Popma commented on LOG4J2-385:
------------------------------------

After checking the behaviour of Log4J-1.2 and Logback there seem to be a few 
bugs in the current {{PatternProcessor.getNextTime()}} logic.

Current {{PatternProcessor.getNextTime()}} results (dates in {{yyyy/MM/dd}} 
format):
# Monthly rollover from 2014/01/31 gives 2014/02/01
# Monthly rollover from 2014/10/15 gives 2014/{color:red}02/01{color} *<-- BUG*
# Weekly rollover from 2014/03/4 Tue gives 2014/{color:red}01/08 Wed{color} 
*<-- BUG*
# Hourly rollover from 2014/03/04 10:31 gives 2014/03/04 11:00 when run in the 
morning
# Hourly rollover from 2014/03/04 10:31 gives 2014/03/04 
{color:red}23{color}:00 when run in the afternoon *<-- BUG*
# Minutely rollover from 2014/03/04 10:31 gives 2014/03/04 
{color:red}22{color}:00 when run in the afternoon *<-- BUG*

The following patch fixes the above issues:
{code}
Index: 
src/main/java/org/apache/logging/log4j/core/appender/rolling/PatternProcessor.java
===================================================================
--- 
src/main/java/org/apache/logging/log4j/core/appender/rolling/PatternProcessor.java
  (revision 1563035)
+++ 
src/main/java/org/apache/logging/log4j/core/appender/rolling/PatternProcessor.java
  (working copy)
@@ -102,6 +102,7 @@
             nextFileTime = cal.getTimeInMillis();
             return nextTime;
         }
+        cal.set(Calendar.MONTH, currentCal.get(Calendar.MONTH));
         if (frequency == RolloverFrequency.MONTHLY) {
             increment(cal, Calendar.MONTH, increment, modulus);
             nextTime = cal.getTimeInMillis();
@@ -110,7 +111,9 @@
             return nextTime;
         }
         if (frequency == RolloverFrequency.WEEKLY) {
+            cal.set(Calendar.WEEK_OF_YEAR, 
currentCal.get(Calendar.WEEK_OF_YEAR));
             increment(cal, Calendar.WEEK_OF_YEAR, increment, modulus);
+            cal.set(Calendar.DAY_OF_WEEK, currentCal.getFirstDayOfWeek());
             nextTime = cal.getTimeInMillis();
             cal.add(Calendar.WEEK_OF_YEAR, -1);
             nextFileTime = cal.getTimeInMillis();
@@ -124,11 +127,11 @@
             nextFileTime = cal.getTimeInMillis();
             return nextTime;
         }
-        cal.set(Calendar.HOUR, currentCal.get(Calendar.HOUR));
+        cal.set(Calendar.HOUR_OF_DAY, currentCal.get(Calendar.HOUR_OF_DAY));
         if (frequency == RolloverFrequency.HOURLY) {
-            increment(cal, Calendar.HOUR, increment, modulus);
+            increment(cal, Calendar.HOUR_OF_DAY, increment, modulus);
             nextTime = cal.getTimeInMillis();
-            cal.add(Calendar.HOUR, -1);
+            cal.add(Calendar.HOUR_OF_DAY, -1);
             nextFileTime = cal.getTimeInMillis();
             return nextTime;
         }
{code}

Updated JUnit tests:
{code}
    private String format(long time) {
        String actualStr = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS")
                .format(new Date(time));
        return actualStr;
    }

    @Test
    public void testGetNextTimeMonthlyReturnsFirstDayOfNextMonth() {
        PatternProcessor pp = new PatternProcessor(
                "logs/app-%d{yyyy-MM}.log.gz");
        Calendar initial = Calendar.getInstance();
        initial.set(2014, 9, 15, 10, 31, 59); // Oct 15th
        long actual = pp.getNextTime(initial.getTimeInMillis(), 1, false);

        // We expect 1st day of next month
        Calendar expected = Calendar.getInstance();
        expected.set(2014, 10, 1, 0, 0, 00);
        expected.set(Calendar.MILLISECOND, 0);
        assertEquals(format(expected.getTimeInMillis()), format(actual));
    }

    @Test
    public void testGetNextTimeMonthlyReturnsFirstDayOfNextMonth2() {
        PatternProcessor pp = new PatternProcessor(
                "logs/app-%d{yyyy-MM}.log.gz");
        Calendar initial = Calendar.getInstance();
        initial.set(2014, 0, 31, 10, 31, 59); // 2014 Jan 31st
        long actual = pp.getNextTime(initial.getTimeInMillis(), 1, false);

        // Expect 1st of next month: 2014 Feb 1st
        Calendar expected = Calendar.getInstance();
        expected.set(2014, 1, 1, 0, 0, 00);
        expected.set(Calendar.MILLISECOND, 0);
        assertEquals(format(expected.getTimeInMillis()), format(actual));
    }

    @Test
    public void testGetNextTimeWeeklyReturnsFirstDayOfNextWeek_US() {
        Locale old = Locale.getDefault();
        Locale.setDefault(Locale.US); // force 1st day to be Sunday

        try {
            PatternProcessor pp = new PatternProcessor(
                    "logs/app-%d{yyyy-MM-W}.log.gz");
            Calendar initial = Calendar.getInstance();
            initial.set(2014, 2, 4, 10, 31, 59); // Tue, March 4, 2014
            long actual = pp.getNextTime(initial.getTimeInMillis(), 1, false);

            // expect Sun, March 9, 2014
            Calendar expected = Calendar.getInstance();
            expected.set(2014, 2, 9, 0, 0, 00);
            expected.set(Calendar.MILLISECOND, 0);
            assertEquals(format(expected.getTimeInMillis()), format(actual));
        } finally {
            Locale.setDefault(old);
        }
    }

    @Test
    public void testGetNextTimeWeeklyReturnsFirstDayOfNextWeek_FRANCE() {
        Locale old = Locale.getDefault();
        Locale.setDefault(Locale.FRANCE); // force 1st day to be Monday

        try {
            PatternProcessor pp = new PatternProcessor(
                    "logs/app-%d{yyyy-MM-W}.log.gz");
            Calendar initial = Calendar.getInstance();
            initial.set(2014, 2, 4, 10, 31, 59); // Tue, March 4, 2014
            long actual = pp.getNextTime(initial.getTimeInMillis(), 1, false);

            // expect Monday, March 10, 2014
            Calendar expected = Calendar.getInstance();
            expected.set(2014, 2, 10, 0, 0, 00);
            expected.set(Calendar.MILLISECOND, 0);
            assertEquals(format(expected.getTimeInMillis()), format(actual));
        } finally {
            Locale.setDefault(old);
        }
    }

    @Test
    public void testGetNextTimeHourlyReturnsFirstMinuteOfNextHour() {
        PatternProcessor pp = new PatternProcessor(
                "logs/app-%d{yyyy-MM-dd-HH}.log.gz");
        Calendar initial = Calendar.getInstance();
        initial.set(2014, 2, 4, 10, 31, 59); // Tue, March 4, 2014, 10:31
        long actual = pp.getNextTime(initial.getTimeInMillis(), 1, false);

        // expect Wed, March 4, 2014, 11:00
        Calendar expected = Calendar.getInstance();
        expected.set(2014, 2, 4, 11, 00, 00);
        expected.set(Calendar.MILLISECOND, 0);
        assertEquals(format(expected.getTimeInMillis()), format(actual));
    }

    @Test
    public void testGetNextTimeMinutelyReturnsFirstSecondOfNextMinute() {
        PatternProcessor pp = new PatternProcessor(
                "logs/app-%d{yyyy-MM-dd-HH-mm}.log.gz");
        Calendar initial = Calendar.getInstance();
        initial.set(2014, 2, 4, 10, 31, 59); // Tue, March 4, 2014, 10:31
        initial.set(Calendar.MILLISECOND, 0);
        assertEquals("2014/03/04 10:31:59.000", 
format(initial.getTimeInMillis()));
        long actual = pp.getNextTime(initial.getTimeInMillis(), 1, false);

        // expect Tue, March 4, 2014, 10:32
        Calendar expected = Calendar.getInstance();
        expected.set(2014, 2, 4, 10, 32, 00);
        expected.set(Calendar.MILLISECOND, 0);
        assertEquals(format(expected.getTimeInMillis()), format(actual));
    }
{code}

> Unable to roll log files monthly
> --------------------------------
>
>                 Key: LOG4J2-385
>                 URL: https://issues.apache.org/jira/browse/LOG4J2-385
>             Project: Log4j 2
>          Issue Type: Bug
>          Components: Appenders
>    Affects Versions: 2.0-beta8
>         Environment: Java 1.7.0_25, Windows 7 64bit, IntelliJ IDEA 12 Ultimate
>            Reporter: Ace Funk
>            Assignee: Remko Popma
>         Attachments: LOG4J2-385.patch
>
>
> Attempting to use FastRollingFile appender and configure log file rollover to 
> occur monthly.  When {{filePattern="logs/app-%d\{yyyy-MM}.log.gz"}} is used, 
> at application startup an archive file is created immediately 
> (app-2013-01.log.gz) even if no log previously existed.  A log file is 
> created, but only a single entry is made into the log.



--
This message was sent by Atlassian JIRA
(v6.1.5#6160)

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscr...@logging.apache.org
For additional commands, e-mail: log4j-dev-h...@logging.apache.org

Reply via email to