diff --git a/src/parser/calendar/data/PhutilCalendarRecurrenceRule.php b/src/parser/calendar/data/PhutilCalendarRecurrenceRule.php --- a/src/parser/calendar/data/PhutilCalendarRecurrenceRule.php +++ b/src/parser/calendar/data/PhutilCalendarRecurrenceRule.php @@ -561,10 +561,15 @@ $by_month = $this->getByMonth(); $by_setpos = $this->getBySetPosition(); + // If we have a BYMONTHDAY, we consider that set of days in every month. + // For example, "FREQ=YEARLY;BYMONTHDAY=3" means "the third day of every + // month", so we need to expand the month set if the constraint is present. + $by_monthday = $this->getByMonthDay(); + while (!$this->setMonths) { $this->nextYear(); - if ($is_monthly || $by_month) { + if ($is_monthly || $by_month || $by_monthday) { $months = $this->newMonthsSet( ($is_monthly ? $interval : 1), $by_month); diff --git a/src/parser/calendar/data/__tests__/PhutilCalendarRecurrenceRuleTestCase.php b/src/parser/calendar/data/__tests__/PhutilCalendarRecurrenceRuleTestCase.php --- a/src/parser/calendar/data/__tests__/PhutilCalendarRecurrenceRuleTestCase.php +++ b/src/parser/calendar/data/__tests__/PhutilCalendarRecurrenceRuleTestCase.php @@ -131,6 +131,24 @@ '20080229', ); + $tests[] = array( + 'BYMONTH' => array(1, 3), + ); + $expect[] = array( + '19980102', + '19980302', + '19990102', + ); + + $tests[] = array( + 'BYMONTHDAY' => array(1, 3), + ); + $expect[] = array( + '19970903', + '19971001', + '19971003', + ); + $this->assertRules( array( 'FREQ' => 'YEARLY', @@ -157,6 +175,16 @@ $rrule->setInterval($interval); } + $by_month = idx($options, 'BYMONTH'); + if ($by_month) { + $rrule->setByMonth($by_month); + } + + $by_monthday = idx($options, 'BYMONTHDAY'); + if ($by_monthday) { + $rrule->setByMonthDay($by_monthday); + } + $set = id(new PhutilCalendarRecurrenceSet()) ->addSource($rrule);