2013-12-09 67 views
5

我期待在时间和考勤系统的Rails应用程序的同一视图中的多个时区中显示数据。一点上下文:Rails - 在同一请求上处理多个不同时区

  • 我们使electronic time clocks。人们,但他们在他们的业务。工作人员进出工作时间并记录他们的工作时间。
  • 时钟将有人进入/离开我们API的时间推到一个unix时间(例如,我们的Javascript时间时钟实现如此抓住时钟:moment().unix())。 API然后将其作为timestamp without time zone存储在Postgres数据库中。
  • 当用户登录到站点时,around_filter根据该用户组织的设置为请求设置适当的时区。

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

假设我们的经理在悉尼,现在是上午11点。他们管理着三个办公室 - 一个在悉尼,一个在布里斯班(在DST期间落后于悉尼一个小时),另一个在阿德莱德(在DST之后半个小时)。工作人员在当地时间早上九点在这三个办事处登记。所以,在经理的仪表板上,所有时钟输入应该显示为上午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来设置请求的时区;如果我在这里做了,每个时间都会显示半个小时,这是不正确的。因此,我正在寻求有关来自各个区域的时间的最佳实践建议。

+0

你的措辞令人困惑。什么是实际问题?你能简化你的问题吗?以“问题”开头的句子有一些语法错误,这使得很难理解你想要做什么。也许你可以展示一些代码来演示? (顺便说一句 - 我也用时钟工作,所以我很乐意提供帮助,如果我能理解你的问题。) –

+0

@MattJohnson谢谢 - 那句话很残酷 - 我已经改写了它。我还添加了一些更具体的例子。 –

+0

我仍然不明白你有什么问题。你似乎只是在寻求广泛的建议。我可以提供的唯一一点是在DST回退转换期间注意本地到UTC转换,因为结果可能不明确。但是如果你需要Rails代码,也许你应该展示你已经尝试过的并且专注于一个特定的问题。目前的措辞太宽泛了。 –

回答

4

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

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

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

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

相关问题