Ruby on rails。时区和范围

时间:2016-03-14 19:27:04

标签: ruby-on-rails datetime scope timezone

我需要帮助尝试在范围内使用时区。以下是我试图实现的一个例子。

所有日期都以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;保存时区,并在范围内使用它?

2 个答案:

答案 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属性中 Longitudelatitude可用作属性,因为演出具有在创建表单中设置的位置;

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

这似乎适用于所有时区(未来和过去) 它似乎也适用于夏令时差异。