sql >> Base de Datos >  >> RDS >> PostgreSQL

Diferencias de Rails/Postgresql SQL con fechas

La versión de generate_series que está utilizando está trabajando con marcas de tiempo, no con fechas. Así que tu '2012-10-14' y current_date se están convirtiendo a timestamp with time zone s y generate_series está produciendo un conjunto de timestamp with time zone s; comparar estos:

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

El primero tiene zonas horarias, el segundo no.

Pero, la current_date siempre se convierte en una marca de tiempo con el ajuste de zona horaria de la sesión de la base de datos aplicado. La sesión de Rails se comunicará con la base de datos en UTC, su psql probablemente la sesión esté usando ET.

Si especifica manualmente la fecha actual y trabaja explícitamente con timestamp s:

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

entonces obtendrás los mismos siete resultados en ambos porque no hay una zona horaria a la vista para complicar las cosas.

La forma más fácil de ignorar las zonas horarias es usar la versión entera de generate_series y el hecho de que sumar un número entero a una fecha trata al número entero como un número de días:

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

Eso le dará los mismos siete días sin interferencia de zona horaria. Todavía puedes usar la current_date (que no tiene zona horaria ya que las fechas SQL no tienen zonas horarias) observando que la diferencia entre dos fechas es el número de días entre ellas (un número entero):

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

y de Rieles:

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

Por cierto, odio las zonas horarias, las odio y las desprecio.