Search code examples
javadateeventsdate-manipulation

Calculating next date for events


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?

I used this as a template


Solution

  • 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.

    Documentation links