How to generate a series with the start and end dates of months with Postgres

Tagged generate_series, months, sql  Languages sql
WITH m AS (
  SELECT generate_series(DATE('2010-01-01'), DATE('2010-12-01'), interval '1 month') AS start
)
SELECT m.start, m.start + (interval '1' month) - (interval '1' second) AS end FROM m;
┌────────────────────────┬────────────────────────┐
│         start          │          end           │
├────────────────────────┼────────────────────────┤
│ 2010-01-01 00:00:00+02 │ 2010-01-31 23:59:59+02 │
│ 2010-02-01 00:00:00+02 │ 2010-02-28 23:59:59+02 │
│ 2010-03-01 00:00:00+02 │ 2010-03-31 23:59:59+03 │
│ 2010-04-01 00:00:00+03 │ 2010-04-30 23:59:59+03 │
│ 2010-05-01 00:00:00+03 │ 2010-05-31 23:59:59+03 │
│ 2010-06-01 00:00:00+03 │ 2010-06-30 23:59:59+03 │
│ 2010-07-01 00:00:00+03 │ 2010-07-31 23:59:59+03 │
│ 2010-08-01 00:00:00+03 │ 2010-08-31 23:59:59+03 │
│ 2010-09-01 00:00:00+03 │ 2010-09-30 23:59:59+03 │
│ 2010-10-01 00:00:00+03 │ 2010-10-31 23:59:59+02 │
│ 2010-11-01 00:00:00+02 │ 2010-11-30 23:59:59+02 │
│ 2010-12-01 00:00:00+02 │ 2010-12-31 23:59:59+02 │
└────────────────────────┴────────────────────────┘

Same query without the CTE:

SELECT start, start + (interval '1' month) - (interval '1' second) AS end FROM (
  SELECT generate_series(DATE('2010-01-01'), DATE('2010-12-01'), interval '1 month') AS start
) months;