* Timesheet/Tracker: date filters like "last week" where not aware of daylight saving time changes

This commit is contained in:
Ralf Becker 2015-10-27 10:27:09 +00:00
parent 714c75ef6d
commit b01ac97b7e
2 changed files with 123 additions and 67 deletions

View File

@ -166,6 +166,126 @@ class egw_time extends DateTime
}
}
/**
* Like DateTime::add, but additional allow to use a string run through DateInterval::createFromDateString
*
* @param DateInterval|string $interval eg. '1 day', '-2 weeks'
*/
public function add($interval)
{
if (is_string($interval)) $interval = DateInterval::createFromDateString($interval);
parent::add($interval);
}
/**
* Set date to beginning of the week taking into account calendar weekdaystarts preference
*/
public function setWeekstart()
{
$wday = (int) $this->format('w'); // 0=sun, ..., 6=sat
switch($GLOBALS['egw_info']['user']['preferences']['calendar']['weekdaystarts'])
{
case 'Sunday':
$wstart = -$wday;
break;
case 'Saturday':
$wstart = -(6-$wday);
break;
case 'Moday':
default:
$wstart = -($wday ? $wday-1 : 6);
break;
}
if ($wstart) $this->add($wstart.'days');
}
/**
* return SQL implementing filtering by date
*
* @param string $name
* @param int &$start
* @param int &$end
* @param string $column name of timestamp column to use in returned sql
* @param array $filters $name => list($syear,$smonth,$sday,$sweek,$eyear,$emonth,$eday,$eweek) pairs with offsets
* @return string
*/
public static function sql_filter($name, &$start, &$end, $column, array $filters=array())
{
if ($name == 'custom' && $start)
{
$start = new egw_time($start);
$start->setTime(0, 0, 0);
if ($end)
{
$end = new egw_time($end);
$end->setTime(0, 0, 0);
$end->add('+1day');
}
else
{
$end = new egw_time($start);
$end->add('+1week');
}
}
else
{
if (!isset($filters[$name]))
{
return '1=1';
}
$start = new egw_time('now');
$start->setTime(0, 0, 0);
$end = new egw_time('now');
$end->setTime(0, 0, 0);
$year = (int) $start->format('Y');
$month = (int) $start->format('m');
list($syear,$smonth,$sday,$sweek,$eyear,$emonth,$eday,$eweek) = $filters[$name];
// Handle quarters
if(stripos($name, 'quarter') !== false)
{
$start->setDate($year, ((int)floor(($smonth+$month) / 3.1)) * 3 + 1, 1);
$end->setDate($year, ((int)floor(($emonth+$month) / 3.1)+1) * 3 + 1, 1);
}
elseif ($syear || $eyear)
{
$start->setDate($year+$syear, 1, 1);
$end->setDate($year+$eyear, 1, 1);
}
elseif ($smonth || $emonth)
{
$start->setDate($year, $month+$smonth, 1);
$end->setDate($year, $month+$emonth, 1);
}
elseif ($sday || $eday)
{
if ($sday) $start->add($sday.'days');
if ($eday) $end->add($eday.'days');
}
elseif ($sweek || $eweek)
{
$start->setWeekstart();
if ($sweek) $start->add($sweek.'weeks');
$end->setWeekstart();
if ($eweek) $end->add($eweek.'weeks');
}
}
// convert start + end from user to servertime for the filter
$sql = '('.egw_time::user2server($start, 'ts').' <= '.$column.' AND '.$column.' < '.egw_time::user2server($end, 'ts').')';
//error_log(__METHOD__."('$name', ...) syear=$syear, smonth=$smonth, sday=$sday, sweek=$sweek, eyear=$eyear, emonth=$emonth, eday=$eday, eweek=$eweek --> start=".$start->format().', end='.$end->format().", sql='$sql'");
// returned timestamps: $end is an inclusive date, eg. for today it's equal to start!
$start = $start->format('ts');
$end->add('-1day');
$end = $end->format('ts');
return $sql;
}
/**
* Set user timezone, according to user prefs: converts current time to user time
*

View File

@ -377,76 +377,12 @@ class timesheet_bo extends so_sql_cf
*
* @param string $name
* @param int &$start
* @param int &$end_param
* @param int &$end
* @return string
*/
function date_filter($name,&$start,&$end_param)
function date_filter($name,&$start,&$end)
{
$end = $end_param;
if ($name == 'custom' && $start)
{
if ($end)
{
$end += 24*60*60;
}
else
{
$end = $start + 7*24*60*60;
}
}
else
{
if (!isset($this->date_filters[$name]))
{
return '1=1';
}
$year = (int) date('Y',$this->today);
$month = (int) date('m',$this->today);
$day = (int) date('d',$this->today);
list($syear,$smonth,$sday,$sweek,$eyear,$emonth,$eday,$eweek) = $this->date_filters[$name];
if ($syear || $eyear)
{
$start = mktime(0,0,0,1,1,$syear+$year);
$end = mktime(0,0,0,1,1,$eyear+$year);
}
elseif ($smonth || $emonth)
{
$start = mktime(0,0,0,$smonth+$month,1,$year);
$end = mktime(0,0,0,$emonth+$month,1,$year);
}
elseif ($sday || $eday)
{
$start = mktime(0,0,0,$month,$sday+$day,$year);
$end = mktime(0,0,0,$month,$eday+$day,$year);
}
elseif ($sweek || $eweek)
{
$wday = (int) date('w',$this->today); // 0=sun, ..., 6=sat
switch($GLOBALS['egw_info']['user']['preferences']['calendar']['weekdaystarts'])
{
case 'Sunday':
$weekstart = $this->today - $wday * 24*60*60;
break;
case 'Saturday':
$weekstart = $this->today - (6-$wday) * 24*60*60;
break;
case 'Moday':
default:
$weekstart = $this->today - ($wday ? $wday-1 : 6) * 24*60*60;
break;
}
$start = $weekstart + $sweek*7*24*60*60;
$end = $weekstart + $eweek*7*24*60*60;
}
}
$end_param = $end - 24*60*60;
//echo "<p align='right'>date_filter($name,$start,$end) today=".date('l, Y-m-d H:i',$this->today)." ==> ".date('l, Y-m-d H:i:s',$start)." <= date < ".date('l, Y-m-d H:i:s',$end)."</p>\n";
// convert start + end from user to servertime for the filter
return '('.($start-$this->tz_offset_s).' <= ts_start AND ts_start < '.($end-$this->tz_offset_s).')';
return egw_time::sql_filter($name, $start, $end, 'ts_start', $this->date_filters);
}
/**