diff --git a/src/main/java/biweekly/io/ICalTimeZone.java b/src/main/java/biweekly/io/ICalTimeZone.java index 17fd259cc..50df63780 100644 --- a/src/main/java/biweekly/io/ICalTimeZone.java +++ b/src/main/java/biweekly/io/ICalTimeZone.java @@ -408,20 +408,26 @@ private DateValue getObservanceDateClosestToTheGivenDate(Observance observance, RecurrenceIterator it = createIterator(observance); /* - * The "advanceTo()" method skips all dates that are less than the - * given date. I would have thought that we would have to call - * "next()" once because we want it to skip the date that is equal - * to the "last" date. But this causes all the unit tests to fail, - * so I guess not. + * Calling "it.advanceTo()" here causes problems. + * + * See: https://github.com/mangstadt/biweekly/issues/126 */ - it.advanceTo(last); - //it.next(); + //it.advanceTo(last); DateValue prev = null, cur = null; boolean stopped = false; while (it.hasNext()) { cur = it.next(); - dateCache.add(cur); + int curCompareToLast = cur.compareTo(last); + if (curCompareToLast < 0) { + continue; + } + if (curCompareToLast > 0) { + dateCache.add(cur); + } + if (curCompareToLast == 0) { + //do nothing; don't add to dateCache + } if (givenDate.compareTo(cur) < 0) { //stop if we have passed the givenTime diff --git a/src/test/java/biweekly/issues/Issue115.java b/src/test/java/biweekly/issues/Issue115.java new file mode 100644 index 000000000..0e785dff8 --- /dev/null +++ b/src/test/java/biweekly/issues/Issue115.java @@ -0,0 +1,57 @@ +package biweekly.issues; + +import static biweekly.util.TestUtils.date; +import static org.junit.Assert.assertEquals; + +import java.util.Date; + +import org.junit.Test; + +import biweekly.Biweekly; +import biweekly.ICalendar; +import biweekly.component.VEvent; + +/** + * @author Michael Angstadt + * @see "https://github.com/mangstadt/biweekly/issues/115" + */ +public class Issue115 { + @Test + public void test1() throws Exception { + ICalendar ical = Biweekly.parse(getClass().getResourceAsStream("issue115-1.ics")).first(); + + /* + * The event comes before the last Sunday in October, so it should + * be in daylight time (offset of +02:00). + */ + VEvent event = ical.getEvents().get(0); + + Date expected = date(2022, 10, 29, 8, 0, 0, "+0200"); + Date actual = event.getDateStart().getValue(); + assertEquals(expected, actual); + + expected = date(2022, 10, 29, 8, 30, 0, "+0200"); + actual = event.getDateEnd().getValue(); + assertEquals(expected, actual); + } + + @Test + public void test2() throws Exception { + ICalendar ical = Biweekly.parse(getClass().getResourceAsStream("issue115-2.ics")).first(); + + /* + * The event comes after the last Sunday in October, so it should + * be in standard time (offset of +01:00). + */ + VEvent event = ical.getEvents().get(0); + + Date expected = date(2022, 10, 31, 8, 0, 0, "+0100"); + System.out.println(expected); + Date actual = event.getDateStart().getValue(); + assertEquals(expected, actual); + + expected = date(2022, 10, 31, 8, 30, 0, "+0100"); + actual = event.getDateEnd().getValue(); + assertEquals(expected, actual); + } +} diff --git a/src/test/java/biweekly/issues/Issue126.java b/src/test/java/biweekly/issues/Issue126.java new file mode 100644 index 000000000..f3fa17414 --- /dev/null +++ b/src/test/java/biweekly/issues/Issue126.java @@ -0,0 +1,55 @@ +package biweekly.issues; + +import static biweekly.util.TestUtils.date; +import static org.junit.Assert.assertEquals; + +import java.util.Date; + +import org.junit.Test; + +import biweekly.Biweekly; +import biweekly.ICalendar; +import biweekly.component.VEvent; + +/** + * @author Michael Angstadt + * @see "https://github.com/mangstadt/biweekly/issues/126" + */ +public class Issue126 { + @Test + public void test() throws Exception { + ICalendar ical = Biweekly.parse(getClass().getResourceAsStream("issue126.ics")).first(); + + /* + * The first event comes after the last Sunday in October, so it should + * be in standard time (offset of +01:00). + */ + { + VEvent event = ical.getEvents().get(0); + + Date expected = date(2023, 11, 22, 9, 30, 0, "+0100"); + Date actual = event.getDateStart().getValue(); + assertEquals(expected, actual); + + expected = date(2023, 11, 22, 12, 0, 0, "+0100"); + actual = event.getDateEnd().getValue(); + assertEquals(expected, actual); + } + + /* + * The second event comes after the last Sunday in March, so it should + * be in daylight time (offset of +02:00). + */ + { + VEvent event = ical.getEvents().get(1); + + Date expected = date(2023, 4, 22, 9, 30, 0, "+0200"); + Date actual = event.getDateStart().getValue(); + assertEquals(expected, actual); + + expected = date(2023, 4, 22, 12, 0, 0, "+0200"); + actual = event.getDateEnd().getValue(); + assertEquals(expected, actual); + } + } +} diff --git a/src/test/resources/biweekly/issues/issue115-1.ics b/src/test/resources/biweekly/issues/issue115-1.ics new file mode 100644 index 000000000..a272c1644 --- /dev/null +++ b/src/test/resources/biweekly/issues/issue115-1.ics @@ -0,0 +1,550 @@ +BEGIN:VCALENDAR +PRODID:-//Microsoft Corporation//Outlook 16.0 MIMEDIR//EN +VERSION:2.0 +METHOD:PUBLISH +X-MS-OLK-FORCEINSPECTOROPEN:TRUE +BEGIN:VTIMEZONE +TZID:W. Europe Standard Time +BEGIN:STANDARD +DTSTART:16011028T030000 +RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10 +TZOFFSETFROM:+0200 +TZOFFSETTO:+0100 +END:STANDARD +BEGIN:DAYLIGHT +DTSTART:16010325T020000 +RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3 +TZOFFSETFROM:+0100 +TZOFFSETTO:+0200 +END:DAYLIGHT +END:VTIMEZONE +BEGIN:VEVENT +CLASS:PUBLIC +CREATED:20220510T132250Z +DESCRIPTION: \n +DTEND;TZID="W. Europe Standard Time":20221029T083000 +DTSTAMP:20220510T132250Z +DTSTART;TZID="W. Europe Standard Time":20221029T080000 +LAST-MODIFIED:20220510T132250Z +PRIORITY:5 +SEQUENCE:0 +SUMMARY;LANGUAGE=de:29.10. 8-8:30 +TRANSP:OPAQUE +UID:040000008200E00074C5B7101A82E00800000000509A92BD8164D801000000000000000 + 01000000002B8A0B2A4159442998858E43D9B0927 +X-ALT-DESC;FMTTYPE=text/html:\n\n\n

 \;

+ +X-MICROSOFT-CDO-BUSYSTATUS:BUSY +X-MICROSOFT-CDO-IMPORTANCE:1 +X-MICROSOFT-DISALLOW-COUNTER:FALSE +X-MS-OLK-CONFTYPE:0 +BEGIN:VALARM +TRIGGER:-PT15M +ACTION:DISPLAY +DESCRIPTION:Reminder +END:VALARM +END:VEVENT +END:VCALENDAR diff --git a/src/test/resources/biweekly/issues/issue115-2.ics b/src/test/resources/biweekly/issues/issue115-2.ics new file mode 100644 index 000000000..c0aa5fc76 --- /dev/null +++ b/src/test/resources/biweekly/issues/issue115-2.ics @@ -0,0 +1,550 @@ +BEGIN:VCALENDAR +PRODID:-//Microsoft Corporation//Outlook 16.0 MIMEDIR//EN +VERSION:2.0 +METHOD:PUBLISH +X-MS-OLK-FORCEINSPECTOROPEN:TRUE +BEGIN:VTIMEZONE +TZID:W. Europe Standard Time +BEGIN:STANDARD +DTSTART:16011028T030000 +RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10 +TZOFFSETFROM:+0200 +TZOFFSETTO:+0100 +END:STANDARD +BEGIN:DAYLIGHT +DTSTART:16010325T020000 +RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3 +TZOFFSETFROM:+0100 +TZOFFSETTO:+0200 +END:DAYLIGHT +END:VTIMEZONE +BEGIN:VEVENT +CLASS:PUBLIC +CREATED:20220510T132313Z +DESCRIPTION: \n +DTEND;TZID="W. Europe Standard Time":20221031T083000 +DTSTAMP:20220510T132313Z +DTSTART;TZID="W. Europe Standard Time":20221031T080000 +LAST-MODIFIED:20220510T132313Z +PRIORITY:5 +SEQUENCE:0 +SUMMARY;LANGUAGE=de:31.10. 8-8:30 +TRANSP:OPAQUE +UID:040000008200E00074C5B7101A82E00800000000509A92BD8164D801000000000000000 + 01000000002B8A0B2A4159442998858E43D9B0927 +X-ALT-DESC;FMTTYPE=text/html:\n\n\n

 \;

+ +X-MICROSOFT-CDO-BUSYSTATUS:BUSY +X-MICROSOFT-CDO-IMPORTANCE:1 +X-MICROSOFT-DISALLOW-COUNTER:FALSE +X-MS-OLK-CONFTYPE:0 +BEGIN:VALARM +TRIGGER:-PT15M +ACTION:DISPLAY +DESCRIPTION:Reminder +END:VALARM +END:VEVENT +END:VCALENDAR diff --git a/src/test/resources/biweekly/issues/issue126.ics b/src/test/resources/biweekly/issues/issue126.ics new file mode 100644 index 000000000..15fb61b20 --- /dev/null +++ b/src/test/resources/biweekly/issues/issue126.ics @@ -0,0 +1,28 @@ +BEGIN:VCALENDAR +VERSION:2.0 +PRODID:Microsoft Exchange Server 2010 +METHOD:REQUEST +BEGIN:VTIMEZONE +TZID:W. Europe Standard Time +BEGIN:STANDARD +DTSTART:16010101T030000 +TZOFFSETFROM:+0200 +TZOFFSETTO:+0100 +RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=10 +END:STANDARD +BEGIN:DAYLIGHT +DTSTART:16010101T020000 +TZOFFSETFROM:+0100 +TZOFFSETTO:+0200 +RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=3 +END:DAYLIGHT +END:VTIMEZONE +BEGIN:VEVENT +DTSTART;TZID=W. Europe Standard Time:20231122T093000 +DTEND;TZID=W. Europe Standard Time:20231122T120000 +END:VEVENT +BEGIN:VEVENT +DTSTART;TZID=W. Europe Standard Time:20230422T093000 +DTEND;TZID=W. Europe Standard Time:20230422T120000 +END:VEVENT +END:VCALENDAR