How can I store date and time values with **reduced precision** in a PostgreSQL type, and have them **behave as date and/or time values**? ISO 8601 allows date values with reduced precision. ‘1964’, ‘1964-05’, ‘1964-05-02’ are all valid representations of a value, in increasing precision. The Python ‘datetime’ types also allow values with reduced precision in this way. PostgreSQL native time types doesn't allow reduced precision ------------------------------------------------------------ In the native date type, every element of a date must be present or the value is rejected. Setting the elements below the desired precision level to ‘00’ also fails. => SELECT CAST('1964-05-02' AS DATE); date ------------ 1964-05-02 (1 row) => SELECT CAST('1964-05' AS DATE); ERROR: invalid input syntax for type date: "1964-05" LINE 1: SELECT CAST('1964-05' AS DATE); ^ => SELECT CAST('1964' AS DATE); ERROR: invalid input syntax for type date: "1964" LINE 1: SELECT CAST('1964' AS DATE); ^ => SELECT CAST('1964-00-00' AS DATE); ERROR: date/time field value out of range: "1964-00-00" LINE 1: SELECT CAST('1964-00-00' AS DATE); ^ HINT: Perhaps you need a different "datestyle" setting. Expected behaviour for a reduced-precision date and/or time type ---------------------------------------------------------------- Is there a simple, standard way to support entry of ISO 8601 date values with reduced precision into a PostgreSQL date and/or time type? Creating a type for this is possible, but I don't know how. Of course, I need the values to be range checked and deal with timezones and compare sensibly with other time values all the other useful things the built-in types do. What I expect is that, just as the value ‘1964-05-02’ refers to the entire interval between 00:00:00 on that day until 00:00:00 the next day, a reduced-precision value would simply represent a larger interval: ‘1962-05’ refers to the entire interval between 00:00:00 at the beginning of May 1962 until 00:00:00 on the first day of June of 1962. An example of what I'd like to see: => SELECT CAST('1962-05-02 00:00' AS TIMESTAMP) = CAST('1962-05-02 00:00:00' AS TIMESTAMP); ?column? ---------- t (1 row) => SELECT CAST('1962-05' AS TIMESTAMP) = CAST('1962-05-02' AS TIMESTAMP); ?column? ---------- t (1 row) Currently the former behaves as above; the latter complains about “invalid input syntax for type timestamp”. To my eye, they're both cases of reduced-precision values behaving sensibly when compared to finer-precision values. The meaning of `1964-05` in ISO 8601 *includes* the more-precise values `1964-05-02` and `1964-05-02 18:27` and `1964-05-23`. So those should all compare equal.