【问题标题】:Supporting timezones in a Rails application在 Rails 应用程序中支持时区
【发布时间】:2012-09-23 07:53:33
【问题描述】:

我在我的 rails 应用程序中添加了一个日历。我们的活动有开始日期和结束日期(都包括小时和分钟)。这些是事件表中的字段,实际上它们的格式是日期时间。当您为特定事件选择开始日期、结束日期、标题和描述(以及其他)时,参数哈希是这样的:

parameters = {"event" => {"title" => "a title", "description" => "a description", "start_date" => "2012-09-23 23:45", "end_date" => "2012-09-24 15:32"}}

在事件控制器中我有这样的东西:

Event.create(:title => params[:event][:title],
             :description => params[:event][:description],
             :start_date => params[:event][:start_date].present? ? DateTime.strptime(params[:event][:start_date], "%Y-%m-%d %H:%M") : nil,
             :end_date => params[:event][:end_date].present? ? DateTime.strptime(params[:event][:end_date], "%Y-%m-%d %H:%M") : nil,
             ...
            )

好吧,当这个事件被存储到数据库(mysql)中时,开始日期的值为“2012-09-23 20:45”,而结束日期的值为“2012-09-24 12:32”。我知道 Rails 会自动处理时区。我的问题是,当我想获取特定时间的所有事件(例如,今天发生的所有事件)时,我会这样做:

query = "((start_date between ? AND ?) OR (end_date between ? AND ?))"
query << "title NOT LIKE ? AND ..."
self.events.where(query, 
                  Time.now.beginning_of_day, Time.now.end_of_day, 
                  Time.now.beginning_of_day, Time.now.end_of_day, 
                  some_restriction_here, ...)

我得到了错误的事件! (很明显,为什么数据库中的日期和时间与输入不同)。还有一个明显的解决方案,将所有事件都带入内存,日期和时间将再次与原来的一样,但这在资源方面是昂贵的。另一方面,这并不能解决时区问题,如果有人在中国创建一个事件,数据库中的值将与服务器本地化的时间偏移量有关。我可以在某处有一个字段,用户可以在其中设置时区并使用此字段为此类用户存储特定日期并解决此问题,您对处理此问题的最佳方法有何建议?

【问题讨论】:

    标签: ruby-on-rails datetime


    【解决方案1】:

    Rails 以 UTC 格式将所有日期存储在数据库中。因此,一种方法是始终以 UTC 进行操作,并在视图中将显示的日期转换为当前时区。另一种方法是在每个操作开始时更改 Rails 时区。然后,所有解析的时间和日期都将在您的自定义时区中。

    def action_name
      Time.zone = "Prague"
      # ... logic
    end
    

    【讨论】:

    • ajam,听起来不错,但不太适合我的问题,我可以有很多用户从世界任何地方连接,我需要将任何本地化与时区匹配,此外,一个实体可以从不同的位置连接,无论如何非常感谢! ..另一件事,我怎么能告诉Rails不要将它存储在utc中,而就像我传递的字符串一样?我的意思是,在我的情况下,它应该存储 2012-09-23 23:45 作为开始日期,不要更改它以匹配 UTC 时间,而是存储相同的字符串。
    • 查看 Google 日历以获取灵感。您的时区存储在日历设置中,并且每个事件都被赋予此默认时区,除非您更改它。在我的现实生活中,当与外国合作伙伴和客户打交道并且我们正在安排会议(或电话)时,我们总是决定时间和时区(如果他们不在我的时区)。我将其存储在我的日历事件中。日历比显示我所在时区的此事件的时间。您可以将日期存储为字符串。您必须更改数据库列类型才能执行此操作,但您将失去执行日期/时间查询的能力。
    猜你喜欢
    • 2021-06-24
    • 2010-09-06
    • 1970-01-01
    • 2014-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-08
    相关资源
    最近更新 更多