[ 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