铁轨上的红宝石.时区和范围



我需要帮助尝试在作用域中使用时区。下面是我想要实现的示例。

所有日期都以 UTC 时间存储:

例如。时区 UTC +1 的用户发布了将于 20:00 开始的演出。在演出节目页面上,每个人都会看到这是20:00,这是正确的。我的问题在于我必须"过期"演出,因此在date过后它们不再出现在搜索中。

到目前为止,我一直在使用示波器;

scope :expired, -> { where('date <= ?', Time.current.to_datetime) }

因此,gig.expired将显示过去gig.date的所有演出。

问题是,当用户处于 UTC +1 时区时,对他来说,演出将在 21:00 而不是 20:00 "过期",因为它以 UTC 而不是 UTC+1 过期。

编辑:

我现在在创建时将时区保存为演出模型的属性。我已经在使用地理编码器进行定位,它可以保存坐标。使用时区 gem,我可以查找坐标并提取时区,该时区作为字符串保存到模型中。

例如。在视图中,@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 仍然在 UTC 时间"过期"演出。如何添加演出保存的时区,并在范围内使用它?

我从未使用过时区 gem,但如果您在作用域中使用它遇到困难,您可以考虑简单地在返回所需内容的方法中使用它。

Fwiw,我认为如果您为不同的时区保存不同的时间,您可能会使您的应用程序难以维护。我可以看到向用户显示一个转换为其时区的日期......但它们应该以统一的方式保存。这段代码,如果它依赖于当前用户的时区,将会很挣扎。将苹果与苹果进行比较很重要。

如何保存日期?如果将其保存为 UTC 时间,只需将其与 UTC 时间进行比较即可。

如果你更喜欢使用范围,我会做这样的事情:

scope :expired, -> { where('date < ?', Date.today) }

或者,您可以执行以下操作:

def self.expired
  Gig.where('date < ?', Date.today)
end

好的,经过几天的尝试,我想出了一个解决方案。如果有人能做得更好,我很想听听。

在创建演出时,我使用时区 gem 查找时区,并将生成的:string保存到我在演出模型中创建的 timezone 属性 Longitudelatitude可用作属性,因为演出具有在创建表单中设置的位置;

timezone = Timezone.lookup(@gig.latitude, @gig.longitude)
          @gig.update_attributes(timezone: timezone)

然后,我在演出模型中添加了另一列gigzonetime。我将其设置为 gig.date,并减去时区偏移量。

 gigzonetime = @gig.date - @gig.date.in_time_zone(@gig.timezone).utc_offset
  @gig.update_attributes(gigzonetime: gigzonetime)

在显示和索引页面上,我显示<%= @gig.date %>以显示它将显示的本地时间,在我的范围内,我将新属性gigzonetime进行比较,以便它在正确的时间过期。

scope :expired, -> { where('gigzonetime <= ?', Time.current.to_datetime) }

这似乎适用于所有时区(未来和过去)对于夏令时时差,它似乎也可以正常工作。

相关内容

  • 没有找到相关文章

最新更新