How to handle time zones in complicated queries?
I have the following code... that will essentially tell me how many many behaviors happened for a given day, but will also return 0s for days where no behaviors are stored. My question is two-fold:
(1) This was some of my earlier code and so I am thinking about cleaning this up, refactoring ~ are there any design patterns that I should use here? Or is this fine?
(2) All dates are stored in UTC, so I need to change the query to account for time zone. Otherwise the charts will show behaviors on the UTC dates, and not the local dates. So I was thinking I could just modify the following part:
b.created_at < d.generated_date + INTERVAL 1 DAY AND to account for the diff between their local time and utc? Is there a cleaner better way to think about this?
Thanks in advance.
protected function getBehaviors(Child $child, int $daysBack, $operator = '>=', $typeID = null)
{
$typeWhere = ($typeID) ? 'b.behavior_type_id = ' . $typeID . ' AND': '';
return DB::select($this->getRecursiveDatesQuery() . "
LEFT JOIN behaviors b
ON b.child_id = :child_id AND
b.created_at >= d.generated_date AND
" . $typeWhere . "
b.created_at < d.generated_date + INTERVAL 1 DAY AND
b.value " . $operator . " 0
GROUP BY
d.generated_date
ORDER BY
d.generated_date ASC
", ['child_id' => $child->id, 'days' => ($daysBack - 1)]);
}
private function getRecursiveDatesQuery()
{
return "WITH RECURSIVE dates as (
SELECT
CURDATE() as generated_date,
1 as days
UNION ALL
SELECT
generated_date - interval 1 day,
days + 1
FROM
dates
WHERE
days <= :days
)
SELECT
DATE_FORMAT(d.generated_date, '%m/%d') as created_day,
COALESCE(COUNT(b.id), 0) as total
FROM
dates d";
}
Please or to participate in this conversation.