PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Differenze tra Rails/Postgresql SQL con date

La versione di generate_series che stai utilizzando sta lavorando con timestamp, non date. Quindi il tuo '2012-10-14' e current_date vengono convertiti in timestamp with time zone se generate_series sta producendo una serie di timestamp with time zone S; confronta questi:

=> 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)

Il primo ha i fusi orari, il secondo no.

Ma, il current_date viene sempre convertito in un timestamp con la regolazione del fuso orario della sessione del database applicata. La sessione di Rails parlerà con il database in UTC, il tuo psql probabilmente sta usando ET.

Se specifichi manualmente la data corrente e lavori in modo esplicito con timestamp s:

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

quindi otterrai gli stessi sette risultati in entrambi perché non c'è nessun fuso orario in vista per fare un pasticcio di cose.

Il modo più semplice per ignorare i fusi orari è utilizzare la versione intera di generate_series e il fatto che l'aggiunta di un numero intero a una data considera il numero intero come un numero di giorni:

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

Questo ti darà gli stessi sette giorni senza interferenze di fuso orario. Puoi ancora utilizzare il current_date (che non ha fuso orario poiché le date SQL non hanno fusi orari) notando che la differenza tra due date è il numero di giorni tra loro (un numero intero):

=> 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)

e da 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"}]

A proposito, odio i fusi orari, li odio e li disprezzo.