mirror of
https://gitlab.com/davical-project/davical.git
synced 2026-02-13 03:23:34 +00:00
Fix handling of BYMONTHDAY=-N in repeat rules.
It seems PHP's date::setDate function doesn't do what we want when you hand it a negative integer so we need to override a little more of it's behaviour. We have to make sure that date::modify is not called with a days greater than the month we might land in when we add a number of months to it.
This commit is contained in:
parent
11892c4e97
commit
e64f92ff86
@ -343,6 +343,9 @@ class RepeatRuleDateTime extends DateTime {
|
||||
// printf( "Modify '%s' by: >>%s<<\n", $this->__toString(), $interval );
|
||||
// print_r($this);
|
||||
if ( !isset($interval) || $interval == '' ) $interval = '1 day';
|
||||
if ( parent::format('d') > 28 && strstr($interval,'month') !== false ) {
|
||||
$this->setDate(null,null,28);
|
||||
}
|
||||
parent::modify($interval);
|
||||
return $this->__toString();
|
||||
}
|
||||
@ -431,10 +434,36 @@ class RepeatRuleDateTime extends DateTime {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a 1 if this year is a leap year, otherwise a 0
|
||||
* @param int $year The year we are quizzical about.
|
||||
* @return 1 if this is a leap year, 0 otherwise
|
||||
*/
|
||||
public static function hasLeapDay($year) {
|
||||
if ( ($year % 4) == 0 && (($year % 100) != 0 || ($year % 400) == 0) ) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of days in a year/month pair
|
||||
* @param int $year
|
||||
* @param int $month
|
||||
* @return int the number of days in the month
|
||||
*/
|
||||
public static function daysInMonth( $year, $month ) {
|
||||
if ($month == 4 || $month == 6 || $month == 9 || $month == 11) return 30;
|
||||
else if ($month != 2) return 31;
|
||||
return 28 + RepeatRuleDateTime::hasLeapDay($year);
|
||||
}
|
||||
|
||||
|
||||
function setDate( $year=null, $month=null, $day=null ) {
|
||||
if ( !isset($year) ) $year = parent::format('Y');
|
||||
if ( !isset($month) ) $month = parent::format('m');
|
||||
if ( !isset($day) ) $day = parent::format('d');
|
||||
if ( $day < 0 ) {
|
||||
$day += RepeatRuleDateTime::daysInMonth($year, $month) + 1;
|
||||
}
|
||||
parent::setDate( $year , $month , $day );
|
||||
return $this;
|
||||
}
|
||||
@ -749,7 +778,9 @@ class RepeatRule {
|
||||
$this->current_set = array();
|
||||
foreach( $instances AS $k => $instance ) {
|
||||
foreach( $this->bymonthday AS $k => $monthday ) {
|
||||
$this->current_set[] = $this->date_mask( clone($instance), null, null, $monthday, null, null, null);
|
||||
$expanded = $this->date_mask( clone($instance), null, null, $monthday, null, null, null);
|
||||
if ( DEBUG_RRULE ) printf( "Expanded BYMONTHDAY $monthday into date %s from %s\n", $expanded->format('c'), $instance->format('c') );
|
||||
$this->current_set[] = $expanded;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,7 +80,8 @@ $tests = array(
|
||||
, new RRuleTest( "The last working day of each month", "20061107T113000", "RRULE:FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1;COUNT=30" )
|
||||
, new RRuleTest( "Every working day", "20081020T103000", "RRULE:FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;COUNT=30" )
|
||||
, new RRuleTest( "Every working day", "20081020T110000", "RRULE:FREQ=DAILY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;COUNT=30" )
|
||||
//**SQL is wrong , new RRuleTest( "1st Tuesday, 2nd Wednesday, 3rd Thursday & 4th Friday, every March, June, September, October and December", "20081001T133000", "RRULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=1TU,2WE,3TH,4FR;BYMONTH=3,6,9,10,12" )
|
||||
, new RRuleTest( "The last day of each month", "20110831", "RRULE:FREQ=MONTHLY;BYMONTHDAY=-1" )
|
||||
, new RRuleTest( "1st Tuesday, 2nd Wednesday, 3rd Thursday & 4th Friday, every March, June, September, October and December (SQL is wrong)", "20081001T133000", "RRULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=1TU,2WE,3TH,4FR;BYMONTH=3,6,9,10,12" )
|
||||
, new RRuleTest( "Every tuesday and friday", "20081017T084500", "RRULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=TU,FR;COUNT=30" )
|
||||
, new RRuleTest( "Every tuesday and friday", "20081017T084500", "RRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=TU,FR;COUNT=30" )
|
||||
, new RRuleTest( "Every tuesday and friday", "20081017T084500", "RRULE:FREQ=DAILY;INTERVAL=1;BYDAY=TU,FR;COUNT=30" )
|
||||
|
||||
@ -2,7 +2,7 @@ HTTP/1.1 200 OK
|
||||
Date: Dow, 01 Jan 2000 00:00:00 GMT
|
||||
DAV: 1, 2, 3, access-control, calendar-access, calendar-schedule
|
||||
DAV: extended-mkcol, calendar-proxy, bind, addressbook, calendar-auto-schedule
|
||||
Content-Length: 5323
|
||||
Content-Length: 7224
|
||||
Content-Type: text/plain
|
||||
|
||||
#!/usr/bin/php
|
||||
@ -51,6 +51,36 @@ PHP & SQL results are identical (-:
|
||||
20081020T110000 - RRULE:FREQ=DAILY;INTERVAL=1;BYDAY=MO,TU,WE,TH,FR;COUNT=30
|
||||
Every working day
|
||||
PHP & SQL results are identical (-:
|
||||
=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=
|
||||
20110831 - RRULE:FREQ=MONTHLY;BYMONTHDAY=-1
|
||||
The last day of each month
|
||||
PHP & SQL results are identical (-:
|
||||
=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=
|
||||
20081001T133000 - RRULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=1TU,2WE,3TH,4FR;BYMONTH=3,6,9,10,12
|
||||
1st Tuesday, 2nd Wednesday, 3rd Thursday & 4th Friday, every March, June, September, October and December (SQL is wrong)
|
||||
PHP & SQL results differ :-(
|
||||
PHP Result:
|
||||
|
||||
2008-10-07 13:30:00 2008-10-08 13:30:00 2008-10-16 13:30:00 2008-10-24 13:30:00
|
||||
2008-12-02 13:30:00 2008-12-10 13:30:00 2008-12-18 13:30:00 2008-12-26 13:30:00
|
||||
2009-03-03 13:30:00 2009-03-11 13:30:00 2009-03-19 13:30:00 2009-03-27 13:30:00
|
||||
2009-06-02 13:30:00 2009-06-10 13:30:00 2009-06-18 13:30:00 2009-06-26 13:30:00
|
||||
2009-09-01 13:30:00 2009-09-09 13:30:00 2009-09-17 13:30:00 2009-09-25 13:30:00
|
||||
2009-10-06 13:30:00 2009-10-14 13:30:00 2009-10-15 13:30:00 2009-10-23 13:30:00
|
||||
2009-12-01 13:30:00 2009-12-09 13:30:00 2009-12-17 13:30:00 2009-12-25 13:30:00
|
||||
2010-03-02 13:30:00 2010-03-10 13:30:00
|
||||
|
||||
SQL Result:
|
||||
|
||||
2008-10-07 13:30:00 2008-10-08 13:30:00 2008-10-16 13:30:00 2008-10-24 13:30:00
|
||||
2008-11-04 13:30:00 2008-11-12 13:30:00 2008-11-20 13:30:00 2008-11-28 13:30:00
|
||||
2008-12-02 13:30:00 2008-12-10 13:30:00 2008-12-18 13:30:00 2008-12-26 13:30:00
|
||||
2009-01-06 13:30:00 2009-01-14 13:30:00 2009-01-15 13:30:00 2009-01-23 13:30:00
|
||||
2009-02-03 13:30:00 2009-02-11 13:30:00 2009-02-19 13:30:00 2009-02-27 13:30:00
|
||||
2009-03-03 13:30:00 2009-03-11 13:30:00 2009-03-19 13:30:00 2009-03-27 13:30:00
|
||||
2009-04-07 13:30:00 2009-04-08 13:30:00 2009-04-16 13:30:00 2009-04-24 13:30:00
|
||||
2009-05-05 13:30:00 2009-05-13 13:30:00
|
||||
|
||||
=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=
|
||||
20081017T084500 - RRULE:FREQ=MONTHLY;INTERVAL=1;BYDAY=TU,FR;COUNT=30
|
||||
Every tuesday and friday
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user