dongmin-shin/google-rfc-2445

RRULE does not honor UNTIL setting

Closed this issue · 8 comments

What steps will reproduce the problem?

DTSTART:20070501T090000
RRULE:FREQ=DAILY;UNTIL=20070506T000000Z

Then call:
  RecurrenceIteratorFactory.createRecurrenceIterator 


What is the expected output? What do you see instead?

I should get just 5 days back.

The iterator does not seem to end (I break out of the loop
after 10000 dates).


What version of the product are you using? On what operating system?

Unknown.  Downloaded the jar from the website this week.


Please provide any additional information below.

I am using the RRULE functionality as a component of my Java-based
iCalendar library:

http://javacaltools.sourceforge.net

Original issue reported on code.google.com by craig...@gmail.com on 17 May 2007 at 5:26

I tried to reproduce with the following program
  import com.google.ical.iter.*;
  import com.google.ical.values.*;
  import java.util.TimeZone;

  public class Test {
    public static void main(String[] args) throws Exception {
      DateTimeValue dtStart = new DateTimeValueImpl(2007, 5, 1, 9, 0, 0);
      TimeZone displayTz = TimeZone.getTimeZone("America/Los_Angeles");
      for (DateValue time : RecurrenceIteratorFactory.createRecurrenceIterable(
               "RRULE:FREQ=DAILY;UNTIL=20070506T000000Z", dtStart, displayTz,
               true)) {
        System.out.println(time);
      }
    }
  }
and I get the following output
  20070501T160000
  20070502T160000
  20070503T160000
  20070504T160000
  20070505T160000
when I link with the rfc2445.jar from
http://code.google.com/p/google-rfc-2445/downloads/list

How are you using the library?

Original comment by mikesamuel@gmail.com on 18 May 2007 at 9:30

I am using my own parser, so I am calling the RRule.setUntil method.  I have my 
own
Date class, but here's the relavant code:

if ( this.untilDate != null ) {
  com.google.ical.values.DateValue rruleUntil = null;
  if ( this.untilDate.dateOnly ) {
    rruleUntil = new DateValueImpl ( this.untilDate.getYear (),
      this.untilDate.getMonth (), this.untilDate.getDay () );
  } else {
    rruleUntil = new DateTimeValueImpl ( this.untilDate.getYear (),
      this.untilDate.getMonth (), this.untilDate.getDay (),
      this.untilDate.getHour (), this.untilDate.getMinute (),
      this.untilDate.getSecond () );
  }
  rrule.setUntil ( rruleUntil );
}

I have some debug code that calls rrule.getUntil(), and it does report back the
correct date.

Original comment by craig...@gmail.com on 22 May 2007 at 1:06

I still can't reproduce with the following testcase.
Can you show me the code you're using to create a RecurrenceIterator or 
Iterable, and
the code you're using to iterate over values?

  public void testUntilDate() {
    // testcase for Issue 1 contributed by cknudsen
    RRule rrule = new RRule();
    rrule.setUntil(new DateTimeValueImpl(2007, 5, 6, 0, 0, 0));

    DateTimeValue dtStartUtc = new DateTimeValueImpl(2007, 5, 1, 9, 0, 0);
    TimeZone displayTz = TimeZone.getTimeZone("America/Los_Angeles");

    RecurrenceIterator iterator =
      RecurrenceIteratorFactory.createRecurrenceIterator(
          rrule, dtStartUtc, displayTz);

    // output is in UTC ; 1600 hours is 0900 - (-7 hours due to PDT)
    assertTrue(iterator.hasNext());
    assertEquals("20070501T160000", iterator.next().toString());
    assertTrue(iterator.hasNext());
    assertEquals("20070502T160000", iterator.next().toString());
    assertTrue(iterator.hasNext());
    assertEquals("20070503T160000", iterator.next().toString());
    assertTrue(iterator.hasNext());
    assertEquals("20070504T160000", iterator.next().toString());
    assertTrue(iterator.hasNext());
    assertEquals("20070505T160000", iterator.next().toString());

    // the until date is 20070506T0000000Z, so 
    assertFalse(iterator.hasNext());
  }

Original comment by mikesamuel@gmail.com on 22 May 2007 at 8:41

Here is my code for iterating.  Note that I have my own check for handing the 
UNTIL
date, which makes this code longer than it needs to be.

public Vector generateRecurrances ( Date startDate, String tzid ) {
...snip... [code for manually setting other RRULE fields]

Vector ret = new Vector ();
java.util.TimeZone timezone = null;
if ( tzid != null )
  timezone = java.util.TimeZone.getTimeZone ( tzid );
RecurrenceIterator iter = RecurrenceIteratorFactory.createRecurrenceIterator ( 
rrule,
dtStart, timezone );
num = 0;
int thisYear = java.util.Calendar.getInstance ().get (
  java.util.Calendar.YEAR );
while ( iter.hasNext () && num++ < 10000 ) {
  com.google.ical.values.DateValue d = iter.next ();
  if ( d instanceof com.google.ical.values.DateTimeValue ) {
    com.google.ical.values.DateTimeValue dt = (com.google.ical.values.DateTimeValue) d;
    try {
      Date newDateTime = new Date ( "XXX", dt.year (), dt.month (), dt
        .day (), dt.hour (), dt.minute (), dt.second () );
      // HACK! The google RRULE code does not seem to support
      // the "UNTIL=" setting, so we will enforce it here.
      if ( this.untilDate != null && newDateTime.isAfter ( this.untilDate ) ) {
        break;
      }
      ret.addElement ( newDateTime );
    } catch ( BogusDataException e1 ) {
      e1.printStackTrace ();
    }
  } else {
    try {
      Date newDate = new Date ( "XXX", d.year (), d.month (), d.day () );
      // HACK! The google RRULE code does not seem to support
      // the "UNTIL=" setting, so we will enforce it here.
      if ( this.untilDate != null && newDate.isAfter ( this.untilDate ) ) {
        break;
      }
      ret.addElement ( newDate );
    } catch ( BogusDataException e1 ) {
      e1.printStackTrace ();
    }
  }
  // Max of 100 years from this year. (To avoid endless loop.)
  // TODO: make this configurable
  if ( d.year () >= thisYear + 100 )
    break;
  }
}
return ret;

Original comment by craig...@gmail.com on 23 May 2007 at 11:58

Also.... if it makes a difference in your unit test, I am using DateValueImpl 
most of
the time rather than DateTimeValueImpl.

Original comment by craig...@gmail.com on 23 May 2007 at 12:00

attached is the file that I ran.  It is mostly your code with a few additions 
to stub
out your Date class, to set up the rrule, and to error out if the until date 
doesn't
do its job.

It works fine for me, so I'm pretty sure the error is in whatever code you have 
that
sets up the RRule.  What do you see if you do System.out.println("UNTIL=" +
rrule.getUntil()) right before you create the recurrence iterator?

If you can get that file to break, please let me know.

Original comment by mikesamuel@gmail.com on 24 May 2007 at 12:03

Attachments:

I was able to get my code working properly.  So, it must have been a bug in my 
code
somewhere.  Thanks for the help!

Original comment by craig...@gmail.com on 1 Jun 2007 at 8:53

Cool.  Congrats on your launch btw.

Closing this issue without making source changes.

Original comment by mikesamuel@gmail.com on 1 Jun 2007 at 10:34

  • Changed state: Invalid