Consider the following query:
SELECT
INTERVAL '1 month' * v AS i,
EXTRACT(YEAR FROM INTERVAL '1 month' * v) AS y,
EXTRACT(QUARTER FROM INTERVAL '1 month' * v) AS q,
EXTRACT(MONTH FROM INTERVAL '1 month' * v) AS m
FROM generate_series(0, 16) t(v)
It yields, to my surprise:
i |y|q|m |
-------------|-|-|--|
00:00:00|0|1| 0|
1 mon|0|1| 1|
2 mons|0|1| 2|
3 mons|0|2| 3|
4 mons|0|2| 4|
5 mons|0|2| 5|
6 mons|0|3| 6|
7 mons|0|3| 7|
8 mons|0|3| 8|
9 mons|0|4| 9|
10 mons|0|4|10|
11 mons|0|4|11|
1 year|1|1| 0|
1 year 1 mon|1|1| 1|
1 year 2 mons|1|1| 2|
1 year 3 mons|1|2| 3|
1 year 4 mons|1|2| 4|
So, when extracting a QUARTER from such a "normalized" INTERVAL (produced by an INTERVAL '1 month' * <some integer> expression), we get values 1-4 (as if this extraction were somehow 1-based), whereas extracting a YEAR or MONTH from an INTERVAL produces values 0-N (YEAR) or 0-11 (MONTH), respectively.
What's the rationale behind this behaviour and is it documented? (I do not think it is documented here, explicitly)