Skip to content

Commit

Permalink
CronTab.floor / .ceil should return times at minute granularity (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
krisstern authored Feb 9, 2025
2 parents f5bbd10 + 832ba1d commit 1e89d00
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 0 deletions.
7 changes: 7 additions & 0 deletions core/src/main/java/hudson/scheduler/CronTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,11 @@ public Calendar ceil(long t) {
* (e.g. Jun 31) date, or at least a date too rare to be useful. This addresses JENKINS-41864 and was added in 2.49
*/
public Calendar ceil(Calendar cal) {
if (cal.get(Calendar.SECOND) > 0 || cal.get(Calendar.MILLISECOND) > 0) {
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
cal.add(Calendar.MINUTE, 1);
}
Calendar twoYearsFuture = (Calendar) cal.clone();
twoYearsFuture.add(Calendar.YEAR, 2);
OUTER:
Expand Down Expand Up @@ -440,6 +445,8 @@ public Calendar floor(long t) {
* (e.g. Jun 31) date, or at least a date too rare to be useful. This addresses JENKINS-41864 and was added in 2.49
*/
public Calendar floor(Calendar cal) {
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
Calendar twoYearsAgo = (Calendar) cal.clone();
twoYearsAgo.add(Calendar.YEAR, -2);

Expand Down
22 changes: 22 additions & 0 deletions core/src/test/java/hudson/scheduler/CronTabTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,22 @@
import static java.util.Calendar.MONDAY;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;

import antlr.ANTLRException;
import java.text.DateFormat;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;
import java.util.function.Function;
import org.junit.Test;
import org.jvnet.hudson.test.Issue;

Expand Down Expand Up @@ -340,6 +344,24 @@ public int next(int n) {
assertEquals("[35, 56]", times.toString());
}

@Test public void floorCeilMinuteGranularity() throws Exception {
var tab = new CronTab("*/5 * * * *");
assertFloorCeil(tab, new GregorianCalendar(2025, 2, 4, 14, 15, 23), "2025-03-04T14:15:00", "2025-03-04T14:20:00");
assertFloorCeil(tab, new GregorianCalendar(2025, 2, 4, 14, 19, 23), "2025-03-04T14:15:00", "2025-03-04T14:20:00");
assertFloorCeil(tab, new GregorianCalendar(2025, 2, 4, 14, 16, 0), "2025-03-04T14:15:00", "2025-03-04T14:20:00");
assertFloorCeil(tab, new GregorianCalendar(2025, 2, 4, 14, 19, 0), "2025-03-04T14:15:00", "2025-03-04T14:20:00");
assertFloorCeil(tab, new GregorianCalendar(2025, 2, 4, 14, 15, 0), "2025-03-04T14:15:00", "2025-03-04T14:15:00");
}

private static void assertFloorCeil(CronTab tab, Calendar now, String expectedFloor, String expectedCeil) {
Function<Calendar, String> fmt = c -> ZonedDateTime.ofInstant(c.toInstant(), c.getTimeZone().toZoneId()).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
var nowFormatted = fmt.apply(now);
var nowClone = (Calendar) now.clone();
assertThat("floor of " + nowFormatted, fmt.apply(tab.floor(nowClone)), is(expectedFloor));
nowClone = (Calendar) now.clone();
assertThat("ceil of " + nowFormatted, fmt.apply(tab.ceil(nowClone)), is(expectedCeil));
}

@Issue("SECURITY-790")
@Test(timeout = 1000L) public void testLongMonths() throws Exception {
Calendar cal = Calendar.getInstance();
Expand Down

0 comments on commit 1e89d00

Please sign in to comment.