2012-08-22 18 views
1

事件有很多轉變。Rails + Postgres:沒有返回來自已加入表格的列的時區信息

我的班次表,其中包含DATETIME格式的starts_atends_at列。

如果我查詢位移表中,starts_atends_at列返回其包含時區信息,並且由導軌作爲ActiveSupport::TimeWithZone對象識別的串 - 並我可以相應地進行操作。

如果我在包含連接的更復雜查詢中包含shifts.starts_atshifts.ends_at列,我似乎失去了結果集中的時區信息。考慮下面的查詢:

SELECT events.id, events.name, events.default_shift_start, 
shifts.id AS shift_id, shifts.starts_at, shifts.ends_at, users.id AS user_id, 
users.first_name, users.last_name 
FROM "events" 
INNER JOIN "shifts" ON "shifts"."event_id" = "events"."id" 
INNER JOIN "requests" ON "requests"."shift_id" = "shifts"."id" 
INNER JOIN "users" ON "users"."id" = "requests"."user_id" 
WHERE (events.default_shift_start > '2012-08-22 05:55:22.069340' AND requests.status = 'accepted') 
ORDER BY default_shift_start ASC 

編輯:我用的方式調用Rails的這個查詢:

Event.joins(:shifts => { :requests => :user}).where(["events.default_shift_start > ? AND requests.status = ?", Time.now, "accepted"]).select("events.id, events.name, events.default_shift_start, shifts.id AS shift_id, shifts.starts_at, shifts.ends_at, users.id AS user_id, users.first_name, users.last_name").order("default_shift_start ASC") 

產地:

 
+-----+----------+---------------------+---------------------+ 
| id | shift_id | starts_at   | ends_at    | 
+-----+----------+---------------------+---------------------+ 
| 17 | 80  | 2012-08-23 00:30:00 | 2012-08-23 07:30:00 | 
| 17 | 55  | 2012-08-23 00:30:00 | 2012-08-23 07:30:00 | 
+-----+----------+---------------------+---------------------+ 

的問題是列從JOINed表(shifts)不返回任何時區數據,導致Rails將它們識別爲字符串數據。數據以UTC格式存儲在數據庫中。如果我在同一個查詢中包含events表中的datetime列,它將在結果中包含時區數據。

我一直在搜索文件試圖瞭解這裏發生了什麼,但無濟於事。

+0

請在psql中顯示您的表定義,或者CREATE TABLE語句或'\ d tablename'的輸出。是否有可能使用'timestamp'和'timestamptz'類型的組合,而Rails只喜歡其中之一? –

+0

@CraigRinger:Rails意味着'沒有時區的時間戳'和數據庫中的UTC值。 –

+0

按照要求定義表格[此處](https://gist.github.com/3424581)。這些列是沒有時區格式的時間戳 - 這確實看起來像是一個Rails問題,與Postgres相反。由於某些原因,從JOINed表中選擇的列未被識別爲通常的類型。請注意,如果我直接從班次表中選擇,我沒有這樣的問題。 –

回答

2

我想你應該開始掌握所涉及的數據類型。 PostgreSQL中的「datetime」數據類型實際上是timestamp and there are two variants: with and without time zone。默認值是without

在內部,PostgreSQL總是存儲UTC時間戳。時區數據本身是而不是有時間戳保存,既沒有時區也沒有時區。這些只是用於輸入和輸出的裝飾器,以適應客戶端的時區設置。

查找更多detailed explanation, examples and links at this related answer

+1

謝謝,歐文。我目前通過在Rails中使用'to_time'來轉換生成的'String'來解決這個問題。我確信這是一個Railsism,這是因爲在我用來查詢的對象('Event')的模式中不存在連接列(來自'shift'表)的事實。 –

0

我想如果你把starts_at :: timestamptz那麼你很好。

+0

我的猜測是你要求事件默認給予你timestamptz,但是因爲在你的查詢中你通過字符串進行了比較,所以它將列轉換爲字符串。嘗試'2012-08-22 05:55:22.069340':: timestamp。 – Kasumi

+0

它確實會在結果中返回時區數據 - 但Rails仍將其顯示爲一個「String」。同樣,越來越多地考慮到這是因爲Rails無法在'events'表的模式中找到'starts_at'列(因爲它是由JOIN訪問的'shifts'表中的一列)。不知道這是否是一個「bug」,但我想我必須解決它或查看Rails代碼庫以查看它是否存在問題。 –

相關問題