最近在干活的时候发现一个问题,数据库里存入的时间总是比自己预期的时间多 8 个小时。 具体看代码:
controller:
time_from = DateTime.strptime("2012-10-09 21:00:00", '%Y-%m-%d %H:%M:%S')
object.new(:time_from => time_from)
object.save
说明:以上代码为 controller 中的代码,即希望存入数据库中的时间为 2012-10-09 21:00:00 但是实际存入的时间却是 2012-10-10 05:00:00,结果是真实存入的时间比自己预期的时间多了 8 个小时。 需要解决的问题 1: 想让这两个时间达到一致
当我在 console 中拿到该对象的时候,又有了问题:
object = TimeSpecial.first
object.time_from # => Tue, 10 Oct 2012 05:00:00 CST +08:00
说明:即把上面刚刚存入的数据取出来的时候,访问该对象的 time_from 属性的时候,得到的值是数据库中的值,并不是当初期望存入的值。 需要解决的问题 2:希望该值为当初希望存入的值
我的配置:application.rb 文件:
config.active_record.default_timezone = :local
config.time_zone = 'Beijing'
我的数据库为 mysql,对应的时区为:
mysql> show variables like '%time_zone%';
+------------------+--------+
| Variable_name | Value |
+------------------+--------+
| system_time_zone | CST |
| time_zone | SYSTEM |
+------------------+--------+
因为我需要在 controller 中做时间的对比,即: Time.now < object.time_from 类似这样的对比,但是因为时区问题,对比总是会有错误,这个问题要怎样解决呢,望各位大侠指点了
@naitnix DateTime.strptime("2012-10-09 21:00:00+8", '%Y-%m-%d %H:%M:%S%z') 这样貌似可以
#4 楼 @beiersi 你这思路不对, rails
会在存储数据库时采用 UTC
时间, 然后取的时候再转换出来. 所以 mysql
应当使用 UTC
存储. 这里有一个参考:
https://makandracards.com/makandra/646-how-rails-and-mysql-are-handling-time-zones
@lyfi2003 ,按照你说的,确实是,我不用去关心数据库里面到底是什么样的数据,只是我在 rails 里面拿出来用的时候,rails 会自动给我转换,所以我在做时间对比的时候也就没问题了。但是如果我需要做统计,统计到小时,这需要我直接用数据库里面的值,这个时候的值就跟真实值差 8 个小时了,这种情况有什么好的解决办法么?
把这两行去掉:
config.active_record.default_timezone = :local
config.time_zone = 'Beijing'
全部使用 UTC 时间,就可以了。
1.9.3-p194-perf :003 > a = Blog.new(title:'new',body:'new',add: Time.now)
=> #<Blog id: nil, title: "new", body: "new", add: "2012-10-10 02:41:13", created_at: nil, updated_at: nil>
1.9.3-p194-perf :004 > Time.now
=> 2012-10-10 10:41:33 +0800
1.9.3-p194-perf :005 > a
=> #<Blog id: nil, title: "new", body: "new", add: "2012-10-10 02:41:13", created_at: nil, updated_at: nil>
1.9.3-p194-perf :006 > a.add
=> Wed, 10 Oct 2012 02:41:13 UTC +00:00
1.9.3-p194-perf :007 > Time.zone
=> (GMT+00:00) UTC
debug 一下还是很清晰的。 rails 3.2.8 ruby1.9
@xds2000 ,因为库里的时间比 Time.now 慢了 8 个小时,也就是说你这个例子中的 a 这个对象,应该是 2012-10-10 10:41:13 这个时间入库的,但是库里面却是 2012-10-10 02:41:13,那么如果我要统计,在 10 点到 11 点中有多少数据入库的话,这条记录就统计不到了啊,因为我统计的 sql 是直接写的,类似与这种:select count(*) from tables where date_format(add,'%Y-%-m-%d :%H') = '2012-10-10 10',如果用这种数据库级别的统计的话,会导致数据会有偏差的
timezone 正确配置顺序是:
config.time_zone = 'Beijing' config.active_record.default_timezone = :local
大 BUG 喔。。我打完字。按住 ctrl 敲了三次回车。就出现了三个一样的回复。。那我在页面刷新之前。敲 100 个。岂不是回复 100 个一样的内容喔。
OK,谢谢各位的良言,像@zfjoy520 说的,按照这个顺序就可以了,其中: config.time_zone = 'Beijing' 这个值是 rails 系统对显示时间的默认设置,对于中国地区来说,设置成 Beijing 就可以了。 config.active_record.default_timezone = :local 这个 default_timezone 是决定 active_record 对数据库交互的时区设置,也就是影响 created_at 和 updated_at 在数据库的记录时间,只有两个参数:utc 和:local,rails 初始化时默认是 utc,所以保存到数据库的时间是 utc 时间。
对于我刚才说的统计问题,为了达到既显示中国北京时间,有需要在数据库存储的时间为当前的北京时间,那么只要将 config.active_record.default_timezone 设置为 local 就可以了
created_at
datetime NOT NULL,
updated_at
datetime NOT NULL,
估计你的 time_from 字段 不是 datetime 吧。我这边 mysql> show variables like '%time_zone%'; 跟你是一样的。
存起来的东东。是可读的 +---------------------+ | created_at | +---------------------+ | 2012-05-30 16:29:30 | +---------------------+