【问题标题】:Convert Timestamp from PostgreSQL to Time Zone in Query (Rails)在查询(Rails)中将时间戳从 PostgreSQL 转换为时区
【发布时间】:2018-08-06 10:12:42
【问题描述】:

过去的几个小时的头撞这个。

我正在尝试按天组将查询模型与 PG 模型 start_time(以 UTC 存储)分开。

  • 上午(12a - 12p)
  • 下午(12p - 5p)
  • 晚上 (5p - 12a)

我尝试过范围方法、实例方法查询和整体类方法。所有这些都按 UTC 返回日期组(不是预定事件的本地时区

# event.rb
def self.morning
  startday = 0
  midday = 12
  Event.where("extract(hour from start_time) >= ? AND extract(hour from start_time) < ?", startday, midday)
end

也试过了,

def self.afternoon
  midday = "12:00:00"
  eveday = "17:00:00"
  Event.where("start_time::time >= ? AND start_time::time < ?", midday, eveday)
end

当控制台提示时(通常在整个应用程序中)我调用 event.start_time 在本地时区成功返回(在 application.rb 文件中设置)

但除非在模型之外调用,否则 start_time 会继续以 UTC 查询。

我不想预设数据库时区(因为这是不好的做法,并且应用程序在全球范围内使用)

编辑

作为视图中的示例,我正在调用

<% events.morning.order("start_time ASC").each do |fit_class| %>
...

在哪里,

events = @events = Event.all # passed through a partial

【问题讨论】:

  • 我写了一篇关于 Rails 和时区的文章,您可能会觉得有用:jessehouse.com/blog/2013/11/15/… 也有旧的示例应用程序代码与之配套,并且有各种场景来说明您可能需要如何使用时区。
  • @house9 实实在在的文章!学习了大量关于通过时区查询的知识。它在我的调查中导致了更深层次的隐藏复杂性 (stackoverflow.com/questions/49012499/…)。发现后我会发布我的更好实践的解决方案!
  • 您是否尝试过使用时区格式的字段进行查询?

标签: ruby-on-rails postgresql


【解决方案1】:

对于围观者,我的临时解决方案如下(大量研究 PostgreSQL 文档):

def self.morning
  startday = 0
  midday = 12
  Event.where("extract(hour from start_time - interval '6 hours') >= ? AND extract(hour from start_time - interval '6 hours') < ?", startday, midday)
end

def self.afternoon
  midday = 12
  eveday = 17
  Event.where("extract(hour from start_time - interval '6 hours') >= ? AND extract(hour from start_time - interval '6 hours') < ?", midday, eveday)
end

def self.evening
  eveday = 17
  endday = 24
  Event.where("extract(hour from start_time - interval '6 hours') >= ? AND extract(hour from start_time - interval '6 hours') < ?", eveday, endday)
end

这需要我预设应用时区。

# application.rb
config.time_zone = "Central Time (US & Canada)"

我会在发现完整解决方案更新后进行更改!

【讨论】:

    【解决方案2】:

    只需为带有时区检查的事件模型添加范围

    class Event < ApplicationRecord
    
      scope :morning, -> { where(
        "start_time >= ? AND start_time < ?",
          formatted_time(0), formatted_time(12))
      }
    
      scope :afternoon, -> { where(
        "start_time >= ? AND start_time < ?",
          formatted_time(12), formatted_time(17))
      }
    
      scope :evening, -> { where(
        "start_time >= ? AND start_time < ?",
          formatted_time(17), formatted_time(24))
      }
    
      private
    
      def formatted_time(hour = 0)
        Time.zone.parse(Date.current.to_s).change(hour: hour)
      end
    end
    

    您无需为此查询修改任何其他时区设置。希望对您有所帮助!

    【讨论】:

    • 漂亮!谢谢!
    猜你喜欢
    • 2014-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-05
    • 2013-02-08
    • 1970-01-01
    • 2023-03-28
    • 2014-02-12
    相关资源
    最近更新 更多