Serhii
Serhii

Reputation: 7543

Ical4j. RFC5545. Calculate event occurrences, duration hack

I check ical4j library. At time I need calculate event occurrences. Useful example to calculate is here. I try to shift start date and end date. In original start date is 20101113 - 2010 November, Saturday (it maps on pattern see BYDAY=...SA). I want do not care if start match or not. So I used start date with value 20101112 - 2010 November, Friday (it doesn't map on any day in pattern see BYDAY=MO,TU,SA)

    VEvent event = new ContentBuilder().vevent {
        dtstart('20101112', parameters: parameters() {value('DATE')})
        dtend('20101113', parameters: parameters() {value('DATE')})
        rrule('FREQ=WEEKLY;WKST=MO;INTERVAL=3;BYDAY=MO,TU,SA')
    }
    def dates = event.calculateRecurrenceSet(new Period('20101101T000000/20110101T000000'))
    println dates

result is

[20101112T000000Z/20101113T000000Z, 20101113T000000Z/P1D, 20101129T000000Z/P1D, 20101130T000000Z/P1D, 20101204T000000Z/P1D, 20101220T000000Z/P1D, 20101221T000000Z/P1D, 20101225T000000Z/P1D]

almost as expected (except first period in result 20101112T000000Z/20101113T000000Z is redundant). So I continue investigate how to exclude one. In debug mode I see

result = {PeriodList@1497}  size = 8
0 = {Period@2240} "20101112T000000Z/20101113T000000Z"
  duration = null
  rangeStart = {DateTime@2243} "20101112T000000Z"
  rangeEnd = {DateTime@2244} "20101113T000000Z"
1 = {Period@2264} "20101113T000000Z/P1D"
  duration = {Dur@2284} "P1D"
  rangeStart = {DateTime@2285} "20101113T000000Z"
  rangeEnd = {DateTime@2286} "20101114T000000Z"
2 = {Period@2265} "20101129T000000Z/P1D"
  duration = {Dur@2284} "P1D"
  rangeStart = {DateTime@2290} "20101129T000000Z"
  rangeEnd = {DateTime@2291} "20101130T000000Z"
3 = {Period@2266} "20101130T000000Z/P1D"
  duration = {Dur@2284} "P1D"
  rangeStart = {DateTime@2295} "20101130T000000Z"
  rangeEnd = {DateTime@2296} "20101201T000000Z"
4 = {Period@2267} "20101204T000000Z/P1D"
  duration = {Dur@2284} "P1D"
  rangeStart = {DateTime@2300} "20101204T000000Z"
  rangeEnd = {DateTime@2301} "20101205T000000Z"
5 = {Period@2268} "20101220T000000Z/P1D"
  duration = {Dur@2284} "P1D"
  rangeStart = {DateTime@2315} "20101220T000000Z"
  rangeEnd = {DateTime@2316} "20101221T000000Z"
6 = {Period@2269} "20101221T000000Z/P1D"
  duration = {Dur@2284} "P1D"
  rangeStart = {DateTime@2310} "20101221T000000Z"
  rangeEnd = {DateTime@2311} "20101222T000000Z"
7 = {Period@2270} "20101225T000000Z/P1D"
  duration = {Dur@2284} "P1D"
  rangeStart = {DateTime@2305} "20101225T000000Z"
  rangeEnd = {DateTime@2306} "20101226T000000Z"

Eureka! I've found marker to detect redundant dates in generated set (corrupted period has null duration). I continue handling it filtering periods with null value. But filter have filtered nothing. Continue checking...

package net.fortuna.ical4j.model;
...
public class Period extends DateRange implements Comparable<Period> {

    private static final long serialVersionUID = 7321090422911676490L;

    private Dur duration;
    ...
    public final Dur getDuration() {
        if (duration == null) {
            return new Dur(getStart(), getEnd());
        }
        return duration;
    }
    ...

as you can see, class Period has private Dur duration and public final Dur getDuration(). I can't access duration without workaround...

Question is

How should I do?

  1. Use reflection hack to get duration - ugly solution.
  2. Download library sources to change Period class and rebuild library - follows bad support new library versions.
  3. Ask to ical4j developers to expand Period facade - it needs time to change and for release.
  4. Use duration hack over toString (it's unreliable solution).

Upvotes: 1

Views: 630

Answers (1)

Serhii
Serhii

Reputation: 7543

I've raised issue. I'will add details if they consider the issue.

Upvotes: 1

Related Questions