PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Diferenças do Rails/Postgresql SQL com datas


A versão de generate_series que você está usando está trabalhando com timestamps, não com datas. Portanto, seu '2012-10-14' e current_date estão sendo convertidos para timestamp with time zone se generate_series está produzindo um conjunto de timestamp with time zone s; compare estes:
=> 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)

O primeiro tem fusos horários, o segundo não.

Mas, o current_date sempre é convertido em um carimbo de data/hora com o ajuste de fuso horário da sessão do banco de dados aplicado. A sessão do Rails irá conversar com o banco de dados em UTC, seu psql sessão provavelmente está usando ET.

Se você especificar manualmente a data atual e trabalhar explicitamente com timestamp s:
select generate_series('2012-10-14'::timestamp, '2012-10-20'::timestamp, '1 day')

então você obterá os mesmos sete resultados em ambos porque não há fuso horário à vista para bagunçar as coisas.

A maneira mais fácil de ignorar os fusos horários é usar a versão inteira de generate_series e o fato de que adicionar um inteiro a uma data trata o inteiro como um número de dias:
select '2012-10-14'::date + generate_series(0, 6)

Isso lhe dará os mesmos sete dias sem interferência de fuso horário. Você ainda pode usar o current_date (que não tem fuso horário, pois as datas SQL não têm fusos horários) observando que a diferença entre duas datas é o número de dias entre elas (um inteiro):
=> 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 dos trilhos:
> 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, eu odeio fusos horários, odeio e desprezo-los.