Rails Rails ActiveRecord timezone 限制太死了

linjunhalida · 2015年01月22日 · 最后由 benzhang 回复于 2015年01月23日 · 3627 次阅读

我们可以设置 Rails 的 timezone 到某个时区,然后可以设置 ActiveRecord 的时区是 UTC,还是根据 rails 的时区来:

config.time_zone = 'Eastern Time (US & Canada)'
config.active_record.default_timezone = :utc # or :local

但是很遗憾,不能直接设置 ActivieRecord 的时区,更不能根据 ActiveRecord 的数据库连接来设置时区,这样:

  • 不能分离 Rails 的时区和数据库的时区
  • 如果 Rails 连接多个数据库,它们的时区不一样,那么获取时间就会出现问题

现在我有一个项目,连接一个 UTC 的 mysql 数据库(作为 rails 项目的数据库),一个一个美国时区的 sqlserver 数据库(用来访问另外一个项目,获取数据),现在只能设置 rails 的时区根据 sqlserver 数据库的时区走,让 mysql 数据库的时间错掉,请问大家,有什么好的解法?

1、把数据库默认时间改为客户【结算】时间 2、https://github.com/tzinfo/tzinfo

@liwei78 不是很懂什么意思?

#2 楼 @linjunhalida

1、【结算时间】就是说,客户 1 月 1 号的 order 可以用 coupon,但是客户说的是西海岸时间,而俄罗斯和亚洲已经到 1 月 1 号了。 2、用 tzinfo 把时间转成和 1 一致的时间,比如中国 16:06 下的 order,访问 details 时显示的是 12:05(西海岸时间)。因为客户不是全球结算,而是按照它当地时间结算。亚太区 1 月 1 日的 order,一大部分还算作 2014 年的。

可能我没太理解你的应用场景,我讲的是我遇到的情景,仅供参考。

统一成 UTC,然后把数据洗一遍,显示的时候再根据当地的时区来显示

你这个是遗留项目的问题,遗留数据库属于遗留项目的一种。你的那个 SQL Server 数据库如果一开始就用 UTC 来存储时间,就不会有这个问题了。

这个问题也比较好解决,就是分成两个系统,用 API 来互通,API 中的时间用 UTC 即可。缺点就是需要一定的开发时间。

看了一下大家的解法,现在数据库因为已经有数据了,不能更新时间。同时移出来做 api 动作太大了,并且就算做了 api,也需要记录数据,这个时候还是要用到 mysql 数据库,mysql 数据库还不能改信息。

不过 rails 保存时间都是用 datetime 这种时区不相关的格式,然后这个数据是 rails 算好塞进去的,这样 mysql 只要不用 now 这种和时区相关的函数就没有问题。那么就这样将就着用吧。

mysql 支持根据 session 设置 timezone,不过 ActiveRecord 不支持设置: https://github.com/rails/rails/issues/13494

ActiveRecord 也不支持设置 timezone,更别说根据数据库连接设置 timezone 了: https://github.com/rails/rails/issues/13796

如果 SQL Server 的数据库的时间是带时区的,那 Rails 读的时候会自动转换时间的,所以应该没有什么问题。如果不行你把时区设置成根 SQL Server 的时区也没什么问题啊,你读的时候转换成你需要的时间就好了。我们的一个项目每个用户都可以设置自己的 time zone,稍微转换一下而已 比如

@topic.created_at.in_time_zone(current_user.time_zone)
需要 登录 后方可回复, 如果你还没有账号请 注册新账号