简体   繁体   English

将记录从MySql迁移到Postgres时,如何在Rails中设置查询的默认时区或为日期时间值设置偏移量

[英]How to set in Rails a default timezone for query or set offset for datetime value when migrating record from MySql to Postgres

I created a ruby class in my models folder to connect to a legacy MySQL database that by default uses Pacific/PT for datetime columns. 我在我的models文件夹中创建了一个ruby类,以连接到默认情况下将Pacific / PT用于datetime列的旧版MySQL数据库。

However, rails is treating datetime values from legacy database records as UTC as opposed PT/Pacific . 但是,rails将旧数据库记录中的datetime值视为UTC而不是PT / Pacific Inserting this value into Postgres would be incorrect since Postgres timestamp (for rails) is timestamp without time zone (therefore, value needs to be UTC). 将此值插入Postgres是不正确的,因为Postgres时间戳(用于rails)是timestamp without time zone (因此,值必须为UTC)。

How can I either 1) set my default_timezone connection to be Pacific or 2) create some type of offset that will correctly convert the value to UTC? 我该如何1)将我的default_timezone连接设置为Pacific或2)创建某种类型的偏移量,以将值正确转换为UTC? For the later, how would an offset incorporate daylight savings time nuances? 对于后一种情况,偏移量将如何整合夏时制的细微差别?

Here's how I've confirmed the issue: 这是我确认问题的方法:

[6] pry(LegacyClient)> @legacy.ClientRecordAddDate.to_yaml
=> "--- 2010-04-11 14:23:01.000000000 Z\n...\n"
[7] pry(LegacyClient)> @legacy.ClientRecordAddDate
=> Sun, 11 Apr 2010 07:23:01 PDT -07:00
[8] pry(LegacyClient)> self.default_timezone
=> :utc

First, find a time zone name that actually exists in your Postgres DB cluster: 首先,找到Postgres数据库集群中实际存在的时区名称:

SELECT *
FROM   pg_timezone_names
WHERE  name ~~* '%Pacif%'
   OR  abbrev = 'PT';

Then set this time zone in your session: 然后在会话中设置此时区:

SET timezone = 'US/Pacific';

Which means values from timestamp [without time zone] columns are interpreted as being in this time zone, and timestamp [with time zone] is offset from / to UTC accordingly on input / output. 这意味着来自timestamp [without time zone]列的值被解释为处于该时区,并且timestamp [with time zone]于输入/输出的UTC偏移量。

There are many ways to set a config parameter in Postgres. 在Postgres中有很多方法可以设置配置参数。 Compare: 相比:

More information: 更多信息:

I solved this after a few days toiling with this issue. 经过几天的努力,我解决了这个问题。 It's somewhat of a subtle hack. 这有点微妙。 default_timezone in rails can be either :local or :utc . rails中的default_timezone可以是:local:utc So, since rails misinterpreted my Pacific-based Mysql records as 'utc' or -7 hours behind UTC, I had to change it back to UTC (really back to 'Pacific' since it was originally misinterpreted) and convert the value to a string. 因此,由于rails将我基于太平洋的Mysql记录误解为“ utc”或比UTC落后-7小时,因此我不得不将其改回UTC(由于最初被误解,所以实际上又改回了“ Pacific”)并将值转换为字符串。 ActiveRecord would then treat convert the string to Pacific (since in application.rb I have config.time_zone = 'Pacific Time (US & Canada)' ) and then save it to Postgres in correct UTC format! 然后,ActiveRecord将处理将字符串转换为Pacific的方法(因为在application.rb中,我有config.time_zone = 'Pacific Time (US & Canada)' ),然后以正确的UTC格式将其保存到Postgres!

[2] pry(LegacyClient)> @legacy.ClientRecordAddDate.utc.to_s
=> "2010-04-11 14:23:01"

In my hash that would capture the legacy mysql values, I would have the below for created_at and updated_at : 在捕获旧版mysql值的哈希中,我将使用created_atupdated_at的以下内容:

{
...
created_at: @legacy.ClientRecordAddDate.utc.to_s,
updated_at: @legacy.ClientRecordUpdateDate.utc.to_s
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM