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'
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.
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.
In general @> is the "contains" operator. It is defined for several data types.
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.
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)
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With