From daee01c4944b5bfeb0b27faf94542cde8598611b Mon Sep 17 00:00:00 2001 From: Josh Symonds Date: Thu, 19 Feb 2009 09:45:44 -0600 Subject: [PATCH] Rails should now support two-digit years for all date fields. --- .../lib/active_record/attribute_methods.rb | 11 ++++++++--- activerecord/lib/active_record/base.rb | 8 ++++++++ .../abstract/schema_definitions.rb | 10 ++++++++++ .../active_support/core_ext/string/conversions.rb | 2 +- activesupport/test/core_ext/string_ext_test.rb | 8 ++++++++ 5 files changed, 35 insertions(+), 4 deletions(-) diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index 3ffc489..4bebdf9 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -307,10 +307,15 @@ module ActiveRecord def write_attribute(attr_name, value) attr_name = attr_name.to_s @attributes_cache.delete(attr_name) - if (column = column_for_attribute(attr_name)) && column.number? - @attributes[attr_name] = convert_number_column_value(value) + column = column_for_attribute(attr_name) + @attributes[attr_name] = if column && column.number? + convert_number_column_value(value) + elsif column && column.date? + convert_date_column_value(value) + elsif column && column.time? + convert_time_column_value(value) else - @attributes[attr_name] = value + value end end diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 78c6ac2..ba64ffe 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -2927,6 +2927,14 @@ module ActiveRecord #:nodoc: value end end + + def convert_time_column_value(value) + value.to_time + end + + def convert_date_column_value(value) + value.to_date + end def remove_attributes_protected_from_mass_assignment(attributes) safe_attributes = diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb index 24c734c..553c42c 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb @@ -42,6 +42,16 @@ module ActiveRecord def number? type == :integer || type == :float || type == :decimal end + + # Returns +true+ if the column is a date. + def date? + type == :date + end + + # Returns +true+ if the column is a time or a datetime. + def time? + type == :time || type == :datetime + end def has_default? !default.nil? diff --git a/activesupport/lib/active_support/core_ext/string/conversions.rb b/activesupport/lib/active_support/core_ext/string/conversions.rb index d4334dc..7598f8d 100644 --- a/activesupport/lib/active_support/core_ext/string/conversions.rb +++ b/activesupport/lib/active_support/core_ext/string/conversions.rb @@ -16,7 +16,7 @@ module ActiveSupport #:nodoc: end def to_date - ::Date.new(*::Date._parse(self, false).values_at(:year, :mon, :mday)) + ::Date.new(*::Date._parse(self, true).values_at(:year, :mon, :mday)) end def to_datetime diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb index e232bf8..0492551 100644 --- a/activesupport/test/core_ext/string_ext_test.rb +++ b/activesupport/test/core_ext/string_ext_test.rb @@ -104,6 +104,14 @@ class StringInflectionsTest < Test::Unit::TestCase def test_string_to_date assert_equal Date.new(2005, 2, 27), "2005-02-27".to_date end + + def test_string_to_date_with_two_digit_year_post_millenium + assert_equal Date.new(2005, 2, 27), "02/27/05".to_date + end + + def test_string_to_date_with_two_digit_year_pre_millenium + assert_equal Date.new(1995, 2, 27), "02/02/95".to_date + end def test_access s = "hello" -- 1.5.5.1 From d68de323328544d521579393c4498fe1eab64693 Mon Sep 17 00:00:00 2001 From: Josh Symonds Date: Thu, 19 Feb 2009 12:59:12 -0600 Subject: [PATCH] Added better tests and made the location of the tests more obvious. --- activerecord/lib/active_record/base.rb | 24 ++++++++++++++- activerecord/test/cases/base_test.rb | 48 ++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index ba64ffe..c7a0a26 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -2929,11 +2929,31 @@ module ActiveRecord #:nodoc: end def convert_time_column_value(value) - value.to_time + if value.is_a?(String) && value.blank? + nil + elsif value.is_a?(String) + begin + value.to_time + rescue ArgumentError + value # The date is not formatted correctly so it might be a timezone, let the timezone handlers deal with it + end + else + value + end end def convert_date_column_value(value) - value.to_date + if value.is_a?(String) && value.blank? + nil + elsif value.is_a?(String) + begin + value.to_date + rescue ArgumentError + value # The time is not formatted correctly so it might be a timezone, let the timezone handlers deal with it + end + else + value + end end def remove_attributes_protected_from_mass_assignment(attributes) diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 973bb56..2d40cc3 100755 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -1172,6 +1172,54 @@ class BasicsTest < ActiveRecord::TestCase topic.attributes = attributes assert_equal Time.local(2000, 1, 1, 5, 42, 0), topic.bonus_time end + + def test_time_format_post_millenium_with_datetime + # Oracle, and Sybase do not have a TIME datatype. + return true if current_adapter?(:OracleAdapter, :SybaseAdapter) + + attributes = { + "bonus_time" => "01/01/07 2:00AM" + } + topic = Topic.find(1) + topic.attributes = attributes + assert_equal DateTime.new(2007,01,01,2,0), topic.bonus_time + end + + def test_time_format_pre_millenium_with_datetime + # Oracle, and Sybase do not have a TIME datatype. + return true if current_adapter?(:OracleAdapter, :SybaseAdapter) + + attributes = { + "bonus_time" => "01/01/77 2:00AM" + } + topic = Topic.find(1) + topic.attributes = attributes + assert_equal DateTime.new(1977,01,01,2,0), topic.bonus_time + end + + def test_time_format_post_millenium_with_date + # Oracle, and Sybase do not have a TIME datatype. + return true if current_adapter?(:OracleAdapter, :SybaseAdapter) + + attributes = { + "last_read" => "01/01/09" + } + topic = Topic.find(1) + topic.attributes = attributes + assert_equal Date.new(2009,01,01), topic.last_read + end + + def test_time_format_pre_millenium_with_date + # Oracle, and Sybase do not have a TIME datatype. + return true if current_adapter?(:OracleAdapter, :SybaseAdapter) + + attributes = { + "last_read" => "01/01/77" + } + topic = Topic.find(1) + topic.attributes = attributes + assert_equal Date.new(1977,01,01), topic.last_read + end def test_boolean b_nil = Booleantest.create({ "value" => nil }) -- 1.5.5.1 From 43fa49dc2d7e590e6a2633ed9dec8dd0f01030ea Mon Sep 17 00:00:00 2001 From: Josh Symonds Date: Thu, 19 Feb 2009 13:04:30 -0600 Subject: [PATCH] Added negative case to make it entirely clear what we're testing --- activerecord/test/cases/base_test.rb | 12 ++++++++++++ 1 files changed, 12 insertions(+), 0 deletions(-) diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 2d40cc3..909d37d 100755 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -1173,6 +1173,18 @@ class BasicsTest < ActiveRecord::TestCase assert_equal Time.local(2000, 1, 1, 5, 42, 0), topic.bonus_time end + def test_time_format_with_two_digit_years + # Oracle, and Sybase do not have a TIME datatype. + return true if current_adapter?(:OracleAdapter, :SybaseAdapter) + + attributes = { + "last_read" => "01/01/77" + } + topic = Topic.find(1) + topic.attributes = attributes + assert_not_equal DateTime.new(77,01,01,2,0), topic.last_read + end + def test_time_format_post_millenium_with_datetime # Oracle, and Sybase do not have a TIME datatype. return true if current_adapter?(:OracleAdapter, :SybaseAdapter) -- 1.5.5.1