2011-12-11 85 views
1

在我的應用程序中,我有一個Person模型。每個Person都有一個屬性time_zone,它指定了它們的默認時區。我也有一個Event模型。每個Event都有一個start_timeend_time時間戳,以UTC時間保存在Postgres數據庫中。Rails 3.1:查詢Postgres在時間範圍內的記錄

我需要創建一個查詢,查找特定人員在一天午夜和下午午夜之間發生的事件。控制器變量@todays_events保存查詢的結果。

我採取這種方法的部分原因是我可能會讓其他時區的人員查看某人的事件列表。我希望他們看到一天的人會看到一天,而不是基於他們作爲觀察者的時區。

無論出於何種原因,我仍然在前一天在@todays_events.的結果集中收到一些事件我的猜測是我將UTC時間戳與非UTC參數進行比較,或者沿着這些行進行比較。通常,只有在前一天晚上開始或結束的活動纔會顯示在今天的查詢結果列表中。

現在,我設置了:

@today = Time.now.in_time_zone(@person.time_zone).midnight.to_date 
@tomorrow = (@today + 1.day).to_datetime 
@today = @today.to_datetime 

我的查詢是這樣的:

@todays_activities = @person.marks.where("(start_time >= ? AND start_time < ?) OR (end_time >= ? AND end_time < ?);", @today, @tomorrow, @today, @tomorrow).order("start_time DESC") 

我應該如何改變這種做法,我只能保證收到從今天的結果(每@person.time_zone@todays_activities查詢?

+0

注:我存儲全時區字符串中的'@ person.time_zone'場,而不僅僅是抵消。 – Clay

+0

違規事件之一在'start_time'的db表中具有以下內容:'2011-12-10 23:28:00'和'end_time':'2011-12-11 03:00:00' with'time_zone '東部時間(美國和加拿大)''。 – Clay

回答

10

當你撥打to_date時,你正在失去跟蹤你的時區,所以不要這樣做:

@today = Time.now.in_time_zone(@person.time_zone).midnight.utc 
@tomorrow = @today + 1.day 

當你some_date.to_datetime,你會得到一個DateTime實例,它是在UTC所以像這樣的結果:

Time.now.in_time_zone(@person.time_zone).midnight.to_date.to_datetime 

將有一個時間的日00:00:00和UTC的時區; 00:00:00是@person.time_zone中的正確時間,但不適用於UTC(除非,當然,@person處於+0時區)。

而且你可以簡化與overlaps查詢:

where(
    '(start_time, end_time) overlaps (timestamp :today, timestamp :tomorrow)', 
    :today => @today, :tomorrow => @tomorrow 
) 

注意overlaps works with half-open intervals

Each time period is considered to represent the half-open interval start <= time < end , unless start and end are equal in which case it represents that single time instant.

+0

太棒了!這是我經過大量搜索後看到的唯一最好的解釋。我不知道重疊,要麼非常感謝!時區令人沮喪! – Clay

+0

在這種情況下使用'overlapps',使用你的代碼如圖所示,我認爲'@ today'和'@ tomorrow'需要被施放。引發此錯誤:'PGError:ERROR:function pg_catalog。重疊(沒有時區的時間戳,沒有時區的時間戳,未知的,未知的)是不唯一的 線1:... arks「。」person_id「= 1 AND((start_time,end_time)重疊(... ^ HINT :無法選擇最佳候選功能,您可能需要添加顯式類型轉換。' – Clay

+1

@Clay:嘗試添加一些轉換:'重疊(:today :: timestamp,:tomorrow:timestamp)'或'overlapps(timestamp:today ,時間戳:明天)'。爲了記錄,我討厭時區,幾乎和我討厭DST一樣。 –