Here’s a quick snippet that I wrote because I needed a media calendar that covers the time period of most living people. Hopes this helps keep somebody from typing this up themselves.
CREATE TABLE calendar (id bigserial primary key,
gregorian_date date not null,
long_date text,
day_of_week text,
day_in_week smallint,
day_number_in_month smallint,
day_number_in_year smallint,
last_day_in_week boolean,
last_day_in_month boolean,
week_ending_day date,
month_ending_day date,
week_in_month smallint,
week_in_year smallint,
month_name text,
month_number smallint,
year_month text,
quarter text,
year_quarter text,
year_number smallint,
roman_year text,
roman_month text,
roman_day text,
load_date timestamp with time zone NOT NULL DEFAULT now())
;
COMMENT ON COLUMN calendar.gregorian_date IS 'Date in current calendar';
COMMENT ON COLUMN calendar.long_date IS 'Date in full formal notation';
COMMENT ON COLUMN calendar.day_of_week IS 'Text representation of the day of week';
COMMENT ON COLUMN calendar.day_in_week IS 'Numeric position of the day in the week';
COMMENT ON COLUMN calendar.day_number_in_month IS 'Numeric position of the day in the month';
COMMENT ON COLUMN calendar.day_number_in_year IS 'Numeric position of the day within the year';
COMMENT ON COLUMN calendar.last_day_in_week IS 'Is this the last day of the week';
COMMENT ON COLUMN calendar.last_day_in_month IS 'Is this the last day of the month';
COMMENT ON COLUMN calendar.week_ending_day IS 'What is the date of Saturday in this week';
COMMENT ON COLUMN calendar.month_ending_day IS 'Is this the last day of the week (saturday)';
COMMENT ON COLUMN calendar.week_in_month IS 'Numeric position of the week in the month';
COMMENT ON COLUMN calendar.week_in_year IS 'Numeric position of the week in the year';
COMMENT ON COLUMN calendar.month_name IS 'Text name of the month';
COMMENT ON COLUMN calendar.month_number IS 'Numeric value of the month in year';
COMMENT ON COLUMN calendar.year_month IS 'YYYY-MM formatted';
COMMENT ON COLUMN calendar.quarter IS 'Q1 - Q4';
COMMENT ON COLUMN calendar.year_quarter IS 'YYYY-Q(1-4)';
COMMENT ON COLUMN calendar.year_number IS 'Year as an integer';
COMMENT ON COLUMN calendar.load_date IS 'the timestamp when this row was created';
CREATE OR REPLACE FUNCTION media_calendar () RETURNS TRIGGER
AS $$
BEGIN
NEW.long_date := to_char(NEW.gregorian_date, 'FMDay, the FMDDth of FMMonth, YYYY');
NEW.day_of_week := to_char(NEW.gregorian_date, 'Day');
NEW.day_in_week := to_char(NEW.gregorian_date, 'D')::smallint;
NEW.day_number_in_month := to_char(NEW.gregorian_date, 'DD')::smallint;
NEW.day_number_in_year := to_char(NEW.gregorian_date, 'DDD')::smallint;
NEW.month_ending_day := to_char(NEW.gregorian_date + interval '1 month', 'YYYY-MM-01')::date -1; -- (to_char(NEW.gregorian_date, 'YYYY') || '-' || (to_char(NEW.gregorian_date, 'MM')::integer + 1)::text || '-01')::date -1;
NEW.last_day_in_month := NEW.gregorian_date = NEW.month_ending_day;
NEW.week_ending_day := NEW.gregorian_date + (7 - NEW.day_in_week);
NEW.last_day_in_week := NEW.gregorian_date = NEW.week_ending_day;
NEW.week_in_month := to_char(NEW.gregorian_date, 'W')::smallint;
NEW.week_in_year := to_char(NEW.gregorian_date, 'WW')::smallint;
NEW.month_name := to_char(NEW.gregorian_date, 'Month');
NEW.month_number := to_char(NEW.gregorian_date, 'MM')::smallint;
NEW.year_month := to_char(NEW.gregorian_date, 'YYYY-MM');
NEW.quarter := 'Q' || to_char(NEW.gregorian_date, 'Q');
NEW.year_quarter := to_char(NEW.gregorian_date, 'YYYY') || '-' || NEW.quarter;
NEW.year_number := to_char(NEW.gregorian_date, 'YYYY')::smallint;
NEW.roman_year := to_char(to_char(NEW.gregorian_date, 'YYYY')::integer, 'FMRN');
NEW.roman_month := to_char(NEW.gregorian_date, 'RM');
NEW.roman_day := to_char(to_char(NEW.gregorian_date, 'DD')::integer, 'FMRN');
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
CREATE TRIGGER media_calendar
BEFORE INSERT ON calendar
FOR EACH ROW EXECUTE PROCEDURE media_calendar();
--covers 1890-01-01 to 2099-12-31
INSERT INTO calendar (gregorian_date) select '1890-01-01'::date + s.a as dates from generate_series(0,76700,1) as s(a);
CREATE UNIQUE INDEX idx_calendar_gregorian ON calendar(gregorian_date);
CLUSTER calendar USING idx_calendar_gregorian;