我需要帮助尝试在范围内使用时区。以下是我试图实现的一个例子。
所有日期都以UTC时间格式存储:
EG。时区UTC +1的用户发布将于20:00开始的演出。在演出页面上,每个人都会看到这是20:00,这是正确的。
我的问题出现在我必须“到期”的事实上。 gigs,所以在date
过去后它们不再出现在搜索中。
到目前为止,我一直在使用范围;
scope :expired, -> { where('date <= ?', Time.current.to_datetime) }
所以gig.expired
会显示gig.date
过去的所有演出。
问题在于,当用户处于UTC +1时区时,对于他来说,演出将会“到期”。在21:00,而不是20:00,因为它在UTC时间到期而不是UTC + 1.
编辑:
我现在将时区保存为创建时的gig模型的属性。 我已经使用地理编码器进行定位,这样可以节省坐标。 使用timezone gem,我可以查找坐标并提取时区,该时区将作为字符串保存到模型中。
EG。在视图中,@gig.timezone
显示Europe/Amsterdam
(或保存的任何时区)
或<%= @gig.date.in_time_zone(@gig.timezone) %>
显示2016-03-17 21:38:00 +0100
我现在的问题是,将此问题与之前的范围一起使用。 如果我试试;
def self.expired
Gig.where('date < ?', Time.now.in_time_zone("Europe/Amsterdam"))
end
Rails仍然会过期&#39; UTC时间的演出。 如何添加演出&#39;保存时区,并在范围内使用它?
答案 0 :(得分:0)
我从未使用过TimeZone gem,但是如果你在范围内使用它时遇到困难,你可以考虑在一个返回你想要的方法中使用它。
Fwiw,如果您为不同的时区保存不同的时间,我认为您可能会使您的应用难以维护。我可以看到向用户显示转换到他们时区的日期......但是他们应该以统一的方式保存。如果代码依赖于当前用户的时区,那么这段代码将会变得困难。将苹果与苹果进行比较非常重要。
如何保存日期?如果将其保存为UTC时间,只需将其与UTC时间进行比较。
如果您更喜欢使用示波器,我会这样做:
scope :expired, -> { where('date < ?', Date.today) }
或者你也可以这样做:
def self.expired
Gig.where('date < ?', Date.today)
end
答案 1 :(得分:0)
好的,经过几天尝试完成这项工作后,我想出了一个解决方案。如果有人能做得更好,我很乐意听到它。
在创建gig时,我使用timezone gem查找时区,并将生成的:string
保存到我在gig模型中创建的timezone
属性中
Longitude
和latitude
可用作属性,因为演出具有在创建表单中设置的位置;
timezone = Timezone.lookup(@gig.latitude, @gig.longitude)
@gig.update_attributes(timezone: timezone)
然后我在gig模型中添加了另一列gigzonetime
。我将其设置为gig.date,减去时区偏移量。
gigzonetime = @gig.date - @gig.date.in_time_zone(@gig.timezone).utc_offset
@gig.update_attributes(gigzonetime: gigzonetime)
在show和index页面上,我显示<%= @gig.date %>
以显示它将显示的本地时间,在我的范围内,我将与新属性gigzonetime
进行比较,因此它会在正确的时间到期
scope :expired, -> { where('gigzonetime <= ?', Time.current.to_datetime) }
这似乎适用于所有时区(未来和过去) 它似乎也适用于夏令时差异。