I need to be able manage dates in flexible way for calculating monthly events.
If I use
SimpleDateFormat sdf = new SimpleDateFormat("dd-M-yyyy hh:mm:ss");
Calendar calendar = Calendar.getInstance();
calendar.set(2017, Calendar.AUGUST, 31, 9, 30, 15);
Calendar next = calendar;
for (int i = 1; i++<10;) {
next = (Calendar) calendar.clone();
next.add(Calendar.MONTH, i);
System.out.println(sdf.format(next.getTime()));
}
in result you can see
31-10-2017 09:30:15
30-11-2017 09:30:15
31-12-2017 09:30:15
31-1-2018 09:30:15
28-2-2018 09:30:15
31-3-2018 09:30:15
30-4-2018 09:30:15
31-5-2018 09:30:15
30-6-2018 09:30:15
It seems following month semantic if we add one moth to date we should get next month (it's correct), but following occurrence semantic it has an issue, because of acceptance is to get same date day but in next month (as you can see it is not same sometimes. There are 31
, 30
, 28
). If there is no same date, we should null
for example.
Does java provides ability calculate months following occurrence semantic strategy to handle my issue?
More explanation examples.
I DO NOT NEED LAST MONTH DAY I need occurrences only from first explanation for 31th month day. I simplified question as it was possible.
I can do workarounds with calendar
but I expected more elegant solution.
If you use ical4j to calculate occurrences, you'll get this result. And occurrences calculation should be fixed (it's a bug because of rfc5545).
import net.fortuna.ical4j.model.*
import net.fortuna.ical4j.model.component.VEvent
void testCalculateRecurrenceSetOn31th() {
VEvent event = new ContentBuilder().vevent {
dtstart('20100831T061500Z', parameters: parameters() {
value('DATETIME')})
dtend('20100831T064500Z', parameters: parameters() {
value('DATETIME')})
rrule('FREQ=MONTHLY;UNTIL=20110101')
}
def dates = event.calculateRecurrenceSet(new Period('20100831T000000/20110131T000000'))
def expected = new PeriodList(true)
expected.add new Period('20100831T061500Z/PT30M')
expected.add new Period('20101031T061500Z/PT30M')
expected.add new Period('20101231T061500Z/PT30M')
println dates
assert dates == expected
/*
Assertion failed:
assert dates == expected
| | |
| | [20100831T061500Z/PT30M, 20101031T061500Z/PT30M, 20101231T061500Z/PT30M]
| false
[20100831T061500Z/PT30M, 20100930T061500Z/PT30M, 20101030T061500Z/PT30M, 20101130T061500Z/PT30M, 20101230T061500Z/PT30M]
*/
}
but if I use same library with small change:
rrule('FREQ=MONTHLY;UNTIL=20110101')
-->
rrule('FREQ=MONTHLY;UNTIL=20110101;BYMONTHDAY=31')
it is calculated than correctly. But I need same calculation for both cases because of rfc5545.
The root issue in the ical4j is in Recur.java
:
private void increment(final Calendar cal) {
final int calInterval = (getInterval() >= 1) ? getInterval() : 1;
cal.add(calIncField, calInterval);
}