【问题标题】:Rails - Different timezone to limit daily postsRails - 不同时区限制每日发帖
【发布时间】:2013-02-01 13:37:08
【问题描述】:

我正在开发 Rails 应用程序,该应用程序允许用户每天最多发布 2 个帖子,非常简单。

我的问题是如何管理不同用户所在的不同时区。例如,如果我住在伦敦,一天从00.00 开始并在23.59 结束,帖子计数将重置为00.00,但对于住在纽约的其他用户,计数器将在不同的时间重置。 (不是00.00)我该如何处理这种情况?

我希望我自己解释了。

更新 1

@集群

您的代码的问题是time_zone.utc_offset 给出了错误的时间增量:

1.9.3p194 :123 > time_zone = ActiveSupport::TimeZone.new("Prague")
 => (GMT+01:00) Prague 
1.9.3p194 :124 > DateTime.now.utc.midnight - time_zone.utc_offset
 => Thu, 10 Apr 2003 00:00:00 +0000 

为什么?

我发现这段代码很有用:

User.posts.where(:created_at => DateTime.now.in_time_zone(time_zone).beginning_of_day..DateTime.now.in_time_zone(time_zone).end_of_day).count

似乎在用户当天(使用用户的时区)之间获得了正确数量的消息。你怎么看?

更新 2

@集群

两者有什么区别:

User.posts.where(:created_at => DateTime.now.in_time_zone(utc_time_zone).beginning_of_day..DateTime.now.in_time_zone(utc_time_zone).end_of_day).count

还有你的:

1.9.3p327 :015 > time_zone = ActiveSupport::TimeZone.new("Prague")
 => (GMT+01:00) Prague 
1.9.3p327 :016 > Time.zone.now.utc.midnight - time_zone.utc_offset
 => 2013-02-15 23:00:00 UTC

在性能和做事方式方面?

更新 3

其实你的例子中的代码不起作用,看这里:

# WRONG
1.9.3p194 :096 > user.posts.where('created_at > ?', Time.zone.now.utc.midnight - my_time_zone.utc_offset).count
   (0.2ms)  SELECT COUNT(*) FROM "messages" WHERE "messages"."sender_id" = 5 AND (created_at > '2013-02-15 23:00:00.000000')
 => 4 

# CORRECT
1.9.3p194 :098 > users.posts.where(:created_at => DateTime.now.in_time_zone(my_time_zone).beginning_of_day..DateTime.now.in_time_zone(my_time_zone).end_of_day).count
   (0.3ms)  SELECT COUNT(*) FROM "messages" WHERE "messages"."sender_id" = 5 AND ("messages"."created_at" BETWEEN '2013-02-16 23:00:00.000000' AND '2013-02-17 22:59:59.000000')
 => 0

【问题讨论】:

  • 响应更新 1,这是因为 DateTime 减去的是 Days 而不是 Seconds,应该更清楚,这就是为什么我总是使用 Time.zone.now 而不是 DateTime.now。 Time.zone 是一个 Rails 附加项,它为您提供了一个 ActiveSupport::TimeWithZone,它似乎比 Date/Time/DateTime 更理智,改变了我的回应以反映这一点

标签: ruby-on-rails ruby timezone


【解决方案1】:

根据您希望它的工作方式,我可以想到两种解决方案。

首先,允许用户在 24 小时内发布两次,这样做的好处是与时区无关:

User.posts.where('created_at > ?', 24.hours.ago).count

如果返回 2,则不要让他们发布。

如果你真的想确保每天不超过 2 个帖子,那么:

time_zone = ActiveSupport::TimeZone.new(current_user.time_zone)
Users.posts.where('created_at > ?', Time.zone.now.utc.midnight - time_zone.utc_offset).count

User#time_zone 需要持有 Rails 识别的有效时区。

由于数据库日期时间 (created_at) 已经采用 UTC,首先将您的服务器时间标准化为 utc,然后将时间设置为午夜,并为时区应用 utc 偏移量。因此,如果您有人在 -7 时区,那么它会查找自 0700 UTC 以来的帖子,对于处于 +3 时区的人,它将查找自 2100 UTC 以来的帖子。

ActiveSupport::TimeZone

为了阐明两者之间的区别,让我举几个例子。

第一个示例是用户在 1200 发帖,然后在周一 1800 发帖。

使用第一段代码,用户在周二 0600 之后才能再次发帖。使用第二段代码,他们将能够在星期二 0000(午夜之后)再次发布。

第二个例子是用户在 2330 发帖,然后在周一的 2350 发帖。同样,在第一个示例中,他们在星期二 2330 之后才能再次发布,但第二个示例将允许他们在午夜再次发布,允许他们在 0010 和 0020 发布,在 50 分钟内给他们 4 个帖子。

这实际上取决于帖子限制的目的。第一个示例将更易于使用和实施,因为它可以在不受时区影响的情况下工作。

如果您从 FB 提取时区信息,请检查该时区信息的格式。我猜它不是 ActiveSupport::TimeZone 将接受的有效字符串。例如,它希望 "Mountain Time (US & Canada)" 用于 MST(-0700)。如果 FB 为您返回类似 MST 的 -7 或 -25200(-7 小时以秒为单位)之类的东西,那么您可以使用它们而无需与 AS:TZ 混在一起

RE:更新 1

这是使用 Time.zone 代替 DateTime 的输出

1.9.3p327 :015 > time_zone = ActiveSupport::TimeZone.new("Prague")
 => (GMT+01:00) Prague 
1.9.3p327 :016 > Time.zone.now.utc.midnight - time_zone.utc_offset
 => 2013-02-15 23:00:00 UTC

【讨论】:

  • 感谢您的回答!当你说:“如果你真的想确保每天不超过 2 个帖子,那么......”是什么意思? 24.hours.ago的第一种方法不好?对于第二种方法,我需要 User 模型中的 time_zone 字段,对吧?我让用户只用FB连接,所以我需要从FB取时区,我认为可以没有任何麻烦。顺便说一句,我会以这种方式处理这种情况:如果您今天已经发布了 2 个帖子(在您的时区 00.00-23.59 之间)并且过了午夜(所以这是新的一天),您必须能够发布新的 2 个帖子。
  • 更新了一个解释,阐明了两个示例之间的差异。
  • 老兄回答得好,非常感谢。请查看我的新更新。
【解决方案2】:

考虑为所有人使用 UTC 时区。 IE。 StackOverflow 使用这种方法进行投票,并且效果很好。

【讨论】:

  • 谢谢。如何使用 UTC 时区来实现这一目标?您是否有一些问题/答案或链接可以为 Rails 提供一些有用的信息?
  • 不...实际上你想要达到什么目的? - 让用户在 24 小时内发布一次(而不仅仅是使用您服务器的时区)或在用户 0:00-23.59 期间发布两次(而不是您需要从浏览器 getTimeZoneOffset 发送用户的时区并将其发送到您的服务器)。跨度>
  • 我会让用户在他的一天(00:00 - 23.59 期间)发布一次,而不是在服务器的时区)。例如,如果您与我住在不同的时区,您的一天可能会在我之前或之后完成,然后您的帖子计数器可能会在您的一天结束时重置,这与我的不同。
  • @FredCollins,请注意,正确执行“用户日”比服务器/UTC 时区更难 - 您需要注意夏令时,用户在一天内跨越时区。看看差异对你来说是否真的很重要......无论如何,Cluster (+1) 给了你代码,所以你唯一需要的就是搜索ruby user timezone rails
猜你喜欢
  • 2023-03-25
  • 1970-01-01
  • 1970-01-01
  • 2014-03-17
  • 1970-01-01
  • 2014-03-16
  • 1970-01-01
  • 2022-01-05
  • 2011-07-19
相关资源
最近更新 更多