Rails 用 Time.now 写入 MySQL,时间为什么都滞后八小时?

lin_style · 2012年05月14日 · 最后由 woaigithub 回复于 2012年11月01日 · 14665 次阅读

直接运行 RY 文件正常,写入字段后,就是少 8 个小时,不解。。

你从数据库中读出的时间也滞后 8 小时嘛?

如果是 Rails 的 ActiveRecord 保存时间,会默认以 UTC 时间保存数据,自然跟中国大陆的市区差八小时。可以通过 config/application.rb 修改 ActiveRecord 的默认市区,不过 UTC 是推荐设置。

写入是 UTC,可以设置服务器的 timezone 改变默认显示时区

系统时区没设置对

三个问题:

  1. 楼主是如何写进数据库的?
  2. 楼主是如何读数据库的?
  3. Rails 版本

Rails-3 写数据库时,会转换成 UTC 时间。读取的时候,那得看怎么读了。记得 #to_s(:db) 会转换成 UTC 时间。其他的,可能是本地时间。

Rails-2 和 Rails-3 在时区处理上略有不同,但具体的我还没搞明白……

#2 楼 @Rei

服务器的 timezone 应该没问题,因为我直接运行 ruby 文件,Time.now 输出的时间是正确的

#4 楼 @zhangyuan 1) 我是这样更新的 if !user.update_attribute("lastlogin_time", Time.now)

2) 我直接用前端工具查看 MYSQL,显示的时间就是滞后 8 小时。

3)Rails 3.2.2

#5 楼 @lin_style Rails 里的时区我还没完全搞懂。但希望能给你一些思路:

  1. 保存的时候,传递的是 Time.now,是一个 Time 对象,但从数据库查出来对象后的时间,却是一个 ActiveSupport::TimeWithZone 对象。

  2. 假设在 Rails 的 config/application.rb 设置的时区是 Beijing,从数据库查出来的时间为 created_at,那么 created_at.to_s(:db) 返回的时间,和用其他工具在数据库查看到时间一致,也就是滞后 8 小时;但created_at.to_s(:long) 返回的时间,却是本地时间。

  3. created_at.localtime 返回的是本地时间。

  4. 查看 user.update_attribute("lastlogin_time", Time.now) 时的 SQL 语句,应该可以看到保存时间,是滞后八小时的时间。也就是 UTC 时间。

大致可以推测:

  1. 数据库里保存的是 UTC 时间:Rails 会在保存前转换成 UTC 时间;
  2. 从数据库里取出来的是 TimeWithZone 对象,需要时间 #localtime 才能得到本地时间。

Rails-2 里,可能不是这样处理。

@zhangyuan

解决入下: 监视 MYSQL 语句,执行为 1 Query UPDATE users SET lastlogin_time = '2012-05-14 16:58:38' WHERE users.id = 20

说明跟数据库无关,值是 RAIS 传来的。

config /application.rb 文件,加上

config.time_zone = 'Beijing'
config.active_record.default_timezone = :Beijing

@lin_style rails 保存 DateTime 是 UTC 0 时区时间 timestamp 是代时区的时间,rails 的机制就是存储在数据库中的时间都是一个绝对时间,取出来的时候,自动转换成 User 时区时间,这种方式非常好,能解决不同时间,不同地点的时间,都是同步的

#7 楼 @lin_style 原来 Rails 里有一个整个框架用的时区,还有一个 ActiveRecord 的默认时区。

#8 楼 @hysios 理解,但是我在数据库中直接做一些资料查询的时候不是很不方便?

#9 楼 @zhangyuan 刚用 RAILS 不久。谢谢回复

广而告之: http://willmouse.com/2012/05/14/local-time-zone/

不过已经写入的数据即使按照上面设置了,从数据库取出后也是 UTC 时间,只有在设置后,新写入的数据,时间才是本地的

看到题目就觉得是时区问题,北京时间在东八区

@lin_style 实际上你不会需要在 mysql 中查询的,rails console 也可以做的很好

学习了。 我也碰到过这样的问题,后来在 rails 的配置文件里面设置了时区解决的。

假设time是从数据库中得到的时间的变量

time.utc.getlocal("+08:00")

如果是String类型的话先用Time.parse方法转换一下得到Time类型

遇到过类似问题,我是通过修改 application.rb 中 config.time_zone 来解决的

rails 默认就是写入 utc 时间,然后读取也是 utc 时间。 设置 config.time_zone 只能保证写入数据库的时间是 local,但是读出来的时候还是 utc,还是需要在界面上转换的。 created_at.utc created_at.local

config.active_record.default_timezone = :local config.time_zone = 'Beijing'

rake time:zones:all #查看所有时区 rake time:zones:localtime #查看本地时区

rails 推荐使用 utc 时间,这样就统一了,只是在界面显示的时候格式化为本地时间。

最好不用 Time.now, 都用 Time.zone.now.

广告来了 Rails+MySQL 开发中的时间问题 http://virusswb.blog.51cto.com/115214/1046723 我在参加 51cto 的博客大赛,觉得内容不错就帮我投投票,谢谢了! 投票地址:http://blog.51cto.com/contest2012/115214

需要 登录 后方可回复, 如果你还没有账号请 注册新账号