Here's a shorter version:
On the date variant, I wasn't sure how to handle intervals with parts
smaller than days:
floor, ceiling, round or error out
To get round, the last parameters of generate_series would be
extract('epoch' FROM '1 day'::interval)::bigint * round(extract('epoch' FROM
$3) / extract('epoch' FROM '1 day'::interval))::bigint
CREATE OR REPLACE FUNCTION generate_series ( start_ts timestamptz, end_ts timestamptz, step interval
) RETURNS SETOF timestamptz
STRICT
LANGUAGE sql
AS $$
SELECT 'epoch'::timestamptz + s.i * '1 second'::interval AS "generate_series"
FROM generate_series( extract('epoch' FROM $1)::bigint, extract('epoch' FROM $2)::bigint,
extract('epoch'FROM $3)::bigint ) s(i);
$$;
CREATE OR REPLACE FUNCTION generate_series ( start_ts date, end_ts date, step interval
) RETURNS SETOF date
STRICT
LANGUAGE sql
AS $$
SELECT ('epoch'::date + s.i * '1 second'::interval)::date AS "generate_series"
FROM generate_series( extract('epoch' FROM $1)::bigint, extract('epoch' FROM $2)::bigint,
extract('epoch'FROM date_trunc('day', $3))::bigint -- does a floor ) s(i);
$$;
Jean-Pierre Pelletier
e-djuster