1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-18 19:40:55 +01:00

Schedule monthly events on the 29th, 30th or 31st relative to the end of the month

Summary:
Ref T11326. If you scheudle a monthly event on the 31st, the default behavior of RRULE means that it only occurs in months with 31 days.

This is actually how Google Calendar and Calendar.app both work: if you schedule a monthly event on the 31st, you get about six events per year.

This seems real confusing and bad to me?

Instead, if the user schedules a monthly event on the 29th, 30th or 31st, pretend they scheduled it on the "last day of the month" or "second-to-last day of the month" or similar, so they always get 12 events per year.

This could be slightly confusing too, but seems way less weird than not getting an event every month.

Test Plan: Scheduled events on the 31st of October, saw them occur in November too after the patch.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T11326

Differential Revision: https://secure.phabricator.com/D16775
This commit is contained in:
epriestley 2016-10-31 11:14:27 -07:00
parent 850fcf0207
commit 182611ef7e

View file

@ -19,6 +19,33 @@ final class PhabricatorCalendarEventFrequencyTransaction
$rrule = id(new PhutilCalendarRecurrenceRule()) $rrule = id(new PhutilCalendarRecurrenceRule())
->setFrequency($value); ->setFrequency($value);
// If the user creates a monthly event on the 29th, 30th or 31st of a
// month, it means "the 30th of every month" as far as the RRULE is
// concerned. Such an event will not occur on months with fewer days.
// This is surprising, and proably not what the user wants. Instead,
// schedule these events relative to the end of the month: on the "-1st",
// "-2nd" or "-3rd" day of the month. For example, a monthly event on
// the 31st of a 31-day month translates to "every month, on the last
// day of the month".
if ($value == PhutilCalendarRecurrenceRule::FREQUENCY_MONTHLY) {
$start_datetime = $object->newStartDateTime();
$y = $start_datetime->getYear();
$m = $start_datetime->getMonth();
$d = $start_datetime->getDay();
if ($d >= 29) {
$year_map = PhutilCalendarRecurrenceRule::getYearMap(
$y,
PhutilCalendarRecurrenceRule::WEEKDAY_MONDAY);
$month_days = $year_map['monthDays'][$m];
$schedule_on = -(($month_days + 1) - $d);
$rrule->setByMonthDay(array($schedule_on));
}
}
$object->setRecurrenceRule($rrule); $object->setRecurrenceRule($rrule);
} }