如何在数据库中存储带时区的日期?日期VS日期时间?

时间:2013-12-29 10:06:32

标签: ruby-on-rails database date datetime timezone

我们有RoR网站。有节目。课程持续时间为30天。如果用户在06:00之前(在用户的时区中)注册,则程序在同一天的06:00开始。如果用户在06:00之后在网站上注册,则程序将在第二天的06:00开始。 我们将UTC中的started_date保存在数据库中。我们还节省了时区名称。当我们需要查看程序是否已启动时,我们会进行一些计算。 问题是我们计算错误的时期。我认为这个问题与时区有关。

我坚持将started_date保存为UTC DateTime。我的同事们说,最好继续将started_date保留为UTC Date,并修复代码中的错误。时间是开销,但我认为最好保存它。时间将帮助我们处理时区。

更好的是:将日期作为UTC日期存储为时区名称,还是将其存储为带有时区名称的UTC DateTime?我说的时候我是对的,那个时区应该仅用于DateTime,而不能用于Date?

2 个答案:

答案 0 :(得分:1)

我将集中讨论这部分问题:

  

更好的是:将日期作为UTC日期存储为时区名称,还是将其存储为带有时区名称的UTC DateTime?我说的时候我是对的,那个时区只能和DateTime一起使用,而不能和Date一起使用?

没有时间的日期仅在您引用整个日期时有用,或者如果您有时间背景的某些预定概念,例如的开头当天当天结束。它是一个UTC日这一事实并没有改变这一点。

因此,如果您要存储UTC日期和时区,但没有其他时间背景,那么是 - 时区相当无用。来自不同时区的整个日期会相互重叠,因此您需要一些时间来进行任何类型的转换。

我同意你的观点,你应该存储一个DateTime而不仅仅是一个Date。

然后,我还没有看到你的任何代码,而且我也不知道所涉及的所有其他部分。如果您团队中的其他人坚持只使用日期,那么请尝试找出为什么。可能有一个很好的理由,例如实际上某些其他时间背景,无论是在其他地方假设还是记录。

答案 1 :(得分:0)

我建议你在UTC上坚持使用INSIST。用户时区可用于显示,可以帮助做出决定,但不应保存到数据库中。

让我们回顾一下这个案例,假设用户“Bob”在他的时区5:50(6:00之前)注册。并且Bob处于UTC + 5.在用户表中,有一个num字段timezone来保存每个用户的时区。所以鲍勃的timezone是5.鲍勃应该从今天6点开始。

在同一时区还有另一位用户“Joe”,但是在7:00注册,所以他应该在第二天6点开始。

# Bob's data
# timezone                        : 5
# registered time in timezone     : 5:50
# registered time in UTC          : 0:50
# supposed start time in timezone : 6:00
# supposed start time in UTC      : 1:00

# Joe's data
# timezone                        : 5
# registered time in timezone     : 7:00
# registered time in UTC          : 2:00
# supposed start time in timezone : 6:00 + 1.day
# supposed start time in UTC      : 1:00 + 1.day

设置一种方法来计算它们的开始时间

# User model
def start_time
  adjusted_hour = 6 - timezone
  # Always start at 6:00 despite of day
  start = created_at.change(hour: adjusted_hour) 
  start += 1.day if created_at > adjusted_hour
  start
end

这只是一个基本想法。如有必要,您需要测试一些边缘情况。

您可以在运行时计算此开始时间,也可以将其作为用户模型中的after_create回调保存到db。

然后使用它

user = User.find(name: 'Bob')
user.start_time
#A time object at today's 6:00

返回的时间始终为UTC。时区只有助于计算开始时间,但从未被保存到时间对象中。