Milliseconds in your Timestamps.
We got 'em, you want 'em.
Shit needs to be PRECISE
MIT
class MillisecondsMigration < ActiveRecord::Migration | |
# Include non default date stamps here | |
# Key :table_name | |
# value [:column_names] | |
# NOTE: only MySQL 5.6.4 and above supports DATETIME's with more precision than a second. | |
TABLES_AND_COLUMNS = { | |
# Your :table_names here | |
} | |
STANDARD_ACTIVE_RECORD_COLUMNS = [:created_at, :updated_at] | |
TABLE_AND_COLUMNS.each {|k,v| v.concat(STANDARD_ACTIVE_RECORD_COLUMNS)} | |
def up | |
TABLE_AND_COLUMNS.each do |table, columns| | |
columns.each do |column| | |
# MySQL supports time precision down to microseconds -- DATETIME(6) | |
change_column table, column, :datetime, limit: 3 | |
end | |
end | |
end | |
def down | |
TABLE_AND_COLUMNS.each do |table, columns| | |
columns.each do |column| | |
echange_column table, column, :datetime | |
end | |
end | |
end | |
end |
# Save this in config/initializers/WHATEVER.rb | |
class Time | |
# Ruby will complain that it has already initialzed DATE_FORMATS because it has... | |
DATE_FORMATS = { | |
# Where 3N is the number of places after the decimal (.) | |
# If you want microseconds change 3N to 6N | |
:db => '%Y-%m-%d %H:%M:%S.%3N' | |
} | |
end |
Thanks, was helpful for me!
Time::DATE_FORMATS.merge!({ db: '%Y-%m-%d %H:%M:%S.%3N' })
also works for me and avoids the warning.
For (my own) reference: MySQL 5.6.4 changelog
is "echange_column" supposed to be "change_column"
This also works great for Postgresql, BUT, I will add that time.rb
ended up creating errors when I tried to create or update objects. My error being PG::InvalidDatetimeFormat
. Not using time.rb
and everything is perfect.
Nice. Here's if you want to convert all datetime columns, add indexes and avoid the Time warning:
class MillisecondsDateTime < ActiveRecord::Migration
def up
ActiveRecord::Base.connection.tables.each do |table|
ActiveRecord::Base.connection.columns(table).each do |column|
if column.type == :datetime
change_column table, column.name, :datetime, limit: 6
add_index table, column.name
end
end
end
end
def down
ActiveRecord::Base.connection.tables.each do |table|
ActiveRecord::Base.connection.columns(table).each do |column|
if column.type == :datetime
change_column table, column.name, :datetime
remove_index table, column.name
end
end
end
end
end
app/config/initializers/time.rb
Time::DATE_FORMATS[:db] = '%Y-%m-%d %H:%M:%S.%6N'
The initializer is not necessary with Rails 4.2.5. It just works with the correct database type DATETIME(6)
.
Additionally, adding this into an initializer will fix your migrations. All that is left after that is to make the change retroactive.
# Creates DATETIME(6) column types by default which support microseconds.
#
# Without it, regular DATETIME columns are created and Percona does not attach
# microseconds to the default DATETIME types. This has a rich history, refer to
# SQL Server DATETIME2.
ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter::NATIVE_DATABASE_TYPES[:datetime][:limit] = 6
I've created an updated gist with feedback from this thread.
See https://gist.github.com/MarkMurphy/93adca601b05acffb8b5601df09f66df
:datetime
:limit
to AbstractMysqlAdapter::NATIVE_DATABASE_TYPES[:datetime]
for future migrations.Is there a way to implement this in Teensy 4.1 or Arduino ? I am trying to develop a gunshot localization program to solve local gunfire at 2AM-4AM.
No problem!