似乎当数据库中的列未保存在正确的时区时
1) Rails 在将时间插入数据库之前会自动将时间转换为 UTC 时间(这是一件好事),这意味着时间的偏移量为 "+0000" 。这意味着如果您将晚上 8 点的时间保存到数据库中,并且您的服务器位于偏移量为“+0600”的时区,那么等效的 UTC 时间是下午 2 点,因此下午 2 点会保存在数据库中。换句话说,您本地服务器的时间比 UTC 时间早 6 小时,这意味着当您服务器所在时区的晚上 8 点时,UTC 时区的下午 2 点。
2)当您比较日期时,ruby 会考虑时区偏移量——换句话说,ruby 会将所有时间转换为同一时区,然后比较时间。这是一个例子:
2.0.0p247 :086 > x = DateTime.strptime('28-01-2013 08:00:00 PM +6', '%d-%m-%Y %I:%M:%S %p %z')
=> Mon, 28 Jan 2013 20:00:00 +0600
2.0.0p247 :087 > y = DateTime.strptime('28-01-2013 08:20:00 PM +7', '%d-%m-%Y %I:%M:%S %p %z')
=> Mon, 28 Jan 2013 20:20:00 +0700
2.0.0p247 :088 > x < y
=> false
如果只是比较两个 Datetime 对象的时间,x 小于 y。但是,y 在偏移量为 +7 的时区中的时间为晚上 8:20,这相当于在偏移量为 +6 的时区中的时间晚上 7:20。因此,y 实际上小于 x。您需要将苹果与苹果进行比较,这意味着您需要在心理上比较已转换为同一时区的时间,以获得与 ruby/rails 产生的相同结果。
3)您可以使用 rails utc() 方法将 Time.now 转换为 UTC 时间:
2.0.0p247 :089 > x = Time.now
=> 2013-09-07 8:00:00 +0600
2.0.0p247 :090 > x.utc
=> 2013-09-07 02:00:00 UTC
这就是 ruby 在比较 Time.now 之前所做的task.when + task.duration
4)您可能会发现使用您想要使用的时间创建 DateTime 对象更方便:
DateTime.strptime('28-01-2013 08:00:00 PM +0', '%d-%m-%Y %I:%M:%S %p %z'
因为您可以将偏移量指定为零,所以您不必创建预期转换为 UTC 时间的时间。
或者你可以使用 change() 方法,它会导致 offset() 改变而不转换时间:
2.0.0p247 :011 > x = DateTime.now
=> Sun, 08 Sep 2013 00:34:08 +0600
2.0.0p247 :012 > x.change offset: "+0000"
=> Sun, 08 Sep 2013 00:34:08 +0000