PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Différences Rails/Postgresql SQL avec les dates

La version de generate_series que vous utilisez travaille avec des horodatages, pas des dates. Donc votre '2012-10-14' et current_date sont convertis en timestamp with time zone s et generate_series produit un ensemble de timestamp with time zone s ; comparez-les :

=> select generate_series('2012-10-14', current_date, '1 day');
    generate_series     
------------------------
 2012-10-14 00:00:00-07
 2012-10-15 00:00:00-07
 2012-10-16 00:00:00-07
 2012-10-17 00:00:00-07
 2012-10-18 00:00:00-07
 2012-10-19 00:00:00-07
 2012-10-20 00:00:00-07
(7 rows)

=> select generate_series('2012-10-14', current_date::timestamp, '1 day');
   generate_series   
---------------------
 2012-10-14 00:00:00
 2012-10-15 00:00:00
 2012-10-16 00:00:00
 2012-10-17 00:00:00
 2012-10-18 00:00:00
 2012-10-19 00:00:00
 2012-10-20 00:00:00
(7 rows)

Le premier a des fuseaux horaires, le second non.

Mais, la current_date est toujours converti en un horodatage avec l'ajustement du fuseau horaire de la session de base de données appliqué. La session Rails parlera à la base de données en UTC, votre psql la session utilise probablement ET.

Si vous spécifiez manuellement la date actuelle et travaillez explicitement avec timestamp s :

select generate_series('2012-10-14'::timestamp, '2012-10-20'::timestamp, '1 day')

alors vous obtiendrez les sept mêmes résultats dans les deux, car il n'y a pas de fuseau horaire en vue pour gâcher les choses.

Le moyen le plus simple d'ignorer les fuseaux horaires est d'utiliser la version entière de generate_series et le fait que l'ajout d'un entier à une date traite l'entier comme un nombre de jours :

select '2012-10-14'::date + generate_series(0, 6)

Cela vous donnera les mêmes sept jours sans interférence de fuseau horaire. Vous pouvez toujours utiliser la current_date (qui n'a pas de fuseau horaire puisque les dates SQL n'ont pas de fuseau horaire) en notant que la différence entre deux dates est le nombre de jours qui les séparent (un entier) :

=> select '2012-10-14'::date + generate_series(0, current_date - '2012-10-14');
  ?column?  
------------
 2012-10-14
 2012-10-15
 2012-10-16
 2012-10-17
 2012-10-18
 2012-10-19
 2012-10-20
(7 rows)

et depuis Rails :

> pp ActiveRecord::Base.connection.execute("select '2012-10-14'::date + generate_series(0, 6)").to_a
[{"?column?"=>"2012-10-14"},
 {"?column?"=>"2012-10-15"},
 {"?column?"=>"2012-10-16"},
 {"?column?"=>"2012-10-17"},
 {"?column?"=>"2012-10-18"},
 {"?column?"=>"2012-10-19"},
 {"?column?"=>"2012-10-20"}]

BTW, je déteste les fuseaux horaires, les déteste et les méprise.