2012-10-21 28 views
5

Khi chạy truy vấn sau đây trong psql tôi nhận lại 7 kết quả:Rails/PostgreSQL SQL khác biệt w/Ngày

SELECT generate_series('2012-10-14', CURRENT_DATE, interval '1 day'); # 7 

Tuy nhiên khi tôi chạy truy vấn chính xác như nhau trong ứng dụng ray của tôi, tôi nhận được 8 kết quả:

result = ActiveRecord::Base.connection.execute "SELECT generate_series('2012-10-14', CURRENT_DATE, interval '1 day');" 
puts result.count # 8 

Dường như điều này có gì đó để làm với các múi giờ nhưng tôi không biết vấn đề có thể là gì. Tôi đã điều sau đây trong application.rb tôi

config.time_zone = 'Eastern Time (US & Canada)' 

Đây là cùng một cài đặt múi giờ mà tôi có trong postgresql.conf tôi

Tôi đang bối rối tại tại sao ứng dụng ray của tôi là thêm một ngày bổ sung cho kết quả của tôi. Bất cứ ai có thể cung cấp một số cái nhìn sâu sắc?

Điều này dường như chỉ xảy ra vào cuối ngày (sau 8 giờ tối) vì vậy đây là điều khiến tôi nghĩ rằng đó là điều gì đó có thời gian bù giờ.

Trả lời

9

Phiên bản generate_series mà bạn đang sử dụng đang hoạt động với dấu thời gian, không phải ngày tháng. Vì vậy, '2012-10-14'current_date của bạn đang được chuyển đổi thành timestamp with time zone s và generate_series đang sản xuất một bộ timestamp with time zone s; so sánh chúng:

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

Thứ nhất có múi giờ, múi giờ thứ hai không có múi giờ thứ hai.

Nhưng, current_date luôn được chuyển đổi thành dấu thời gian với điều chỉnh múi giờ của phiên cơ sở dữ liệu được áp dụng. Phiên Rails sẽ nói chuyện với cơ sở dữ liệu trong UTC, phiên psql của bạn có thể đang sử dụng ET.

Nếu bạn tự xác định ngày hiện tại và rõ ràng làm việc với timestamp s:

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

sau đó bạn sẽ nhận được cùng Bảy kết quả trong cả hai vì không có múi giờ trong tầm nhìn để làm cho một mớ hỗn độn của sự vật.

Cách dễ nhất để bỏ qua các múi giờ là sử dụng phiên bản nguyên của generate_series và thực tế rằng việc thêm một số nguyên cho một ngày xử lý các số nguyên như một số ngày:

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

Điều đó sẽ cung cấp cho bạn cùng bảy ngày không có nhiễu múi giờ. Bạn vẫn có thể sử dụng current_date (mà không có múi giờ kể từ ngày SQL không có múi giờ) bằng cách ghi nhận rằng sự khác biệt giữa hai ngày là số ngày giữa chúng (một số nguyên):

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

và từ 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, tôi ghét múi giờ, ghét và coi thường chúng.

+2

+1 Giải thích tuyệt vời. BTW, tôi bảo lưu * hận thù * của tôi cho khái niệm đạo đức của DST (tiết kiệm ánh sáng ban ngày) mà không tiết kiệm ánh sáng ban ngày cũng không có ý nghĩa gì cả. Chỉ cần lãng phí rất nhiều thời gian trên toàn thế giới bằng cách gây nhầm lẫn. DST nên được loại bỏ khỏi sự tồn tại và không bao giờ được đề cập một lần nữa. –

+2

@ErwinBrandstetter: Tôi không thể nói về DST trong một diễn đàn công cộng không khuyến khích chửi thề, tôi không thể làm điều đó. –

+0

Cảm ơn bạn đã giải thích sâu sắc, mặc dù nó chỉ khiến tôi ghét múi giờ nhiều hơn thế nữa;) –

Các vấn đề liên quan