sql >> Database >  >> RDS >> PostgreSQL

Rails/Postgresql SQL-verschillen met datums

De versie van generate_series die u gebruikt, werkt met tijdstempels, niet met datums. Dus uw '2012-10-14' en current_date worden geconverteerd naar timestamp with time zone s en generate_series produceert een set timestamp with time zone s; vergelijk deze:

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

De eerste heeft tijdzones, de tweede niet.

Maar de current_date wordt altijd geconverteerd naar een tijdstempel waarop de tijdzone-aanpassing van de databasesessie is toegepast. De Rails-sessie praat met de database in UTC, uw psql sessie gebruikt waarschijnlijk ET.

Als u handmatig de huidige datum opgeeft en expliciet werkt met timestamp s:

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

dan krijg je in beide dezelfde zeven resultaten omdat er geen tijdzone in zicht is om er een zooitje van te maken.

De gemakkelijkste manier om tijdzones te negeren, is door de integer-versie van generate_series te gebruiken en het feit dat het toevoegen van een geheel getal aan een datum het gehele getal behandelt als een aantal dagen:

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

Dat geeft je dezelfde zeven dagen zonder tijdzone-interferentie. Je kunt nog steeds de current_date . gebruiken (die geen tijdzone heeft aangezien SQL-datums geen tijdzones hebben) door op te merken dat het verschil tussen twee datums het aantal dagen ertussen is (een geheel getal):

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

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

Trouwens, ik haat tijdzones, haat en veracht ze.




  1. Intermitterende ODBC-verbindingsfouten

  2. T-SQL:hoe parameters gebruiken in dynamische SQL?

  3. Hoe de naamreeks in mysql te splitsen?

  4. Veelgestelde vragen over JAVA/JRE in Oracle Apps