Im trying to build an application with recurring events. In my database i have a table recurring_pattern:
type_name sepereation_count day_of_week week_of_month day_of_month month_of_year
daily 0 NULL NULL NULL NULL
weekly 0 2 NULL NULL NULL
monthly 0 1 3 NULL NULL
monthly2 1 NULL NULL 10 NULL
yearly 0 NULL NULL 20 5
seperation_count: if an event needs to be configured for every other week/month/etc., then seperation_count would be 1
day_of_week: 1 = Monday; 2 = Tuesday etc.
And i have a table recurring_events:
id start_date last_occurence recurring_pattern_name
1 2019-10-01 2019-12-03 daily
2 2019-10-01 2019-12-03 weekly
3 2019-10-01 2019-11-18 monthly
4 2019-11-01 NULL monthly2
5 2019-01-01 2019-05-20 yearly
The next dates of the events should be:
1 = 2019-12-04 because of every day
2 = 2019-12-10 because every week on Tuesday (Week starts here at monday)
3 = 2019-12-16 because every 3. week on monday
4 = 2019-12-10 because on every second month on 10.
5 = 2020-05-20 because every year, month 5 and day 20
Now i am trying to find the next dates in Java but i have no idea how i could do it.
For the daily event i have
nextDate = lastPaid == null ? startDate : lastPaid;
nextDate = nextDate.plusDays(1 + recurringPattern.getSepereationCount());
But how do i get next dates for the weekly, monthly, monthly2 and yearly event?
For the weekly scheme
int separationCount = 0;
LocalDate start = LocalDate.parse("2019-10-01");
int dowNumber = 2;
DayOfWeek dow = DayOfWeek.of(dowNumber);
LocalDate first = start.with(TemporalAdjusters.nextOrSame(dow));
System.out.println("first: " + first);
LocalDate next = first.plusWeeks(1 + separationCount);
System.out.println("next: " + next);
Output from this demo snippet is:
first: 2019-10-01 next: 2019-10-08
Monthly scheme
LocalDate start = LocalDate.parse("2019-10-01");
int dowNumber = 1;
int weekOfMonth = 3;
DayOfWeek dow = DayOfWeek.of(dowNumber);
LocalDate first = start.with(WeekFields.ISO.weekOfMonth(), weekOfMonth)
.with(dow);
if (first.isBefore(start)) {
// Use next month instead
first = start.plusMonths(1)
.with(WeekFields.ISO.weekOfMonth(), weekOfMonth)
.with(dow);
}
System.out.println("first: " + first);
first: 2019-10-14
You can make the calculation of the following dates in a similar fashion.
Monthly2 scheme
This one is pretty trivial. Use LocalDate.withDayOfMonth()
and LocalDate.plusMonths()
. Remember to check whether the first date that you calculate is before the start date in the same way as above. And remember that day 29, 30 or 31 will not work with every month.
Yearly scheme
I am leaving this one to you. Find what you need in the documentation of LocalDate
.