davical/testing/test-RRULE-v2.php
Andrew Ruthven 326afc8cfc Teach how to set timezone when running standalone
It is useful for debugging to run this command standalone, but in
that case it typically has to set the timezone for the database to
ensure that the times in the results are the same as the PHP times.
2021-09-19 00:01:01 +12:00

150 lines
6.0 KiB
PHP
Executable File

#!/usr/bin/php
<?php
if ( @file_exists('../../awl/inc/AWLUtilities.php') ) {
set_include_path('../inc:../htdocs:../../awl/inc');
}
else {
set_include_path('../inc:../htdocs:/usr/share/awl/inc');
}
require_once("always.php");
$c->dbg = array();
require_once("RRule.php");
require_once('AwlQuery.php');
# Check database timezone
$qry = new AwlQuery();
$qry->QDo("SHOW TIMEZONE");
$row = $qry->Fetch();
$initial_tz = $row->TimeZone;
echo "Database Time Zone: $initial_tz\n";
@header("Content-Type: text/plain; charset=UTF-8");
echo <<<EOTXT
Testing the RRule v2 Library
EOTXT;
class RRuleTest {
var $dtstart;
var $recur;
var $description;
var $result_description;
var $PHP_time;
var $SQL_time;
function __construct( $description, $start, $recur, $result_description = null ) {
$this->description = $description;
$this->dtstart = $start;
$this->recur = $recur;
$this->result_description = $result_description;
$this->result_limit = 30;
if ( preg_match('/^.*? (.*)$/', $this->dtstart, $matches) ) {
$this->tz = $matches[1];
}
}
function PHPTest() {
$result = '';
$start = microtime(true);
$rule = new RepeatRule( $this->dtstart, $this->recur );
$i = 0;
while( $date = $rule->next() ) {
if ( ($i++ % 4) == 0 ) $result .= "\n";
$result .= " " . $date->format('Y-m-d H:i:s');
if ( $i >= $this->result_limit ) break;
}
$this->PHP_time = microtime(true) - $start;
return $result;
}
function SQLTest() {
$qry = new AwlQuery;
global $initial_tz;
# This is a hack to get the output time to be in "local time" so that we
# get the same time out of the PHP code to allow the diff between the
# results to work.
$changed_tz = 0;
if (isset($this->tz) && $this->tz != $initial_tz) {
echo "Setting database time zone to: $this->tz\n";
$qry->QDo("SET TIMEZONE TO :tz", array( ':tz' => $this->tz ));
$changed_tz = 1;
}
$result = '';
$sql = "SELECT event_instances::timestamp AS event_date FROM event_instances(:dtstart,:rrule) LIMIT ".$this->result_limit;
$start = microtime(true);
$qry->SetSql($sql);
$qry->Bind(array( ':dtstart' => $this->dtstart, ':rrule' => $this->recur) );
// printf( "%s\n", $qry->querystring);
if ( $qry->Exec("test") && $qry->rows() > 0 ) {
$i = 0;
while( $row = $qry->Fetch() ) {
if ( ($i++ % 4) == 0 ) $result .= "\n";
$result .= " " . $row->event_date;
}
}
$this->SQL_time = microtime(true) - $start;
if ($changed_tz) {
$qry->QDo("SET TIMEZONE TO '$initial_tz'");
}
return $result;
}
}
$tests = array(
new RRuleTest( "Daily for 7 days", "20061103T073000", "RRULE:FREQ=DAILY;COUNT=7" )
, new RRuleTest( "Weekly for 26 weeks", "20061102T100000", "RRULE:FREQ=WEEKLY;COUNT=26;INTERVAL=1;BYDAY=TH" )
, new RRuleTest( "Fortnightly for 4 events", "20061103T160000", "RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4" )
, new RRuleTest( "Fortnightly for 28 events", "20061103T160000", "RRULE:FREQ=WEEKLY;INTERVAL=2;UNTIL=20071122T235900" )
, new RRuleTest( "3/wk for 5 weeks", "20081101T160000", "RRULE:FREQ=WEEKLY;COUNT=15;INTERVAL=1;BYDAY=MO,WE,FR" )
, new RRuleTest( "Monthly forever", "20061104T073000", "RRULE:FREQ=MONTHLY" )
, new RRuleTest( "Monthly, on the 1st monday, 2nd wednesday, 3rd friday and last sunday, forever", "20061117T073000", "RRULE:FREQ=MONTHLY;BYDAY=1MO,2WE,3FR,-1SU" )
, new RRuleTest( "The working days of each month", "20061107T113000", "RRULE:FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;UNTIL=20070101T000000" )
, 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" )
, 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" )
, new RRuleTest( "Time zone 1", "19700315T030000", "FREQ=YEARLY;INTERVAL=1;BYDAY=3SU;BYMONTH=3" )
, new RRuleTest( "Time zone 2", "19700927T020000", "FREQ=YEARLY;INTERVAL=1;BYDAY=-1SU;BYMONTH=9" )
, new RRuleTest( "Time zone 3", "19810329T030000", "FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU" )
, new RRuleTest( "Time zone 4", "20000404T010000", "FREQ=YEARLY;BYDAY=1SU;BYMONTH=4;COUNT=15" )
, new RRuleTest( "Six Working Days", "20110905", "FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR;COUNT=6" )
, new RRuleTest( "Six Working Days", "20110905", "FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;COUNT=6" )
, new RRuleTest( "31st of each month", "20110831", "RRULE:FREQ=MONTHLY;BYMONTHDAY=31;COUNT=12" )
);
foreach( $tests AS $k => $test ) {
echo "=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=\n";
echo "$test->dtstart - $test->recur\n";
echo "$test->description\n";
$php_result = $test->PHPTest();
$sql_result = $test->SQLTest();
if ( $php_result == $sql_result ) {
printf( 'PHP & SQL results are identical (-: P: %6.4lf & S: %6.4lf'."\n", $test->PHP_time, $test->SQL_time);
echo "PHP Result:\n$php_result\n\n";
echo "SQL Result:\n$sql_result\n\n";
}
else {
printf( 'PHP & SQL results differ :-( P: %6.4lf & S: %6.4lf'."\n", $test->PHP_time, $test->SQL_time);
echo "PHP Result:\n$php_result\n\n";
echo "SQL Result:\n$sql_result\n\n"; // Still under development
}
}
exit(0);