CC-3067: Shows in frontend widgets appear on the wrong day after changing timezone

- Converting times to UTC timezone in ApiController before sending them to model functions

- Added utility functions in DateHelper.php

- GetShowsByDayOfWeek has been removed due to bugs caused by using local timezone
based variable like $day, which represents day of the week in local time, in db query,
which has times saved in UTC timezone. Converting stuff like day of the week from local
to UTC is messy. GetNextShows(...) can do the job so WeekInfoAction now uses it instead
This commit is contained in:
Yuchen Wang 2011-11-21 18:03:56 -05:00
parent eb93004b66
commit 86729475f6
4 changed files with 62 additions and 87 deletions

View file

@ -211,12 +211,12 @@ class ApiController extends Zend_Controller_Action
$this->_helper->viewRenderer->setNoRender(true);
$date = new Application_Model_DateHelper;
$timeNow = $date->getTimestamp();
$timeEnd = $date->getDayEndTimestamp();
$utcTimeNow = $date->getUtcTimestamp();
$utctimeEnd = Application_Model_DateHelper::GetDayEndTimestampInUtc();
$result = array("env"=>APPLICATION_ENV,
"schedulerTime"=>gmdate("Y-m-d H:i:s"),
"nextShow"=>Application_Model_Show::GetNextShows($timeNow, 5, $timeEnd));
"nextShow"=>Application_Model_Show::GetNextShows($utcTimeNow, 5, $utcTimeEnd));
Application_Model_Show::ConvertToLocalTimeZone($result["nextShow"], array("starts", "ends", "start_timestamp", "end_timestamp"));
@ -236,12 +236,19 @@ class ApiController extends Zend_Controller_Action
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
$date = new Application_Model_DateHelper;
$dayStart = $date->getWeekStartDate();
$utcDayStart = Application_Model_DateHelper::ConvertToUtcDateTimeString($dayStart);
$dow = array("sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday");
$result = array();
for ($i=0; $i<7; $i++){
$shows = Application_Model_Show::GetShowsByDayOfWeek($i);
Application_Model_Show::ConvertToLocalTimeZone($shows, array("show_starts", "show_ends"));
$utcDayEnd = Application_Model_DateHelper::GetDayEndTimestamp($utcDayStart);
$shows = Application_Model_Show::GetNextShows($utcDayStart, 0, $utcDayEnd);
$utcDayStart = $utcDayEnd;
Application_Model_Show::ConvertToLocalTimeZone($shows, array("starts", "ends", "start_timestamp", "end_timestamp"));
$result[$dow[$i]] = $shows;
}

View file

@ -29,7 +29,7 @@ class Application_Model_DateHelper
/**
* Get date of object construction in the format
* YY:mm:dd
* YYYY-MM-DD
*/
function getDate()
{
@ -45,6 +45,19 @@ class Application_Model_DateHelper
return gmdate("H:i:s", $this->_dateTime);
}
/**
* Get the week start date of this week in the format
* YYYY-MM-DD
*
* @return String - week start date
*/
function getWeekStartDate()
{
$startDate = date('w') == 0 ? date('Y-m-d') : date('Y-m-d', strtotime('last sunday'));
$startDateTime = new DateTime($startDate);
return $startDateTime->format('Y-m-d H:i:s');
}
/**
* Set the internal timestamp of the object.
*/
@ -63,12 +76,17 @@ class Application_Model_DateHelper
*
* @return End of day timestamp in local timezone
*/
function getDayEndTimestamp() {
$dateTime = new DateTime($this->getDate(), new DateTimeZone("UTC"));
public static function GetDayEndTimestamp($time = "") {
$dateTime = $time == "" ? new DateTime(date("Y-m-d")) : new DateTime($time);
$dateTime->add(new DateInterval('P1D'));
return $dateTime->format('Y-m-d H:i:s');
}
public static function GetDayEndTimestampInUtc($time = "") {
$dayEndTimestamp = Application_Model_DateHelper::GetDayEndTimestamp($time);
return Application_Model_DateHelper::ConvertToUtcDateTime($dayEndTimestamp);
}
/**
* Find the epoch timestamp difference from "now" to the beginning of today.
*/
@ -265,5 +283,11 @@ class Application_Model_DateHelper
return $p_dateString;
return self::ConvertToLocalDateTime($p_dateString)->format($p_format);
}
public static function ConvertToUtcDateTimeString($p_dateString, $p_format="Y-m-d H:i:s"){
if (is_null($p_dateString) || strlen($p_dateString) == 0)
return $p_dateString;
return self::ConvertToUtcDateTime($p_dateString)->format($p_format);
}
}

View file

@ -1461,15 +1461,15 @@ class Application_Model_Show {
}
/**
* Given local current time $timeNow, returns the show being played right now.
* Given time $timeNow, returns the show being played right now.
* Times are all in UTC time.
*
* @param type $timeNow local current time
* @return type show being played right now
* @param String $timeNow - current time (in UTC)
* @return array - show being played right now
*/
public static function GetCurrentShow($timeNow)
{
global $CC_CONFIG, $CC_DBC;
//TODO, returning starts + ends twice (once with an alias). Unify this after the 2.0 release. --Martin
$sql = "SELECT si.starts as start_timestamp, si.ends as end_timestamp, s.name, s.id, si.id as instance_id, si.record, s.url, starts, ends"
." FROM $CC_CONFIG[showInstances] si, $CC_CONFIG[showTable] s"
@ -1484,23 +1484,25 @@ class Application_Model_Show {
}
/**
* Given local current time $timeNow, returns the next $limit number of
* shows within 2 days if $timeEnd is not given; Otherwise, returns the
* next $limit number of shows from $timeNow to $timeEnd, both in local time.
* Given a start time $timeStart and end time $timeEnd, returns the next $limit
* number of shows within the time interval;
* If $timeEnd not given, shows within next 48 hours from $timeStart are returned;
* If $limit not given, all shows within the intervals are returns;
* Times are all in UTC time.
*
* @param type $timeNow local current time
* @param type $limit number of shows to return
* @param type $timeEnd optional: interval end time
* @return type next $limit number of shows
* @param String $timeStart - interval start time (in UTC)
* @param int $limit - number of shows to return
* @param String $timeEnd - interval end time (in UTC)
* @return array - the next $limit number of shows within the time interval
*/
public static function GetNextShows($timeNow, $limit, $timeEnd = "")
public static function GetNextShows($timeStart, $limit = 0, $timeEnd = "")
{
global $CC_CONFIG, $CC_DBC;
// defaults to retrieving shows from next 2 days if no end time has
// been specified
if($timeEnd == "") {
$timeEnd = "'$timeNow' + INTERVAL '2 days'";
$timeEnd = "'$timeStart' + INTERVAL '2 days'";
} else {
$timeEnd = "'$timeEnd'";
}
@ -1509,45 +1511,15 @@ class Application_Model_Show {
$sql = "SELECT *, si.starts as start_timestamp, si.ends as end_timestamp FROM "
." $CC_CONFIG[showInstances] si, $CC_CONFIG[showTable] s"
." WHERE si.show_id = s.id"
." AND si.starts >= TIMESTAMP '$timeNow'"
." AND si.starts >= TIMESTAMP '$timeStart'"
." AND si.starts < TIMESTAMP $timeEnd"
." ORDER BY si.starts"
." LIMIT $limit";
$rows = $CC_DBC->GetAll($sql);
return $rows;
}
/**
* Given a day of the week variable $day, based in local time, returns the
* shows being played on this day of the week we're in right now.
*
* @param type $day day of the week
* @return type shows being played on this day
*/
public static function GetShowsByDayOfWeek($day){
//DOW FROM TIMESTAMP
//The day of the week (0 - 6; Sunday is 0) (for timestamp values only)
//SELECT EXTRACT(DOW FROM TIMESTAMP '2001-02-16 20:38:40');
//Result: 5
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT"
." si.starts as show_starts,"
." si.ends as show_ends,"
." s.name as show_name,"
." s.url as url"
." FROM $CC_CONFIG[showInstances] si"
." LEFT JOIN $CC_CONFIG[showTable] s"
." ON si.show_id = s.id"
." WHERE EXTRACT(DOW FROM si.starts) = $day"
." AND EXTRACT(WEEK FROM si.starts) = EXTRACT(WEEK FROM localtimestamp)"
." ORDER BY si.starts";
// Convert result timestamps to local timezone
// defaults to retrieve all shows within the interval if $limit not set
if($limit != 0) {
$sql = $sql . " LIMIT $limit";
}
$rows = $CC_DBC->GetAll($sql);
return $rows;
@ -1570,34 +1542,6 @@ class Application_Model_Show {
}
}
/**
* Returns the timezone difference as an INTERVAL string that can be used
* by SQL queries.
*
* E.g., if local timezone is -4:30, this function returns:
* INTERVAL '-4 hours -30 minutes'
*
* Note that if $fromLocalToUtc is true, then it returns:
* INTERVAL '4 hours 30 minutes'
*
* @param type $fromLocalToUtc true if we're converting from local to UTC
*/
/*
public static function GetTimeZoneIntervalString($fromLocalToUtc = false) {
$date = new Application_Model_DateHelper;
$timezoneHour = $date->getLocalOffsetHour();
$timezoneMin = $date->getLocalOffsetMinute();
// negate the hour and min if converting from local to UTC
if($fromLocalToUtc) {
$timezoneHour = -$timezoneHour;
$timezoneMin = -$timezoneMin;
}
return "INTERVAL '$timezoneHour hours $timezoneMin minutes'";
}
* */
public static function GetMaxLengths() {
global $CC_CONFIG, $CC_DBC;
$sql = "SELECT column_name, character_maximum_length FROM information_schema.columns"

View file

@ -203,9 +203,9 @@
var url = daySchedule[j].url;
html +=
'<tr>'+
'<td>'+getTime(daySchedule[j].show_starts)+ " - " + getTime(daySchedule[j].show_ends)+'</td>'+
'<td>'+getTime(daySchedule[j].start_timestamp)+ " - " + getTime(daySchedule[j].end_timestamp)+'</td>'+
'<td>'+
'<h4>'+daySchedule[j].show_name+'</h4>'+
'<h4>'+daySchedule[j].name+'</h4>'+
'</td>'+
'<td>'+
'<ul>'+