Rails - 在同一请求上处理多个不同的时区

时间:2013-12-09 02:09:39

标签: ruby-on-rails activerecord timezone

我希望在Rails应用程序中的同一视图中为多个时区显示数据,以用于时间和考勤系统。一点背景:

  • 我们制作electronic time clocks。人们,但他们在他们的业务。工作人员上班和下班时间记录下来。
  • 时钟将某人作为unix时间输入/输出到我们的API的时间推迟(例如,我们的Javascript时钟实现及时抓取时钟:moment().unix())。然后,API将其作为timestamp without time zone存储在Postgres数据库中。
  • 当用户登录该站点时,around_filter会根据该用户组织的设置为该请求设置相应的时区。

如果我们的组织跨越多个时区,则会出现问题。例如,在每个澳大利亚首都城市设有办事处的企业将跨越三个时区(在夏令时期间更多)。但是,中央办公室中将有一个人需要检查整个组织的数据 - 我们称之为我们的经理。

假设我们的经理位于悉尼,现在是上午11点。他们管理着三个办公室 - 一个在悉尼,一个在布里斯班(在DST期间落后悉尼一小时),另一个在阿德莱德(在DST期间落后悉尼半小时)。工作人员在当地时间上午9点在三个办公室上班。因此,在经理的仪表板上,时钟输入的所有时间都应显示为上午9点。 但是,当前的实施(使用around_filter)将分别显示上午9点,上午8点和上午8点30分的时间,因为它们将使用悉尼时区进行偏移。

有一层过滤应用于来自不同城市的员工,因此可以告诉系统A人来自悉尼,B人来自阿德莱德,C人来自布里斯班。问题 - 我希望得到的建议 - 是如何最好地让Rails尽可能有效地向不同时区显示偏移量。

奖励积分:以及显示时间,我们还需要阅读输入。例如,有人可能提前5分钟计时,他们的时间表需要更正。如果当地经理(即布里斯班的某个人)纠正布里斯班员工的时间表,那么这应该相对容易管理 - 鉴于我们知道他们在布里斯班,我们可以将请求的时区设置为布里斯班,让ActiveRecord执行抵消我们。但是,如果总经理(位于悉尼但管理所有时区)想要进行更改,那么我们需要能够根据他们的时区将他们的输入正确地转换回UTC。关于如何做到这一点的任何建议都会很棒。

问题的具体示例

在我的数据库中,我的clock_ins表如下所示:

user_id (integer) | time (timestamp without time zone)
------------------|-----------------------------------
1                 | "2012-09-25 22:00:00.0"
2                 | "2012-09-25 22:30:00.0"
3                 | "2012-09-25 23:00:00.0"

我的用户表看起来像这样:

user_id (integer) | time_zone (varchar)
------------------|-----------------------------------
1                 | "Sydney"
2                 | "Adelaide"
3                 | "Brisbane"

(这是一种简化,实际上用户和他们的时区之间还有另一种联接)

如果我们将每个用户的时区应用到他们的时间,我们发现他们都在当地时间上午9点。即。 UTC的2012-09-25 23:00:00.0在布里斯班是2012-09-26 09:00:00.0(+1000)。 Rails中的一般方法是使用around_filter来设置请求的时区;如果我在这里这样做,每次都会显示相隔半小时,这是不正确的。因此,当我与各个区域合作时,我正在寻找有关最佳实践的建议。

1 个答案:

答案 0 :(得分:4)

我能看到的最简单的方法是在渲染时间时使用Time.use_zone方法。 e.g。

Time.use_zone('Sydney') { Time.current }

Time.use_zone(person.office.time_zone) { person.clock_ins.last.time_stamp }

这“允许在提供的块内局部覆盖Time.zone;完成时将Time.zone重置为现有值。”