I have a table with a field called recordTime
of type timestamp without time zone
. I want to select today's rows only (i.e. since midnight). The records are sourced globally and arrive as UTC, so I need to select rows based on midnight UTC.
There seems to be a myriad of ways of doing this including ...
WHERE date_trunc('day', recordTime) = current_date ;
WHERE date_trunc('day', recordTime) = date_trunc('day', current_date at time zone 'utc')
WHERE date_trunc('day', recordTime) = date_trunc('day', current_timestamp at time zone 'utc')
WHERE recordTime >= '17-May-2024 00:00:00'
Which of these is best practice - or maybe a different method entirely? (Bearing in mind that performance seems similar in all cases.)
WHERE recordtime >= date_trunc('day', now() AT TIME ZONE 'UTC')
AND recordtime < date_trunc('day', now() AT TIME ZONE 'UTC') + interval '1 day';
The 2nd line is optional if there cannot be rows past "today" in the table. (Would waste only very little performance in that case.)
The definition of "today" depends on the current time zone. Use the AT TIME ZONE
construct.
date_trunc('day', now() AT TIME ZONE 'UTC')
gets the start of the current day at time zone UTC. See:
now()
is Postgres short syntax for standard SQL current_timestamp
. See:
Include the starting 00:00, but exclude the ending 00:00.
Don't use BETWEEN
with timestamp types.
Make the expression sargable. I.e., compare the bare column to a (computed) constant, not the other way round. Better in any case, especially to use a B-tree index on recordtime
, which you should have unless the table is trivially small.
If you are sure the timezone
setting of the current session is 'UTC'.
One way to make sure is to set it yourself in the same transaction:
BEGIN;
SET timezone = 'UTC';
...
WHERE recordtime >= current_date
AND recordtime < current_date + 1;
You can add integer
to a date
to add days. And date
is coerced to the column type timestamp [without time zone]
cleanly in the expression.
If time zones can be involved in any way, it's typically better to work with timestamptz
columns to begin with. Then, to get rows for "today in the time zone UTC", use the convenient variant of date_trunc()
taking the time zone as 3rd parameter (since Postgres 12):
WHERE recordtime >= date_trunc('day', now(), 'UTC')
AND recordtime < date_trunc('day', now(), 'UTC') + interval '1 day';
Avoid mixed-case identifier in Postgres if at all possible. Else, you introduce uncertainty whether it's really recordtime
or "recordTime"
. See: