Explain Codes LogoExplain Codes Logo

How to compare dates in datetime fields in Postgresql?

sql
database
postgresql
date-range-comparisons
Alex KataevbyAlex Kataev·Dec 10, 2024
TLDR

In PostgreSQL, use comparison operators with ::date cast for dates or date_trunc for time parts:

Comparison of two dates:

SELECT * FROM your_table WHERE date_column::date = '2023-01-01'; -- Basic date comparison

Ignoring the time in timestamp:

SELECT * FROM your_table WHERE date_trunc('day', date_column) = date_trunc('day', CURRENT_TIMESTAMP); -- The time? Never met her.

Filtering by the current date:

SELECT * FROM your_table WHERE date_column::date = CURRENT_DATE; -- Living in the present

Filtering by year:

SELECT * FROM your_table WHERE EXTRACT(YEAR FROM date_column) = 2023; -- Back to the future!

And for precise date range comparisons:

SELECT * FROM your_table WHERE date_column >= '2023-01-01' AND date_column < '2023-01-02'::date + INTERVAL '1 day'; -- Greedy for the whole day

Crucial date range comparisons

When using date ranges, remember about inclusivity/exclusivity:

SELECT * FROM your_table WHERE date_column BETWEEN '2023-01-01' AND '2023-01-07'; -- Date sandwich with BETWEEN

Timezone matters

Dealing with timezones? Use timestamptz:

SELECT * FROM your_table WHERE date_column AT TIME ZONE 'UTC' BETWEEN '2023-01-01 00:00:00+00' AND '2023-01-07 23:59:59+00'; -- Time travelling with timezone

Handling edge cases

For edge cases, use PostgreSQL's range types and functions:

Non-inclusive upper bounds:

SELECT * FROM your_table WHERE date_column < '2023-01-02'::date + INTERVAL '1 day'; -- Catching those tricky edges

Defining bounds with tsrange:

SELECT * FROM your_table WHERE tsrange(date_column, '2023-01-02'::date + INTERVAL '1 day', '[)') @> date_column; -- TSRange: The Chuck Norris of date ranges

Ensure same data type comparisons:

SELECT * FROM your_table WHERE date_column::date = '2023-01-01'::date; -- Apple to apple, not Apple to orange

Consistent results with TO_DATE & TO_CHAR:

SELECT * FROM your_table WHERE TO_CHAR(date_column, 'YYYY-MM-DD') = '2023-01-01'; -- Nothing to see here, just some fancy formatting.

Advanced examples and best practices

Parts extraction and comparison

In-depth comparison may require extracting parts of dates:

SELECT * FROM your_table WHERE EXTRACT(MONTH FROM date_column) = 1; -- Who said you can’t compare apples and oranges 🍊🍎?

Complex ranged comparisons

Capitalize on daterange for complex comparisons:

SELECT * FROM your_table WHERE daterange(date_column, (date_column + INTERVAL '1 day'), '[]') @> CURRENT_TIMESTAMP; -- I see your date range, and I raise you a TIMESTAMP.

Anomalies handling

Ensure data validity before comparisons:

SELECT * FROM your_table WHERE ISFINITE(date_column); -- ISFINITE: The bouncer of the SQL world 🕶️