-
Notifications
You must be signed in to change notification settings - Fork 187
Reimplementation of RFC5545 Schedule #1071
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
375e1b4
reimplementation of the rfc5545 schedule
ssalinas 27f1892
checkForValid not isValid
ssalinas 0a42866
no need to limit with presence of max iterations
ssalinas 83a47ee
don't need this test anymore
ssalinas 2cc94fb
simplify bad schedule check
ssalinas 2a69772
better handling of dtstart for more efficient loops
ssalinas File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,6 @@ | |
|
|
||
| public enum ScheduleType { | ||
|
|
||
| CRON, QUARTZ; | ||
| CRON, QUARTZ, RFC5545; | ||
|
|
||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
SingularityService/src/main/java/com/hubspot/singularity/helpers/RFC5545Schedule.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| package com.hubspot.singularity.helpers; | ||
|
|
||
| import java.util.Date; | ||
| import java.util.regex.Matcher; | ||
| import java.util.regex.Pattern; | ||
|
|
||
| import org.dmfs.rfc5545.recur.InvalidRecurrenceRuleException; | ||
| import org.dmfs.rfc5545.recur.RecurrenceRule; | ||
| import org.dmfs.rfc5545.DateTime; | ||
| import org.dmfs.rfc5545.recur.RecurrenceRule.Part; | ||
| import org.dmfs.rfc5545.recur.RecurrenceRuleIterator; | ||
| import org.joda.time.format.DateTimeFormat; | ||
| import org.joda.time.format.DateTimeFormatter; | ||
|
|
||
| public class RFC5545Schedule { | ||
| public static final int MAX_ITERATIONS = 10000; | ||
| private final RecurrenceRule recurrenceRule; | ||
| private final org.joda.time.DateTime dtStart; | ||
|
|
||
| public RFC5545Schedule(String schedule) throws InvalidRecurrenceRuleException { | ||
| // DTSTART is RFC5545 but NOT in the recur string, but its a nice to have? :) | ||
| Pattern pattern = Pattern.compile("DTSTART=([0-9]{8}T[0-9]{6})"); | ||
| Matcher matcher = pattern.matcher(schedule); | ||
|
|
||
| if (matcher.find()) { | ||
| DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyyMMdd'T'HHmmss"); | ||
| if (schedule.contains("REPEAT") || schedule.contains("COUNT")) { | ||
| this.dtStart = formatter.parseDateTime(matcher.group(1)); | ||
| } else { | ||
| org.joda.time.DateTime start = formatter.parseDateTime(matcher.group(1)); | ||
| org.joda.time.DateTime now = org.joda.time.DateTime.now().withSecondOfMinute(0); | ||
| if (now.getMillis() > start.getMillis()) { | ||
| start = now; | ||
| } | ||
| this.dtStart = start; | ||
| } | ||
| this.recurrenceRule = new RecurrenceRule(matcher.replaceAll("").replace("RRULE:", "")); | ||
| } else { | ||
| this.recurrenceRule = new RecurrenceRule(schedule); | ||
| this.dtStart = org.joda.time.DateTime.now().withSecondOfMinute(0); | ||
| } | ||
| } | ||
|
|
||
| public org.joda.time.DateTime getStartDateTime() { | ||
| return dtStart; | ||
| } | ||
|
|
||
| public Date getNextValidTime() { | ||
| final long now = System.currentTimeMillis(); | ||
| DateTime startDateTime = new DateTime(dtStart.getYear(), (dtStart.getMonthOfYear() - 1), dtStart.getDayOfMonth(), | ||
| dtStart.getHourOfDay(), dtStart.getMinuteOfHour(), dtStart.getSecondOfMinute()); | ||
| RecurrenceRuleIterator timeIterator = recurrenceRule.iterator(startDateTime); | ||
|
|
||
| int count = 0; | ||
| while (timeIterator.hasNext() && (count < MAX_ITERATIONS || (recurrenceRule.hasPart(Part.COUNT) && count < recurrenceRule.getCount()))) { | ||
| count ++; | ||
| long nextRunAtTimestamp = timeIterator.nextMillis(); | ||
| if (nextRunAtTimestamp >= now) { | ||
| return new Date(nextRunAtTimestamp); | ||
| } | ||
| } | ||
| return null; | ||
| } | ||
|
|
||
| public RecurrenceRule getRecurrenceRule() { | ||
| return recurrenceRule; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
SingularityService/src/test/java/com/hubspot/singularity/helpers/RFC5545ScheduleTest.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| package com.hubspot.singularity.helpers; | ||
|
|
||
| import java.util.Date; | ||
| import java.util.concurrent.TimeUnit; | ||
|
|
||
| import org.dmfs.rfc5545.DateTime; | ||
| import org.junit.Assert; | ||
| import org.junit.Test; | ||
|
|
||
| public class RFC5545ScheduleTest { | ||
| @Test | ||
| public void testEveryWeekdayRFC5545Schdule() throws Exception { | ||
| String schedule = "FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR"; | ||
| Date nextValidTime = new RFC5545Schedule(schedule).getNextValidTime(); | ||
| Assert.assertTrue(nextValidTime.after(new Date())); | ||
| Assert.assertTrue(nextValidTime.before(new Date(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(3)))); | ||
| } | ||
|
|
||
| @Test | ||
| public void testMaxIterations() throws Exception { | ||
| String schedule = "DTSTART=19970902T090000\nRRULE:FREQ=HOURLY;COUNT=10001"; | ||
| Assert.assertEquals(new RFC5545Schedule(schedule).getStartDateTime(), new org.joda.time.DateTime(1997, 9, 2, 9, 0, 0)); | ||
| Assert.assertEquals(new RFC5545Schedule(schedule).getNextValidTime(), null); | ||
| } | ||
|
|
||
| @Test | ||
| public void testRecurInPastDoesNotGiveNext() throws Exception { | ||
| String schedule = "FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,5,6,7,8;COUNT=1"; | ||
| Assert.assertEquals(new RFC5545Schedule(schedule).getNextValidTime(), null); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you could simplify this by just calling
badRequest()in the catch blockThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed