package jfxtras.icalendarfx.component; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import java.lang.reflect.InvocationTargetException; import java.time.DayOfWeek; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.Month; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; import java.time.temporal.ChronoUnit; import java.time.temporal.Temporal; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.Test; import jfxtras.icalendarfx.ICalendarStaticComponents; import jfxtras.icalendarfx.components.DaylightSavingTime; import jfxtras.icalendarfx.components.StandardTime; import jfxtras.icalendarfx.components.VComponent; import jfxtras.icalendarfx.components.VEvent; import jfxtras.icalendarfx.components.VJournal; import jfxtras.icalendarfx.components.VPrimary; import jfxtras.icalendarfx.components.VRepeatable; import jfxtras.icalendarfx.components.VTodo; import jfxtras.icalendarfx.properties.component.recurrence.RecurrenceDates; import jfxtras.icalendarfx.properties.component.recurrence.RecurrenceRule; import jfxtras.icalendarfx.properties.component.recurrence.rrule.FrequencyType; import jfxtras.icalendarfx.properties.component.recurrence.rrule.RecurrenceRuleValue; import jfxtras.icalendarfx.properties.component.recurrence.rrule.byxxx.ByDay; import jfxtras.icalendarfx.properties.component.recurrence.rrule.byxxx.ByMonth; import jfxtras.icalendarfx.properties.component.recurrence.rrule.byxxx.ByMonthDay; import jfxtras.icalendarfx.properties.component.recurrence.rrule.byxxx.ByWeekNumber; import jfxtras.icalendarfx.properties.component.recurrence.rrule.byxxx.ByDay.ByDayPair; import jfxtras.icalendarfx.properties.component.time.DateTimeStart; import jfxtras.icalendarfx.utilities.DateTimeUtilities; import jfxtras.icalendarfx.utilities.DateTimeUtilities.DateTimeType; /** * Test following components: * @see VEvent * @see VTodo * @see VJournal * @see StandardTime * @see DaylightSavingTime * * for the following properties: * @see RecurrenceDates * @see RecurrenceRule * * @author David Bal * */ public class RepeatableTest //extends Application { @Test public void canBuildRepeatable() throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { List<VRepeatable<?>> components = Arrays.asList( new VEvent() .withRecurrenceDates("RDATE;VALUE=DATE:20160504,20160508,20160509") .withRecurrenceDates(LocalDate.of(2016, 4, 15), LocalDate.of(2016, 4, 16), LocalDate.of(2016, 4, 17)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.DAILY) .withInterval(4)), new VTodo() .withRecurrenceDates("RDATE;VALUE=DATE:20160504,20160508,20160509") .withRecurrenceDates(LocalDate.of(2016, 4, 15), LocalDate.of(2016, 4, 16), LocalDate.of(2016, 4, 17)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.DAILY) .withInterval(4)), new VJournal() .withRecurrenceDates("RDATE;VALUE=DATE:20160504,20160508,20160509") .withRecurrenceDates(LocalDate.of(2016, 4, 15), LocalDate.of(2016, 4, 16), LocalDate.of(2016, 4, 17)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.DAILY) .withInterval(4)), new DaylightSavingTime() .withRecurrenceDates("RDATE;VALUE=DATE:20160504,20160508,20160509") .withRecurrenceDates(LocalDate.of(2016, 4, 15), LocalDate.of(2016, 4, 16), LocalDate.of(2016, 4, 17)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.DAILY) .withInterval(4)), new StandardTime() .withRecurrenceDates("RDATE;VALUE=DATE:20160504,20160508,20160509") .withRecurrenceDates(LocalDate.of(2016, 4, 15), LocalDate.of(2016, 4, 16), LocalDate.of(2016, 4, 17)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.DAILY) .withInterval(4)) ); List<LocalDate> expectedDates = new ArrayList<LocalDate>(Arrays.asList( LocalDate.of(2016, 4, 13) // DTSTART , LocalDate.of(2016, 4, 15) // 2nd RDATE , LocalDate.of(2016, 4, 16) // 2nd RDATE , LocalDate.of(2016, 4, 17) // 2nd RDATE and RRULE , LocalDate.of(2016, 4, 21) // RRULE , LocalDate.of(2016, 4, 25) // RRULE , LocalDate.of(2016, 4, 29) // RRULE , LocalDate.of(2016, 5, 3) // RRULE , LocalDate.of(2016, 5, 4) // 1st RDATE , LocalDate.of(2016, 5, 7) // RRULE , LocalDate.of(2016, 5, 8) // 1st RDATE , LocalDate.of(2016, 5, 9) // 1st RDATE )); for (VRepeatable<?> builtComponent : components) { String componentName = builtComponent.name(); String expectedContent = "BEGIN:" + componentName + System.lineSeparator() + "RDATE;VALUE=DATE:20160504,20160508,20160509" + System.lineSeparator() + "RDATE;VALUE=DATE:20160415,20160416,20160417" + System.lineSeparator() + "RRULE:FREQ=DAILY;INTERVAL=4" + System.lineSeparator() + "END:" + componentName; VComponent parsedComponent = builtComponent.getClass().newInstance(); parsedComponent.addChild(expectedContent); assertEquals(parsedComponent, builtComponent); assertEquals(expectedContent, builtComponent.toString()); ((VPrimary<?>) builtComponent).setDateTimeStart(new DateTimeStart(LocalDate.of(2016, 4, 13))); List<Temporal> madeDates = builtComponent .streamRecurrences() .limit(12) .collect(Collectors.toList()); assertEquals(expectedDates, madeDates); } } @Test public void canDetectErrors1() { VEvent component = new VEvent() .withRecurrenceRule(new RecurrenceRuleValue()); assertEquals(4, component.errors().size()); } @Test public void canStreamRecurrences1() { LocalDate dateTimeStart = LocalDate.of(2016, 4, 22); VEvent component = new VEvent() .withRecurrenceRule("RRULE:FREQ=DAILY") .withDateTimeStart(dateTimeStart); List<Temporal> expectedRecurrences = Stream .iterate(dateTimeStart, a -> a.plus(1, ChronoUnit.DAYS)) .limit(100) .collect(Collectors.toList()); List<Temporal> madeRecurrences = component.streamRecurrences().limit(100).collect(Collectors.toList()); assertEquals(expectedRecurrences, madeRecurrences); } @Test public void canStreamLaterStart() { VEvent component = new VEvent() .withRecurrenceRule("RRULE:FREQ=DAILY") .withDateTimeStart(LocalDateTime.of(2015, 11, 9, 22, 0)) .withDateTimeEnd(LocalDateTime.of(2015, 11, 10, 2, 0)); List<Temporal> expectedRecurrences = Stream .iterate(LocalDateTime.of(2016, 5, 31, 22, 0), a -> a.plus(1, ChronoUnit.DAYS)) .limit(10) .collect(Collectors.toList()); List<Temporal> madeRecurrences = component .streamRecurrences(LocalDateTime.of(2016, 5, 31, 22, 0)) .limit(10) .collect(Collectors.toList()); assertEquals(expectedRecurrences, madeRecurrences); } @Test //(expected = DateTimeException.class) // TODO - RELY ON isValid test instead of listener - change test public void canHandleDTStartTypeChange() { VEvent component = new VEvent() .withDateTimeStart(LocalDate.of(1997, 3, 1)) .withRecurrenceDates("RDATE;VALUE=DATE:19970304,19970504,19970704,19970904"); String errorPrefix = "RDATE:"; boolean hasError = component.errors().stream() .anyMatch(s -> s.substring(0, errorPrefix.length()).equals(errorPrefix)); assertFalse(hasError); component.setDateTimeStart(DateTimeStart.parse(ZonedDateTime.class, "20160302T223316Z")); // invalid hasError = component.errors().stream() .anyMatch(s -> s.substring(0, errorPrefix.length()).equals(errorPrefix)); assertTrue(hasError); } @Test public void canCatchWrongDateType() { VEvent component = new VEvent() .withDateTimeStart(LocalDate.of(1997, 3, 1)); List<RecurrenceDates> recurrences = new ArrayList<>(); recurrences.add(RecurrenceDates.parse(LocalDateTime.class, "20160228T093000")); component.setRecurrenceDates(recurrences); String errorPrefix = "RDATE:"; boolean hasError = component.errors().stream() .anyMatch(s -> s.substring(0, errorPrefix.length()).equals(errorPrefix)); assertTrue(hasError); } @Test public void canCatchDifferentRepeatableTypes() { VEvent builtComponent = new VEvent() .withRecurrenceDates("RDATE;VALUE=DATE:19970304,19970504,19970704,19970904"); Set<Temporal> expectedValues = new LinkedHashSet<>(Arrays.asList( ZonedDateTime.of(LocalDateTime.of(1996, 4, 4, 1, 0), ZoneId.of("Z")) ) ); builtComponent.getRecurrenceDates().add(new RecurrenceDates(expectedValues)); } @Test public void canCatchDifferentRepeatableTypes2() { VEvent component = new VEvent() .withRecurrenceDates("RDATE;VALUE=DATE:19970304,19970504,19970704,19970904"); component.getRecurrenceDates().get(0).getValue().add(LocalDateTime.of(1996, 4, 4, 1, 0)); String expectedError = "RDATE: DateTimeType " + DateTimeType.DATE + " doesn't match previous recurrence's DateTimeType " + DateTimeType.DATE_WITH_LOCAL_TIME; boolean isErrorPresent = component.errors() .stream() .anyMatch(s -> s.equals(expectedError)); assertTrue(isErrorPresent); } /* * STREAM RECURRENCES TESTS */ /** tests converting ISO.8601.2004 date-time string to LocalDateTime */ /** Tests daily stream with FREQ=YEARLY */ @Test public void yearlyStreamTest1() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 9, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.YEARLY)); List<Temporal> madeDates = e .streamRecurrences() .limit(5) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 11, 9, 10, 0) , LocalDateTime.of(2016, 11, 9, 10, 0) , LocalDateTime.of(2017, 11, 9, 10, 0) , LocalDateTime.of(2018, 11, 9, 10, 0) , LocalDateTime.of(2019, 11, 9, 10, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=YEARLY"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } /** Tests daily stream with FREQ=YEARLY;BYDAY=FR */ @Test public void yearlyStreamTest2() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 6, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.YEARLY) .withByRules(new ByDay(DayOfWeek.FRIDAY))); List<Temporal> madeDates = e .streamRecurrences() .limit(5) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 11, 6, 10, 0) , LocalDateTime.of(2015, 11, 13, 10, 0) , LocalDateTime.of(2015, 11, 20, 10, 0) , LocalDateTime.of(2015, 11, 27, 10, 0) , LocalDateTime.of(2015, 12, 4, 10, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=YEARLY;BYDAY=FR"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } /** FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8 */ @Test public void yearlyStreamTest3() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(1997, 6, 5, 9, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.YEARLY) .withByRules(new ByDay(DayOfWeek.THURSDAY), new ByMonth(Month.JUNE, Month.JULY, Month.AUGUST))); List<Temporal> madeDates = e .streamRecurrences() .limit(20) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(1997, 6, 5, 9, 0) , LocalDateTime.of(1997, 6, 12, 9, 0) , LocalDateTime.of(1997, 6, 19, 9, 0) , LocalDateTime.of(1997, 6, 26, 9, 0) , LocalDateTime.of(1997, 7, 3, 9, 0) , LocalDateTime.of(1997, 7, 10, 9, 0) , LocalDateTime.of(1997, 7, 17, 9, 0) , LocalDateTime.of(1997, 7, 24, 9, 0) , LocalDateTime.of(1997, 7, 31, 9, 0) , LocalDateTime.of(1997, 8, 7, 9, 0) , LocalDateTime.of(1997, 8, 14, 9, 0) , LocalDateTime.of(1997, 8, 21, 9, 0) , LocalDateTime.of(1997, 8, 28, 9, 0) , LocalDateTime.of(1998, 6, 4, 9, 0) , LocalDateTime.of(1998, 6, 11, 9, 0) , LocalDateTime.of(1998, 6, 18, 9, 0) , LocalDateTime.of(1998, 6, 25, 9, 0) , LocalDateTime.of(1998, 7, 2, 9, 0) , LocalDateTime.of(1998, 7, 9, 9, 0) , LocalDateTime.of(1998, 7, 16, 9, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } /** FREQ=YEARLY;BYMONTH=1,2 */ @Test public void yearlyStreamTest4() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 1, 6, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.YEARLY) .withByRules(new ByMonth(Month.JANUARY, Month.FEBRUARY))); List<Temporal> madeDates = e .streamRecurrences() .limit(5) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 1, 6, 10, 0) , LocalDateTime.of(2015, 2, 6, 10, 0) , LocalDateTime.of(2016, 1, 6, 10, 0) , LocalDateTime.of(2016, 2, 6, 10, 0) , LocalDateTime.of(2017, 1, 6, 10, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=YEARLY;BYMONTH=1,2"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } /** FREQ=YEARLY;BYMONTH=11;BYMONTHDAY=10 */ @Test public void yearlyStreamTest5() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 10, 0, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.YEARLY) .withByRules(new ByMonth(Month.NOVEMBER), new ByMonthDay(10))); List<Temporal> madeDates = e .streamRecurrences() .limit(5) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 11, 10, 0, 0) , LocalDateTime.of(2016, 11, 10, 0, 0) , LocalDateTime.of(2017, 11, 10, 0, 0) , LocalDateTime.of(2018, 11, 10, 0, 0) , LocalDateTime.of(2019, 11, 10, 0, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=YEARLY;BYMONTH=11;BYMONTHDAY=10"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } /** FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYMONTHDAY=2,3,4,5,6,7,8;BYDAY=TU * (U.S. Presidential Election day) */ @Test public void yearlyStreamTest6() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(1996, 11, 5, 0, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.YEARLY) .withInterval(4) .withByRules(new ByMonth(Month.NOVEMBER) , new ByMonthDay(2,3,4,5,6,7,8) , new ByDay(DayOfWeek.TUESDAY) )); List<Temporal> madeDates = e .streamRecurrences() .limit(6) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(1996, 11, 5, 0, 0) , LocalDateTime.of(2000, 11, 7, 0, 0) , LocalDateTime.of(2004, 11, 2, 0, 0) , LocalDateTime.of(2008, 11, 4, 0, 0) , LocalDateTime.of(2012, 11, 6, 0, 0) , LocalDateTime.of(2016, 11, 8, 0, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYMONTHDAY=2,3,4,5,6,7,8;BYDAY=TU"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } /** FREQ=YEARLY;BYDAY=20MO */ @Test public void yearlyStreamTest7() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(1997, 5, 19, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.YEARLY) .withByRules(new ByDay(new ByDayPair(DayOfWeek.MONDAY, 20)))); List<Temporal> madeDates = e .streamRecurrences() .limit(3) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(1997, 5, 19, 10, 0) , LocalDateTime.of(1998, 5, 18, 10, 0) , LocalDateTime.of(1999, 5, 17, 10, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=YEARLY;BYDAY=20MO"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } /** FREQ=YEARLY;BYWEEKNO=20;BYDAY=MO */ @Test public void yearlyStreamTest8() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(1997, 5, 12, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.YEARLY) .withByRules(new ByWeekNumber(20), new ByDay(DayOfWeek.MONDAY))); List<Temporal> madeDates = e .streamRecurrences() .limit(5) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(1997, 5, 12, 10, 0) , LocalDateTime.of(1998, 5, 11, 10, 0) , LocalDateTime.of(1999, 5, 17, 10, 0) , LocalDateTime.of(2000, 5, 15, 10, 0) , LocalDateTime.of(2001, 5, 14, 10, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=YEARLY;BYWEEKNO=20;BYDAY=MO"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); // Locale.setDefault(oldLocale); } /** Tests daily stream with FREQ=MONTHLY */ @Test public void monthlyStreamTest() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 9, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.MONTHLY)); List<Temporal> madeDates = e .streamRecurrences() .limit(5) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 11, 9, 10, 0) , LocalDateTime.of(2015, 12, 9, 10, 0) , LocalDateTime.of(2016, 1, 9, 10, 0) , LocalDateTime.of(2016, 2, 9, 10, 0) , LocalDateTime.of(2016, 3, 9, 10, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=MONTHLY"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } /** Tests daily stream with FREQ=MONTHLY;BYMONTHDAY=-2 */ @Test public void monthlyStreamTest2() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 29, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.MONTHLY) .withByRules(new ByMonthDay() .withValue(-2))); // repeats 2nd to last day of month List<Temporal> madeDates = e .streamRecurrences() .limit(5) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 11, 29, 10, 0) , LocalDateTime.of(2015, 12, 30, 10, 0) , LocalDateTime.of(2016, 1, 30, 10, 0) , LocalDateTime.of(2016, 2, 28, 10, 0) , LocalDateTime.of(2016, 3, 30, 10, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=MONTHLY;BYMONTHDAY=-2"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } /** Tests daily stream with FREQ=MONTHLY;BYDAY=TU,WE,FR */ @Test public void monthlyStreamTest3() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 9, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.MONTHLY) .withByRules(new ByDay(DayOfWeek.TUESDAY, DayOfWeek.WEDNESDAY, DayOfWeek.FRIDAY))); List<Temporal> madeDates = e .streamRecurrences() .limit(10) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 11, 10, 10, 0) , LocalDateTime.of(2015, 11, 11, 10, 0) , LocalDateTime.of(2015, 11, 13, 10, 0) , LocalDateTime.of(2015, 11, 17, 10, 0) , LocalDateTime.of(2015, 11, 18, 10, 0) , LocalDateTime.of(2015, 11, 20, 10, 0) , LocalDateTime.of(2015, 11, 24, 10, 0) , LocalDateTime.of(2015, 11, 25, 10, 0) , LocalDateTime.of(2015, 11, 27, 10, 0) , LocalDateTime.of(2015, 12, 1, 10, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=MONTHLY;BYDAY=TU,WE,FR"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } /** Tests daily stream with FREQ=MONTHLY;BYDAY=-1SA */ @Test public void monthlyStreamTest4() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 9, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.MONTHLY) .withByRules(new ByDay(new ByDay.ByDayPair(DayOfWeek.SATURDAY, -1)))); // last Saturday in month List<Temporal> madeDates = e .streamRecurrences() .limit(5) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 11, 28, 10, 0) , LocalDateTime.of(2015, 12, 26, 10, 0) , LocalDateTime.of(2016, 1, 30, 10, 0) , LocalDateTime.of(2016, 2, 27, 10, 0) , LocalDateTime.of(2016, 3, 26, 10, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=MONTHLY;BYDAY=-1SA"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } /** FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13 Every Friday the 13th, forever: */ @Test public void monthlyStreamTest5() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(1997, 6, 13, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.MONTHLY) .withByRules(new ByDay(DayOfWeek.FRIDAY), new ByMonthDay(13))); List<Temporal> madeDates = e .streamRecurrences() .limit(6) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(1997, 6, 13, 10, 0) , LocalDateTime.of(1998, 2, 13, 10, 0) , LocalDateTime.of(1998, 3, 13, 10, 0) , LocalDateTime.of(1998, 11, 13, 10, 0) , LocalDateTime.of(1999, 8, 13, 10, 0) , LocalDateTime.of(2000, 10, 13, 10, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); RecurrenceRuleValue r = RecurrenceRuleValue.parse("FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13"); assertEquals(r, e.getRecurrenceRule().getValue()); // verify order of parameters doesn't matter } /** Tests daily stream with FREQ=MONTHLY;BYMONTH=11,12;BYDAY=TU,WE,FR */ @Test public void monthlyStreamTest6() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 3, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.MONTHLY) .withByRules(new ByMonth(Month.NOVEMBER, Month.DECEMBER) , new ByDay(DayOfWeek.TUESDAY, DayOfWeek.WEDNESDAY, DayOfWeek.FRIDAY))); List<Temporal> madeDates = e .streamRecurrences() .limit(13) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 11, 3, 10, 0) , LocalDateTime.of(2015, 11, 4, 10, 0) , LocalDateTime.of(2015, 11, 6, 10, 0) , LocalDateTime.of(2015, 11, 10, 10, 0) , LocalDateTime.of(2015, 11, 11, 10, 0) , LocalDateTime.of(2015, 11, 13, 10, 0) , LocalDateTime.of(2015, 11, 17, 10, 0) , LocalDateTime.of(2015, 11, 18, 10, 0) , LocalDateTime.of(2015, 11, 20, 10, 0) , LocalDateTime.of(2015, 11, 24, 10, 0) , LocalDateTime.of(2015, 11, 25, 10, 0) , LocalDateTime.of(2015, 11, 27, 10, 0) , LocalDateTime.of(2015, 12, 1, 10, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=MONTHLY;BYMONTH=11,12;BYDAY=TU,WE,FR"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } /** FREQ=WEEKLY */ @Test public void weeklyStreamTest1() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 9, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.WEEKLY)); List<Temporal> madeDates = e .streamRecurrences() .limit(5) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 11, 9, 10, 0) , LocalDateTime.of(2015, 11, 16, 10, 0) , LocalDateTime.of(2015, 11, 23, 10, 0) , LocalDateTime.of(2015, 11, 30, 10, 0) , LocalDateTime.of(2015, 12, 7, 10, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=WEEKLY"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } /** FREQ=WEEKLY;INTERVAL=2;BYDAY=MO,WE,FR */ @Test public void weeklyStreamTest2() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 11, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.WEEKLY) .withInterval(2) .withByRules(new ByDay(DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY, DayOfWeek.FRIDAY))); List<Temporal> madeDates = e .streamRecurrences() .limit(10) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 11, 11, 10, 0) , LocalDateTime.of(2015, 11, 13, 10, 0) , LocalDateTime.of(2015, 11, 23, 10, 0) , LocalDateTime.of(2015, 11, 25, 10, 0) , LocalDateTime.of(2015, 11, 27, 10, 0) , LocalDateTime.of(2015, 12, 7, 10, 0) , LocalDateTime.of(2015, 12, 9, 10, 0) , LocalDateTime.of(2015, 12, 11, 10, 0) , LocalDateTime.of(2015, 12, 21, 10, 0) , LocalDateTime.of(2015, 12, 23, 10, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=WEEKLY;INTERVAL=2;BYDAY=MO,WE,FR"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } /** FREQ=WEEKLY;BYDAY=MO,WE,FR */ @Test public void weeklyStreamTest3() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 7, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.WEEKLY) .withByRules(new ByDay(DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY, DayOfWeek.FRIDAY))); List<Temporal> madeDates = e .streamRecurrences() .limit(5) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 11, 9, 10, 0) , LocalDateTime.of(2015, 11, 11, 10, 0) , LocalDateTime.of(2015, 11, 13, 10, 0) , LocalDateTime.of(2015, 11, 16, 10, 0) , LocalDateTime.of(2015, 11, 18, 10, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=WEEKLY;BYDAY=MO,WE,FR"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } /** FREQ=WEEKLY;INTERVAL=2;COUNT=11;BYDAY=MO,WE,FR */ @Test public void canStreamWeekly4() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 11, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.WEEKLY) .withInterval(2) .withCount(11) .withByRules(new ByDay(DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY, DayOfWeek.FRIDAY)) ); List<Temporal> madeDates = e.streamRecurrences() .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 11, 11, 10, 0) , LocalDateTime.of(2015, 11, 13, 10, 0) , LocalDateTime.of(2015, 11, 23, 10, 0) , LocalDateTime.of(2015, 11, 25, 10, 0) , LocalDateTime.of(2015, 11, 27, 10, 0) , LocalDateTime.of(2015, 12, 7, 10, 0) , LocalDateTime.of(2015, 12, 9, 10, 0) , LocalDateTime.of(2015, 12, 11, 10, 0) , LocalDateTime.of(2015, 12, 21, 10, 0) , LocalDateTime.of(2015, 12, 23, 10, 0) , LocalDateTime.of(2015, 12, 25, 10, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=11;BYDAY=MO,WE,FR"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } @Test // tests starting on Sunday (1st day of week) with other day of the week public void canStreamWeekly5() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2016, 1, 3, 5, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.WEEKLY) .withByRules(new ByDay(DayOfWeek.SUNDAY, DayOfWeek.WEDNESDAY))); List<Temporal> madeDates = e .streamRecurrences() .limit(10) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2016, 1, 3, 5, 0) , LocalDateTime.of(2016, 1, 6, 5, 0) , LocalDateTime.of(2016, 1, 10, 5, 0) , LocalDateTime.of(2016, 1, 13, 5, 0) , LocalDateTime.of(2016, 1, 17, 5, 0) , LocalDateTime.of(2016, 1, 20, 5, 0) , LocalDateTime.of(2016, 1, 24, 5, 0) , LocalDateTime.of(2016, 1, 27, 5, 0) , LocalDateTime.of(2016, 1, 31, 5, 0) , LocalDateTime.of(2016, 2, 3, 5, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=WEEKLY;BYDAY=SU,WE"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } @Test public void canStreamWeeklyZoned() { VEvent e = new VEvent() .withDateTimeStart(ZonedDateTime.of(LocalDateTime.of(2015, 11, 9, 10, 0), ZoneId.of("America/Los_Angeles"))) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.WEEKLY) .withByRules(new ByDay(DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY, DayOfWeek.FRIDAY))); List<Temporal> madeDates = e .streamRecurrences() .limit(10) .collect(Collectors.toList()); List<ZonedDateTime> expectedDates = new ArrayList<>(Arrays.asList( ZonedDateTime.of(LocalDateTime.of(2015, 11, 9, 10, 0), ZoneId.of("America/Los_Angeles")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 11, 10, 0), ZoneId.of("America/Los_Angeles")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 13, 10, 0), ZoneId.of("America/Los_Angeles")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 16, 10, 0), ZoneId.of("America/Los_Angeles")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 18, 10, 0), ZoneId.of("America/Los_Angeles")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 20, 10, 0), ZoneId.of("America/Los_Angeles")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 23, 10, 0), ZoneId.of("America/Los_Angeles")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 25, 10, 0), ZoneId.of("America/Los_Angeles")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 27, 10, 0), ZoneId.of("America/Los_Angeles")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 30, 10, 0), ZoneId.of("America/Los_Angeles")) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=WEEKLY;BYDAY=MO,WE,FR"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } /** Tests daily stream with FREQ=DAILY */ @Test public void dailyStreamTest1() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 9, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.DAILY)); List<Temporal> madeDates = e .streamRecurrences() .limit(5) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 11, 9, 10, 0) , LocalDateTime.of(2015, 11, 10, 10, 0) , LocalDateTime.of(2015, 11, 11, 10, 0) , LocalDateTime.of(2015, 11, 12, 10, 0) , LocalDateTime.of(2015, 11, 13, 10, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=DAILY"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } /** Tests daily stream with FREQ=DAILY;INTERVAL=3;COUNT=6 */ @Test public void dailyStreamTest2() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 9, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.DAILY) .withInterval(3) .withCount(6) ); List<Temporal> madeDates = e .streamRecurrences() .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 11, 9, 10, 0) , LocalDateTime.of(2015, 11, 12, 10, 0) , LocalDateTime.of(2015, 11, 15, 10, 0) , LocalDateTime.of(2015, 11, 18, 10, 0) , LocalDateTime.of(2015, 11, 21, 10, 0) , LocalDateTime.of(2015, 11, 24, 10, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=DAILY;INTERVAL=3;COUNT=6"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } /** Tests daily stream with FREQ=DAILY;INTERVAL=3;BYMONTHDAY=9,10,11,12,13,14 */ @Test public void dailyStreamTest3() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 9, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.DAILY) .withInterval(3) .withByRules(new ByMonthDay() .withValue(9,10,11,12,13,14))); List<Temporal> madeDates = e .streamRecurrences() .limit(10) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 11, 9, 10, 0) , LocalDateTime.of(2015, 11, 12, 10, 0) , LocalDateTime.of(2015, 12, 9, 10, 0) , LocalDateTime.of(2015, 12, 12, 10, 0) , LocalDateTime.of(2016, 1, 11, 10, 0) , LocalDateTime.of(2016, 1, 14, 10, 0) , LocalDateTime.of(2016, 2, 10, 10, 0) , LocalDateTime.of(2016, 2, 13, 10, 0) , LocalDateTime.of(2016, 3, 11, 10, 0) , LocalDateTime.of(2016, 3, 14, 10, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=DAILY;INTERVAL=3;BYMONTHDAY=9,10,11,12,13,14"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } /** Tests daily stream with FREQ=DAILY;INTERVAL=2;BYMONTHDAY=9 */ @Test public void dailyStreamTest4() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 9, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.DAILY) .withInterval(2) .withByRules(new ByMonthDay(9)) ); List<Temporal> madeDates = e .streamRecurrences() .limit(6) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 11, 9, 10, 0) , LocalDateTime.of(2015, 12, 9, 10, 0) , LocalDateTime.of(2016, 2, 9, 10, 0) , LocalDateTime.of(2016, 4, 9, 10, 0) , LocalDateTime.of(2016, 5, 9, 10, 0) , LocalDateTime.of(2016, 8, 9, 10, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=DAILY;INTERVAL=2;BYMONTHDAY=9"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } /** Tests daily stream with FREQ=DAILY;INTERVAL=2;BYDAY=FR */ @Test public void dailyStreamTest5() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 9, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.DAILY) .withInterval(2) .withByRules(new ByDay(DayOfWeek.FRIDAY))); List<Temporal> madeDates = e .streamRecurrences() .limit(6) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 11, 13, 10, 0) , LocalDateTime.of(2015, 11, 27, 10, 0) , LocalDateTime.of(2015, 12, 11, 10, 0) , LocalDateTime.of(2015, 12, 25, 10, 0) , LocalDateTime.of(2016, 1, 8, 10, 0) , LocalDateTime.of(2016, 1, 22, 10, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=DAILY;INTERVAL=2;BYDAY=FR"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } @Test public void dailyStreamTest6() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 9, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.DAILY) .withInterval(2) .withUntil(ZonedDateTime.of(LocalDateTime.of(2015, 12, 1, 9, 59, 59), ZoneOffset.systemDefault()) .withZoneSameInstant(ZoneId.of("Z"))) ); List<Temporal> madeDates = e .streamRecurrences() .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 11, 9, 10, 0) , LocalDateTime.of(2015, 11, 11, 10, 0) , LocalDateTime.of(2015, 11, 13, 10, 0) , LocalDateTime.of(2015, 11, 15, 10, 0) , LocalDateTime.of(2015, 11, 17, 10, 0) , LocalDateTime.of(2015, 11, 19, 10, 0) , LocalDateTime.of(2015, 11, 21, 10, 0) , LocalDateTime.of(2015, 11, 23, 10, 0) , LocalDateTime.of(2015, 11, 25, 10, 0) , LocalDateTime.of(2015, 11, 27, 10, 0) , LocalDateTime.of(2015, 11, 29, 10, 0) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=DAILY;INTERVAL=2;UNTIL=" + DateTimeUtilities.ZONED_DATE_TIME_UTC_FORMATTER.format( ZonedDateTime.of(LocalDateTime.of(2015, 12, 1, 9, 59, 59), ZoneOffset.systemDefault()) .withZoneSameInstant(ZoneId.of("Z"))); assertEquals(expectedContent, e.getRecurrenceRule().toString()); } @Test public void dailyStreamTestJapanZone() { VEvent e = new VEvent() .withDateTimeStart(ZonedDateTime.of(LocalDateTime.of(2015, 11, 9, 8, 0), ZoneId.of("Japan"))) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.DAILY) .withUntil(ZonedDateTime.of(LocalDateTime.of(2015, 11, 19, 1, 0), ZoneId.of("Z"))) ); List<Temporal> madeDates = e .streamRecurrences() .collect(Collectors.toList()); List<Temporal> expectedDates = new ArrayList<>(Arrays.asList( ZonedDateTime.of(LocalDateTime.of(2015, 11, 9, 8, 0), ZoneId.of("Japan")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 10, 8, 0), ZoneId.of("Japan")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 11, 8, 0), ZoneId.of("Japan")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 12, 8, 0), ZoneId.of("Japan")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 13, 8, 0), ZoneId.of("Japan")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 14, 8, 0), ZoneId.of("Japan")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 15, 8, 0), ZoneId.of("Japan")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 16, 8, 0), ZoneId.of("Japan")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 17, 8, 0), ZoneId.of("Japan")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 18, 8, 0), ZoneId.of("Japan")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 19, 8, 0), ZoneId.of("Japan")) )); assertEquals(expectedDates, madeDates); String expectedContent = "RRULE:FREQ=DAILY;UNTIL=20151119T010000Z"; assertEquals(expectedContent, e.getRecurrenceRule().toString()); } @Test public void dailyStreamTestUTC() { VEvent e = new VEvent() .withDateTimeStart(ZonedDateTime.of(LocalDateTime.of(2015, 11, 9, 10, 0), ZoneId.of("Z"))) .withRecurrenceRule(new RecurrenceRuleValue() .withUntil(ZonedDateTime.of(LocalDateTime.of(2015, 12, 1, 10, 0), ZoneId.of("Z"))) .withFrequency(FrequencyType.DAILY) .withInterval(2)); List<Temporal> madeDates = e .streamRecurrences() .collect(Collectors.toList()); List<ZonedDateTime> expectedDates = new ArrayList<>(Arrays.asList( ZonedDateTime.of(LocalDateTime.of(2015, 11, 9, 10, 0), ZoneId.of("Z")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 11, 10, 0), ZoneId.of("Z")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 13, 10, 0), ZoneId.of("Z")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 15, 10, 0), ZoneId.of("Z")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 17, 10, 0), ZoneId.of("Z")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 19, 10, 0), ZoneId.of("Z")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 21, 10, 0), ZoneId.of("Z")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 23, 10, 0), ZoneId.of("Z")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 25, 10, 0), ZoneId.of("Z")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 27, 10, 0), ZoneId.of("Z")) , ZonedDateTime.of(LocalDateTime.of(2015, 11, 29, 10, 0), ZoneId.of("Z")) , ZonedDateTime.of(LocalDateTime.of(2015, 12, 1, 10, 0), ZoneId.of("Z")) )); assertEquals(expectedDates, madeDates); } /** Tests individual VEvent */ @Test public void individualTest1() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 11, 10, 30)); List<Temporal> madeDates = e .streamRecurrences() .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 11, 11, 10, 30) )); assertEquals(expectedDates, madeDates); } /** Tests VEvent with RDATE VEvent */ @Test public void canStreamRDate() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 9, 10, 0)) .withRecurrenceDates(new RecurrenceDates(LocalDateTime.of(2015, 11, 12, 10, 0) , LocalDateTime.of(2015, 11, 14, 12, 0))); List<Temporal> madeDates = e .streamRecurrences() .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 11, 9, 10, 0) , LocalDateTime.of(2015, 11, 12, 10, 0) , LocalDateTime.of(2015, 11, 14, 12, 0) )); assertEquals(expectedDates, madeDates); } @Test public void getWeekly2ChangeStart() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 11, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.WEEKLY) .withInterval(2) .withByRules(new ByDay(DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY, DayOfWeek.FRIDAY))); LocalDateTime start2 = LocalDateTime.of(2015, 12, 6, 0, 0); List<Temporal> madeDates2 = e .streamRecurrences(start2) .limit(3) .collect(Collectors.toList()); List<LocalDateTime> expectedDates2 = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 12, 7, 10, 0) , LocalDateTime.of(2015, 12, 9, 10, 0) , LocalDateTime.of(2015, 12, 11, 10, 0) )); assertEquals(expectedDates2, madeDates2); } // ten years in future @Test public void getWeekly2FarFuture() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 11, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.WEEKLY) .withInterval(2) .withByRules(new ByDay(DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY, DayOfWeek.FRIDAY))); LocalDateTime start = LocalDateTime.of(2025, 11, 10, 0, 0); List<Temporal> madeDates = e .streamRecurrences(start) .limit(3) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2025, 11, 10, 10, 0) , LocalDateTime.of(2025, 11, 12, 10, 0) , LocalDateTime.of(2025, 11, 14, 10, 0) )); assertEquals(expectedDates, madeDates); LocalDateTime start2 = LocalDateTime.of(2015, 11, 11, 0, 0); List<Temporal> madeDates2 = e .streamRecurrences(start2) .limit(2) .collect(Collectors.toList()); List<LocalDateTime> expectedDates2 = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2015, 11, 11, 10, 0) , LocalDateTime.of(2015, 11, 13, 10, 0) )); assertEquals(expectedDates2, madeDates2); LocalDateTime start3 = LocalDateTime.of(2025, 11, 12, 0, 0); List<Temporal> madeDates3 = e .streamRecurrences(start3) .limit(3) .collect(Collectors.toList()); List<LocalDateTime> expectedDates3 = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2025, 11, 12, 10, 0) , LocalDateTime.of(2025, 11, 14, 10, 0) , LocalDateTime.of(2025, 11, 24, 10, 0) )); assertEquals(expectedDates3, madeDates3); LocalDateTime start4 = LocalDateTime.of(2025, 11, 17, 0, 0); List<Temporal> madeDates4 = e .streamRecurrences(start4) .limit(3) .collect(Collectors.toList()); List<LocalDateTime> expectedDates4 = new ArrayList<LocalDateTime>(Arrays.asList( LocalDateTime.of(2025, 11, 24, 10, 0) , LocalDateTime.of(2025, 11, 26, 10, 0) , LocalDateTime.of(2025, 11, 28, 10, 0) )); assertEquals(expectedDates4, madeDates4); } // Whole day tests @Test public void makeDatesWholeDayDaily2() { VEvent e = new VEvent() .withDateTimeStart(LocalDate.of(2015, 11, 9)) .withRecurrenceRule(new RecurrenceRuleValue() .withCount(6) .withFrequency(FrequencyType.DAILY) .withInterval(3)); List<Temporal> madeDates = e .streamRecurrences() .collect(Collectors.toList()); List<LocalDate> expectedDates = new ArrayList<>(Arrays.asList( LocalDate.of(2015, 11, 9) , LocalDate.of(2015, 11, 12) , LocalDate.of(2015, 11, 15) , LocalDate.of(2015, 11, 18) , LocalDate.of(2015, 11, 21) , LocalDate.of(2015, 11, 24) )); assertEquals(expectedDates, madeDates); } @Test public void makeDatesWholeDayDaily3() { VEvent e = new VEvent() .withDateTimeStart(LocalDate.of(2015, 11, 9)) .withRecurrenceRule(new RecurrenceRuleValue() .withUntil(LocalDate.of(2015, 11, 24)) .withFrequency(FrequencyType.DAILY) .withInterval(3)); List<Temporal> madeDates = e .streamRecurrences() .collect(Collectors.toList()); List<LocalDate> expectedDates = new ArrayList<>(Arrays.asList( LocalDate.of(2015, 11, 9) , LocalDate.of(2015, 11, 12) , LocalDate.of(2015, 11, 15) , LocalDate.of(2015, 11, 18) , LocalDate.of(2015, 11, 21) , LocalDate.of(2015, 11, 24) )); assertEquals(expectedDates, madeDates); } @Test // LocalDate public void canChangeToWholeDay() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 9, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.DAILY)); e.setDateTimeStart(new DateTimeStart(LocalDate.of(2015, 11, 9))); // change to whole-day { List<Temporal> madeDates = e .streamRecurrences() .limit(6) .collect(Collectors.toList()); List<LocalDate> expectedDates = new ArrayList<>(Arrays.asList( LocalDate.of(2015, 11, 9) , LocalDate.of(2015, 11, 10) , LocalDate.of(2015, 11, 11) , LocalDate.of(2015, 11, 12) , LocalDate.of(2015, 11, 13) , LocalDate.of(2015, 11, 14) )); assertEquals(expectedDates, madeDates); } // Change back to date/time e.setDateTimeStart(new DateTimeStart(LocalDateTime.of(2015, 11, 9, 10, 0))); // change to date/time { // start date/time List<Temporal> madeDates = e .streamRecurrences() .limit(6) .collect(Collectors.toList()); List<LocalDateTime> expectedDates = new ArrayList<>(Arrays.asList( LocalDateTime.of(2015, 11, 9, 10, 0) , LocalDateTime.of(2015, 11, 10, 10, 0) , LocalDateTime.of(2015, 11, 11, 10, 0) , LocalDateTime.of(2015, 11, 12, 10, 0) , LocalDateTime.of(2015, 11, 13, 10, 0) , LocalDateTime.of(2015, 11, 14, 10, 0) )); assertEquals(expectedDates, madeDates); } } @Test // tests cached stream ability to reset when RRule and start changes public void canChangeStartStreamTest() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 9, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.DAILY)); { // initialize stream List<Temporal> madeDates = e .streamRecurrences() .limit(50) .collect(Collectors.toList()); Temporal seed = LocalDateTime.of(2015, 11, 9, 10, 00); List<Temporal> expectedDates = Stream .iterate(seed, a -> a.plus(1, ChronoUnit.DAYS)) .limit(50) .collect(Collectors.toList()); assertEquals(expectedDates, madeDates); } e.setDateTimeStart(new DateTimeStart(LocalDateTime.of(2015, 11, 10, 10, 0))); // change start { // make new stream List<Temporal> madeDates = e .streamRecurrences(LocalDateTime.of(2015, 12, 9, 10, 0)) // .recurrenceStreamer().stream(LocalDateTime.of(2015, 12, 9, 10, 0)) .limit(50) .collect(Collectors.toList()); Temporal seed = LocalDateTime.of(2015, 12, 9, 10, 0); List<Temporal> expectedDates = Stream .iterate(seed, a -> a.plus(1, ChronoUnit.DAYS)) .limit(50) .collect(Collectors.toList()); assertEquals(expectedDates, madeDates); } // request date beyond first cached date to test cache system Temporal t = e.streamRecurrences(LocalDateTime.of(2016, 12, 25, 10, 0)).findFirst().get(); assertEquals(LocalDateTime.of(2016, 12, 25, 10, 0), t); } @Test // tests cached stream ability to reset when RRule and start changes public void canChangeRRuleStreamTest() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 9, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.DAILY)); { // initialize stream List<Temporal> madeDates = e .streamRecurrences() .limit(50) .collect(Collectors.toList()); Temporal seed = LocalDateTime.of(2015, 11, 9, 10, 00); List<Temporal> expectedDates = Stream .iterate(seed, a -> a.plus(1, ChronoUnit.DAYS)) .limit(50) .collect(Collectors.toList()); assertEquals(expectedDates, madeDates); } // Change RRule e.setRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.WEEKLY) .withInterval(2) .withByRules(new ByDay(DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY, DayOfWeek.FRIDAY))); { // check new repeatable stream List<Temporal> madeDates = e .streamRecurrences() .limit(50) .collect(Collectors.toList()); Temporal seed = LocalDateTime.of(2015, 11, 9, 10, 00); List<Temporal> expectedDates = Stream .iterate(seed, a -> a.plus(2, ChronoUnit.WEEKS)) .flatMap(d -> { List<Temporal> days = new ArrayList<>(); days.add(d); // Mondays days.add(d.plus(2, ChronoUnit.DAYS)); // Wednesdays days.add(d.plus(4, ChronoUnit.DAYS)); // Fridays return days.stream(); }) .limit(50) .collect(Collectors.toList()); assertEquals(expectedDates, madeDates); } // request date beyond first cached date to test cache system Temporal date = e.streamRecurrences(LocalDateTime.of(2015, 12, 9, 10, 0)).findFirst().get(); assertEquals(LocalDateTime.of(2015, 12, 9, 10, 0), date); } @Test public void canFindPreviousStreamTemporal() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 7, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.WEEKLY) .withByRules(new ByDay(DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY, DayOfWeek.FRIDAY))); e.streamRecurrences().limit(100).collect(Collectors.toList()); // set cache assertEquals(LocalDateTime.of(2016, 1, 20, 10, 0), e.recurrenceCache().previousValue(LocalDateTime.of(2016, 1, 21, 10, 0))); VEvent e2 = new VEvent() // without cache .withDateTimeStart(LocalDate.of(2015, 11, 9)) .withRecurrenceRule(new RecurrenceRuleValue() .withCount(6) .withFrequency(FrequencyType.DAILY) .withInterval(3)); assertEquals(LocalDate.of(2015, 11, 24), e2.recurrenceCache().previousValue(LocalDate.of(2015, 12, 31))); } // Tests added components with recurrence ID to parent's list of recurrences @Test public void canHandleRecurrenceID() { VEvent e = new VEvent() .withDateTimeStart(LocalDateTime.of(2015, 11, 7, 10, 0)) .withRecurrenceRule(new RecurrenceRuleValue() .withFrequency(FrequencyType.WEEKLY) .withByRules(new ByDay(DayOfWeek.MONDAY, DayOfWeek.WEDNESDAY, DayOfWeek.FRIDAY))); e.streamRecurrences().limit(100).collect(Collectors.toList()); // set cache assertEquals(LocalDateTime.of(2016, 1, 20, 10, 0), e.recurrenceCache().previousValue(LocalDateTime.of(2016, 1, 21, 10, 0))); VEvent e2 = new VEvent() // without cache .withDateTimeStart(LocalDate.of(2015, 11, 9)) .withRecurrenceRule(new RecurrenceRuleValue() .withCount(6) .withFrequency(FrequencyType.DAILY) .withInterval(3)); assertEquals(LocalDate.of(2015, 11, 24), e2.recurrenceCache().previousValue(LocalDate.of(2015, 12, 31))); } @Test public void canFindPreviousStreamValue() { VEvent vComponentEdited = ICalendarStaticComponents.getDaily1(); Temporal startRecurrence = LocalDateTime.of(2016, 5, 16, 9, 0); Temporal previous = vComponentEdited.previousStreamValue(startRecurrence); assertEquals(LocalDateTime.of(2016, 5, 15, 10, 0), previous); } // @Test // public void canCheckIfIsRecurrence() // { // VCalendar vCalendar = new VCalendar(); // VEvent vComponentMain = ICalendarStaticComponents.getDaily1(); // vCalendar.addVComponent(vComponentMain); // // VEvent vComponentRecurrence = ICalendarStaticComponents.getDaily1() // .withRecurrenceRule((RecurrenceRuleValue) null) // .withRecurrenceId(LocalDateTime.of(2016, 5, 17, 10, 0)) // .withSummary("recurrence summary") // .withDateTimeStart(LocalDateTime.of(2016, 5, 17, 8, 30)) // .withDateTimeEnd(LocalDateTime.of(2016, 5, 17, 9, 30)); // vCalendar.addVComponent(vComponentRecurrence); // // assertTrue(vComponentMain.isRecurrence(LocalDateTime.of(2016, 5, 16, 10, 0))); // assertFalse(vComponentMain.isRecurrence(LocalDateTime.of(2016, 5, 17, 10, 0))); // is not recurrence because vComponentRecurrence uses this date/time // assertTrue(vComponentMain.isRecurrence(LocalDateTime.of(2016, 5, 18, 10, 0))); // // assertTrue(vComponentRecurrence.isRecurrence(LocalDateTime.of(2016, 5, 17, 8, 30))); // } }