PostgreSQL 9.4 – Strange Upper() Behavior for Dateranges

postgresqlpostgresql-9.4range-types

I'm running PostgreSQL 9.4.5 and I've just got an unexpected result from this query:

select  upper(('[2005-12-01,2005-12-04]')::daterange)

It returns 2005-12-05 instead of 2005-12-04.

The following query excludes the upper bound by specifying ) instead of ]:

select  upper(('[2005-12-01,2005-12-04)')::daterange)

It returns 2005-12-04.

Isn't the upper() function supposed to return the upper bound limit of a given range? If so, by specifying [2005-12-01,2005-12-04] as the range, it should return the upper bound which is 2005-12-04. It returns 2005-12-05 instead, which is very odd to me.

Any explanation on why this happens? I only know that '[2005-12-01,2005-12-04]'::daterange is translated by PostgreSQL to '[2005-12-01,2005-12-05)'::daterange, but this doesn't explain why 2005-12-05 should be the upper bound when I have explicitly specified 2005-12-04 as the upper bound.

Best Answer

'[2005-11-01,2005-12-04]' is just another string literal for a date range to represent the canonical form '[2005-11-01,2005-12-05)'. The documentation:

The built-in range types int4range, int8range, and daterange all use a canonical form that includes the lower bound and excludes the upper bound; that is, [).

Bold emphasis mine.

Else you would have two equal values and upper() would still return a different result, which wouldn't be acceptable.