Отличный SQL запрос для PostgreSQL, который строит календарь дат на 10 лет, начиная с числа указанного в самом конце запроса:
SELECT
datum AS Date,
extract(year FROM datum) AS Year,
extract(month FROM datum) AS Month,
-- Localized month name
to_char(datum, 'TMMonth') AS MonthName,
extract(day FROM datum) AS Day,
extract(doy FROM datum) AS DayOfYear,
-- Localized weekday
to_char(datum, 'TMDay') AS WeekdayName,
-- ISO calendar week
extract(week FROM datum) AS CalendarWeek,
to_char(datum, 'dd. mm. yyyy') AS FormattedDate,
'Q' || to_char(datum, 'Q') AS Quartal,
to_char(datum, 'yyyy/"Q"Q') AS YearQuartal,
to_char(datum, 'yyyy/mm') AS YearMonth,
-- ISO calendar year and week
to_char(datum, 'iyyy/IW') AS YearCalendarWeek,
-- Weekend
CASE WHEN extract(isodow FROM datum) IN (6, 7) THEN 'Weekend' ELSE 'Weekday' END AS Weekend,
-- Fixed holidays
-- for America
CASE WHEN to_char(datum, 'MMDD') IN ('0101', '0704', '1225', '1226')
THEN 'Holiday' ELSE 'No holiday' END
AS AmericanHoliday,
-- for Austria
CASE WHEN to_char(datum, 'MMDD') IN
('0101', '0106', '0501', '0815', '1101', '1208', '1225', '1226')
THEN 'Holiday' ELSE 'No holiday' END
AS AustrianHoliday,
-- for Canada
CASE WHEN to_char(datum, 'MMDD') IN ('0101', '0701', '1225', '1226')
THEN 'Holiday' ELSE 'No holiday' END
AS CanadianHoliday,
-- Some periods of the year, adjust for your organisation and country
CASE WHEN to_char(datum, 'MMDD') BETWEEN '0701' AND '0831' THEN 'Summer break'
WHEN to_char(datum, 'MMDD') BETWEEN '1115' AND '1225' THEN 'Christmas season'
WHEN to_char(datum, 'MMDD') > '1225' OR to_char(datum, 'MMDD') <= '0106' THEN 'Winter break'
ELSE 'Normal' END
AS Period,
-- ISO start and end of the week of this date
datum + (1 - extract(isodow FROM datum))::integer AS CWStart,
datum + (7 - extract(isodow FROM datum))::integer AS CWEnd,
-- Start and end of the month of this date
datum + (1 - extract(day FROM datum))::integer AS MonthStart,
(datum + (1 - extract(day FROM datum))::integer + '1 month'::interval)::date - '1 day'::interval AS MonthEnd
FROM (
-- There are 3 leap years in this range, so calculate 365 * 10 + 3 records
SELECT '2010-01-01'::DATE + sequence.day AS datum
FROM generate_series(0,3652) AS sequence(day)
GROUP BY sequence.day
) DQ
ORDER BY 1
Источник: