Skip to content

Instantly share code, notes, and snippets.

@azhao1981
Forked from MarkMurphy/README.md
Last active August 27, 2018 02:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save azhao1981/49ccdf3e8bee8eb75942e78e5ad55712 to your computer and use it in GitHub Desktop.
Save azhao1981/49ccdf3e8bee8eb75942e78e5ad55712 to your computer and use it in GitHub Desktop.
ActiveRecord: Store Milliseconds (or Microseconds) in Timestamps with Rails / MySQL

ActiveRecord: Store Milliseconds (or Microseconds) in DateTimes or Timestamps with Rails / MySQL

Milliseconds in your DateTimes or Timestamps.

We got 'em, you want 'em.

NOTE: only MySQL 5.6.4 and above supports DATETIME's with more precision than a second. For reference see MySQL 5.6.4 Changelog

Why

Shit needs to be PRECISE

LICENSE

MIT

class DatetimePrecisionMigration < ActiveRecord::Migration
def change
reversible do |change|
# Migrate Up
change.up do
table_columns do |table, column|
# MySQL supports time precision down to microseconds -- DATETIME(6)
change_column table, column, :datetime, limit: 6
end
end
# Migrate Down
change.down do
table_columns do |table, column|
change_column table, column, :datetime
end
end
# NOTE: only MySQL 5.6.4 and above supports DATETIME's with more precision
# than a second. See https://dev.mysql.com/doc/relnotes/mysql/5.6/en/news-5-6-4.html#mysqld-5-6-4-fractional-seconds
end
end
private
def table_columns
# Iterate through all tables in this environment's database
ActiveRecord::Base.connection.tables.each do |table|
# Iterate through all columns in table
ActiveRecord::Base.connection.columns(table).each do |column|
yield table, column.name if column.type == :datetime && block_given?
end
end
end
end
# Save this in config/initializers/mysql.rb (or whatever you want, filename doesn't matter.)
# Creates DATETIME(6) column types by default which support microseconds.
#
# Without it, only regular (second precise) DATETIME columns are created.
require 'active_record/connection_adapters/abstract_mysql_adapter'
module ActiveRecord::ConnectionAdapters
AbstractMysqlAdapter::NATIVE_DATABASE_TYPES[:datetime][:limit] = 6
end
# Save this in config/initializers/time.rb (or whatever you want, filename doesn't matter.)
# NOTE: Apparently, this initializer is not necessary with Rails 4.2.5 and up.
# It just works with the correct database type DATETIME(6).
# Where 6N is the number of places after the decimal (.)
# For less precision (eg. miliseconds), change 6N to 3N
Time::DATE_FORMATS[:db] = '%Y-%m-%d %H:%M:%S.%6N'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment