Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a new date range type with included upper bound in Postgres?

Postgres comes with a nice feature called Range Types that provides useful range functionality (overlaps, contains, etc).

I am looking to use the daterange type, however I think the type was implemented with an awkward choice: the upper bound of the daterange is excluded. That means that if I defined my value as 2014/01/01 - 2014/01/31, this is displayed as [2014/01/01, 2014/01/31) and the 31st of January is excluded from the range!

I think this was the wrong default choice here. I cannot think of any application or reference in real life that assumes that the end date of a date range is excluded. At least not to my experience.

I want to implement a range type for dates with both lower and upper bounds included, but I am hitting the Postgres documentation wall: References on how to create a new discrete range type are cryptic and lack any examples (taken from the documentation: Creating a canonical function is a bit tricky, since it must be defined before the range type can be declared).

Can someone provide some help on this? Or even directly the implementation itself; it should be 5-10 lines of code, but putting these 5-10 lines together is a serious research effort.

EDIT: Clarification: I am looking for information on how to create the proper type so that inserting [2014/01/01, 2014/01/31] results in a upper(daterange) = '2014/01/31'. With the existing daterange type this value is "converted" to a [2014/01/01, 2014/02/01) and gives a upper(daterange) = '2014/02/01'

like image 555
dtheodor Avatar asked Apr 27 '15 11:04

dtheodor


People also ask

What formats are allowable for date formats in PostgreSQL?

Postgres uses the DATE data type for storing different dates in YYYY-MM-DD format. It uses 4 bytes for storing a date value in a column. You can design a Postgres table with a DATE column and use the keyword DEFAULT CURRENT_DATE to use the current system date as the default value in this column.

How do I select data between two dates in PostgreSQL?

Use the PostgreSQL AGE() function to retrieve the interval between two timestamps or dates. This function takes two arguments: the first is the end date and the second is the start date.

What does @> mean in Postgres?

In general @> is the "contains" operator. It is defined for several data types.

What is Tsrange?

Range types are data types representing a range of values of some element type (called the range's subtype). For instance, ranges of timestamp might be used to represent the ranges of time that a meeting room is reserved. In this case the data type is tsrange (short for “timestamp range”), and timestamp is the subtype.


1 Answers

Notice the third constructor parameter:

select daterange('2014/01/01', '2014/01/31', '[]');
        daterange        
-------------------------
 [2014-01-01,2014-02-01)

Or a direct cast with the upper bound included:

select '[2014/01/01, 2014/01/31]'::daterange;
        daterange        
-------------------------
 [2014-01-01,2014-02-01)

Edit

Not a new type (wrong approach IMHO) but a proper function:

create function inclusive_upper_daterange(dtr daterange)
returns date as $$

    select upper(dtr) - 1;

$$ language sql immutable;

select inclusive_upper_daterange('[2014/01/01, 2014/01/31]'::daterange);
 inclusive_upper_daterange 
---------------------------
 2014-01-31
like image 117
Clodoaldo Neto Avatar answered Sep 23 '22 08:09

Clodoaldo Neto