【问题标题】:Manipulating timezones操纵时区
【发布时间】:2015-10-19 22:56:14
【问题描述】:

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

在 UI 端,我有引导 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 个用户导入了 2 个不同的时间

  1. 开始日期:2015 年 10 月 19 日星期一 22:00:00“东部时间(美国和加拿大)”
  2. 开始日期:2015 年 10 月 19 日星期一 22:00:00“太平洋时间(美国和加拿大)”

当该日期时间通过参数时,它没有区域,只有日期,它存储为:Mon, 19 Oct 2015 22:00:00 UTC

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

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

【问题讨论】:

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


【解决方案1】:

查看这篇博文,其中涵盖了使用多个时区时应注意的要点:

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

【讨论】:

  • 我有一个针对用户特别是around_filter :user_time_zone, if: :current_user 的环绕过滤器如果我想确保使用Venue.time_zone 保存可用性,我会做around_filter :avail_time_zone, if :availability?
  • 我已经用另一种解决方案更新了我的答案,即将场地传递到您的范围并在此基础上执行您的逻辑。
  • 我不确定around filter。示例:如果这是我的日期2015-12-19 16:00,Rails/Ruby 如何知道该日期在 Venue 的时区中?据我了解,您在上面的内容将convert 它从假定的默认设置到场地的时区。我试图找到一种方式来表达,如果给定上面的日期字符串,我该怎么说,hey, this is 2015-12-19 16:00 Eastern change it to UTC or hey this is 2015-12-19 16:00 Pacific change it to UTC
  • @batman 看看我对范围的更新。关键是通过.in_time_zone(venue.time_zone)运行你的时间戳
猜你喜欢
  • 2022-01-18
  • 1970-01-01
  • 1970-01-01
  • 2010-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-04
  • 2013-03-25
相关资源
最近更新 更多