有没有办法将Rails默认时间戳更改为Ymd H:i:s(而不是Ymd H:i:su)或laravel忽略Ymd H的小数部分:i:su?

我有两个使用相同postgres DB的应用程序。 laravel应用程序和rails应用程序。 DB中的当前数据是Ymd H:i:s格式,但每当rails添加记录时,格式为Ymd H:i:su ,其中包括毫秒。

如果created_at日期是laravel中的引用,则会在laravel端导致以下错误: InvalidArgumentException Trailing data

Laravel模型可以改变它们的日期格式,所以我可以包括使它符合Ymd H:i:su然后我需要更新所有记录以在created_at日期(以及任何其他时间戳)中具有毫秒。 不幸的是,当我指定格式为Ymd H:i:s为laravel模型时,它不会忽略小数。 这就是为什么我现在正在寻找默认轨道以Ymd H:i:s格式保存的方法,而不是包括毫秒。 然后Rails和Laravel应用程序将使用相同的格式,并且不会有任何冲突。

我知道我可以进入数据库并将列类型更改为时间戳(0),它会截断小数,但我会更改框架保存的格式,而不是更改数据库将接受的内容。

Ymd H:i:sYmd H:i:su都是有效的时间戳…如果我可以让Rails使用Ymd H:i:s格式或让Laravel在查看时间戳时忽略.u以防止尾随数据错误,我会清楚。

有没有办法更改rails将时间戳保存到数据库的默认格式?

是否有办法让Larave Carbon忽略Ymd H:i:su格式中时间戳的小数部分?

谢谢

Rails方面的解决方案

在Rails(5.2)中使用的ActiveRecord似乎自动将十进制秒添加到1毫秒,保存created_atupdated_at或接受子秒的DB中的任何其他Timestamp列,如文件active_record/connection_adapters/abstract/quoting.rb所定义。

这是一个解决方法。 在访问模型(例如,ApplicationRecord模型文件)时Rails将始终读取的任何文件中的顶级添加此行。

 Time::DATE_FORMATS[:db] = '%Y-%m-%d %H:%M:%S.000000000' module ActiveRecord::ConnectionAdapters::Quoting alias_method :quoted_date_orig, :quoted_date if ! self.method_defined?(:quoted_date_orig) def quoted_date(*rest, **kwd) quoted = quoted_date_orig(*rest, **kwd) quoted.sub(/(\.\d*)\.\d{6}$/, '\1') end end 

在创建新记录后,您可以从Rails控制台确认它,

 MyModel.last.created_at.nsec # => 0 

或者直接访问DB以查看它。

警告

此更改不仅会影响created_atupdated_at ,还会影响数据库中的所有其他时间戳列。 我认为你仍然可以通过设置一个String而不是一个Time实例到一个Model实例来保存一个msec(或nsec)精度到这样一列的值,如my_model.col_msec_desired = "2018-01-02 03:04:05.678" ; 然后在保存记录时不会引用Time::DATE_FORMATS[:db]

Laravel方面的潜在解决方案

在撰写本文时(2018-10-18),这可能很棘手,但根据cmbertsch01最近的Laracastpost ,一项工作似乎正在进行中。

(注意:在评论之后的原始post后一天进行了重大更新。)

在Laravel / PHP中,您可以使用以下函数将DateTime转换为毫秒而不是毫秒:

 $date = date('Ymd H:i:s.u'); echo date('Ymd H:i:s', strtotime($date)); 

在Rails中,您可以在将时间对象发送到数据库之前更新它,如下所述:

 time.change(:usec => 0) 

你可以在application.rb中设置Time :: DATE_FORMATS [:db]

 Time::DATE_FORMATS[:db] = "Ymd H:i:su" 

看起来更像strftime格式