操纵时区

时间:2015-10-19 22:56:15

标签: ruby-on-rails ruby datetime ruby-on-rails-4

我遇到时区问题,并在我的应用程序中从不同区域导入日期,这些区域适用于Availability模型。

在UI端,我有bootstrap datetimepicker并创建params[start_time],但它没有与之关联的特定区域。

可用性属于具有时区的Venue。我一直想知道是否有办法可以做类似的事情:

# Explicitly set zone based on Venue.time_zone
start_date_zoned = set_time_zone_to(param[:start_date], Venue.time_zone)

# Convert start_date to UTC to standardize with DB default
start_date_zoned.utc

我需要进行此转换的原因是因为Availabilities上的此范围因为区域已关闭而无法正确返回:

scope :after_now, -> {where{start_time >= Time.zone.now }} 
# Maybe Time.zone.now isn't right?

例如,如果我有两个不同时间从不同时区的2个用户导入

  1. start_date:星期一,2015年10月19日22:00:00“东部时间(美国和加拿大)”
  2. start_date:星期一,2015年10月19日22:00:00“太平洋时间(美国和加拿大)”
  3. 当该日期时间通过参数时,它没有区域,只有日期,它存储为:Mon, 19 Oct 2015 22:00:00 UTC

    当我执行Availabilities.after_now并说它当前为21:00 UTC时,两个结果都会出现,但实际上,这两个导入的可用性应该是EST和PST(然后转换为正确的UTC值) ),他们可能会或可能不会after_now

    有没有办法做到这一点,我有意义吗?

1 个答案:

答案 0 :(得分:0)

查看此博客文章,其中涵盖了使用多个时区时应注意的内容:

http://www.elabs.se/blog/36-working-with-time-zones-in-ruby-on-rails

从文章中,一个解决方案就是将当前请求用于活动时区,活动时间为Venue.time_zone。类似的东西:

around_filter :venue_time_zone, :if => :venue?

def venue?
  @venue = Venue.find(params[:id])
end

def venue_time_zone(&block)
  Time.use_zone(@venue.time_zone, &block)
end

然后更新范围:

scope :after_now, -> {where{start_time >= Time.current }} 

这应该尊重为当前请求设置的时区。

另一种解决方案是将Venue传递给您的scope

scope :after_now, -> { |venue| where{start_time.in_time_zone(venue.time_zone) >= Time.now.in_time_zone(venue.time_zone) }}