Vous attendiez 1-01-01 ... 1-12-31
... mais comment PostgreSQL est-il censé savoir ce que vous entendez par là ?
Les littéraux de chaîne d'entrée sont interprétés en fonction des paramètres de votre session actuelle (qui sont par défaut les paramètres généraux dans postgressql.conf
sauf dérogation). En particulier datestyle
:
DateStyle
(string
)Définit le format d'affichage des valeurs de date et d'heure, ainsi que les règles d'interprétation des valeurs d'entrée de date ambiguës. Pour des raisons historiques, cette variable contient deux composants indépendants :la spécification du format de sortie (
ISO
,Postgres
,SQL
, ouGerman
) et la spécification d'entrée/sortie pour la commande année/mois/jour (DMY
,MDY
,ouYMD
). Ceux-ci peuvent être réglés séparément ou ensemble. Les mots-clésEuro
etEuropean
sont synonymes deDMY
; les mots clésUS
,NonEuro
, etNonEuropean
sont synonymes deMDY
. Voir Section 8.5 pour plus d'informations. La valeur par défaut intégrée estISO, MDY
, mais initdb initialisera le fichier de configuration avec un paramètre qui correspond au comportement dulc_time
choisi locale.
(Alors que le format de sortie est principalement déterminé par lc_time
.)
Dans votre cas, le littéral d'horodatage mutilé 1-12-31 23:59:59
est évidemment interprété comme :
D-MM-YY h24:mi:ss
Alors que vous auriez espéré :
Y-MM-DD h24:mi:ss
3 options
-
Définir
datestyle
afin qu'il interprète les littéraux de la même manière que vous. Peut-êtreISO, YMD
? -
Utilisez
to_timestamp()
pour interpréter la chaîne littérale d'une manière bien définie - indépendamment des autres paramètres. Beaucoup mieux.SELECT to_timestamp('1-12-31 23:59:59', 'Y-MM-DD h24:mi:ss');
-
Mieux encore, utilisez le format ISO 8601 (
YYYY-MM-DD
) pour tous les littéraux datetime. C'est sans ambiguïté et indépendant de tout paramètre .SELECT '2001-12-31 23:59:59'::timestamp;
Réécrire la requête
Votre requête est erronée pour commencer. Gérez les requêtes de plage différemment. Comme :
SELECT d.given_on
FROM documents_document d
WHERE EXTRACT('month' FROM d.given_on) = 1
AND d.given_on >= '2001-01-01 0:0'
AND d.given_on < '2002-01-01 0:0'
ORDER BY d.created_on DESC;
Ou, plus simple encore :
SELECT d.given_on
FROM documents_document d
WHERE d.given_on >= '2001-01-01 0:0'
AND d.given_on < '2001-02-01 0:0'
ORDER BY d.created_on DESC;
Les types de plage dans PostgreSQL 9.2 ou plus récent peuvent être intéressants.