mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Format the datetime string according to the precision of the datetime field.
Incompatible to rounding behavior between MySQL 5.6 and earlier. In 5.5, when you insert `2014-08-17 12:30:00.999999` the fractional part is ignored. In 5.6, it's rounded to `2014-08-17 12:30:01`: http://bugs.mysql.com/bug.php?id=68760
This commit is contained in:
parent
ae419af666
commit
4157f5d172
4 changed files with 62 additions and 1 deletions
|
@ -1,3 +1,14 @@
|
|||
* Format the datetime string according to the precision of the datetime field.
|
||||
|
||||
Incompatible to rounding behavior between MySQL 5.6 and earlier.
|
||||
|
||||
In 5.5, when you insert `2014-08-17 12:30:00.999999` the fractional part
|
||||
is ignored. In 5.6, it's rounded to `2014-08-17 12:30:01`:
|
||||
|
||||
http://bugs.mysql.com/bug.php?id=68760
|
||||
|
||||
*Ryuta Kamizono*
|
||||
|
||||
* Allow precision option for MySQL datetimes.
|
||||
|
||||
*Ryuta Kamizono*
|
||||
|
|
|
@ -688,7 +688,7 @@ module ActiveRecord
|
|||
|
||||
m.register_type(%r(datetime)i) do |sql_type|
|
||||
precision = extract_precision(sql_type)
|
||||
Type::DateTime.new(precision: precision)
|
||||
MysqlDateTime.new(precision: precision)
|
||||
end
|
||||
|
||||
m.register_type(%r(enum)i) do |sql_type|
|
||||
|
@ -884,6 +884,22 @@ module ActiveRecord
|
|||
TableDefinition.new(native_database_types, name, temporary, options, as)
|
||||
end
|
||||
|
||||
class MysqlDateTime < Type::DateTime # :nodoc:
|
||||
def type_cast_for_database(value)
|
||||
if value.acts_like?(:time) && value.respond_to?(:usec)
|
||||
result = super.to_s(:db)
|
||||
case precision
|
||||
when 1..6
|
||||
"#{result}.#{sprintf("%0#{precision}d", value.usec / 10**(6 - precision))}"
|
||||
else
|
||||
result
|
||||
end
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class MysqlString < Type::String # :nodoc:
|
||||
def type_cast_for_database(value)
|
||||
case value
|
||||
|
|
|
@ -2,6 +2,9 @@ require 'cases/helper'
|
|||
|
||||
if mysql_56?
|
||||
class DateTimeTest < ActiveRecord::TestCase
|
||||
self.use_transactional_fixtures = false
|
||||
|
||||
class Foo < ActiveRecord::Base; end
|
||||
|
||||
def test_default_datetime_precision
|
||||
ActiveRecord::Base.connection.create_table(:foos, force: true)
|
||||
|
@ -50,6 +53,20 @@ if mysql_56?
|
|||
assert_equal 4, mysql_datetime_precision('foos', 'updated_at')
|
||||
end
|
||||
|
||||
def test_formatting_datetime_according_to_precision
|
||||
ActiveRecord::Base.connection.create_table(:foos, force: true) do |t|
|
||||
t.datetime :created_at, precision: 0
|
||||
t.datetime :updated_at, precision: 4
|
||||
end
|
||||
date = ::Time.utc(2014, 8, 17, 12, 30, 0, 999999)
|
||||
Foo.create!(created_at: date, updated_at: date)
|
||||
assert foo = Foo.find_by(created_at: date)
|
||||
assert_equal date.to_s, foo.created_at.to_s
|
||||
assert_equal date.to_s, foo.updated_at.to_s
|
||||
assert_equal 000000, foo.created_at.usec
|
||||
assert_equal 999900, foo.updated_at.usec
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def mysql_datetime_precision(table_name, column_name)
|
||||
|
|
|
@ -2,6 +2,9 @@ require 'cases/helper'
|
|||
|
||||
if mysql_56?
|
||||
class DateTimeTest < ActiveRecord::TestCase
|
||||
self.use_transactional_fixtures = false
|
||||
|
||||
class Foo < ActiveRecord::Base; end
|
||||
|
||||
def test_default_datetime_precision
|
||||
ActiveRecord::Base.connection.create_table(:foos, force: true)
|
||||
|
@ -50,6 +53,20 @@ if mysql_56?
|
|||
assert_equal 4, mysql_datetime_precision('foos', 'updated_at')
|
||||
end
|
||||
|
||||
def test_formatting_datetime_according_to_precision
|
||||
ActiveRecord::Base.connection.create_table(:foos, force: true) do |t|
|
||||
t.datetime :created_at, precision: 0
|
||||
t.datetime :updated_at, precision: 4
|
||||
end
|
||||
date = ::Time.utc(2014, 8, 17, 12, 30, 0, 999999)
|
||||
Foo.create!(created_at: date, updated_at: date)
|
||||
assert foo = Foo.find_by(created_at: date)
|
||||
assert_equal date.to_s, foo.created_at.to_s
|
||||
assert_equal date.to_s, foo.updated_at.to_s
|
||||
assert_equal 000000, foo.created_at.usec
|
||||
assert_equal 999900, foo.updated_at.usec
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def mysql_datetime_precision(table_name, column_name)
|
||||
|
|
Loading…
Reference in a new issue