From b06b63915c8010c451aa6c66141596c72b85b0b3 Mon Sep 17 00:00:00 2001 From: Tom Lea Date: Thu, 4 Sep 2008 17:38:53 +0100 Subject: [PATCH] Made 1.5.days.ago == 36.hours.ago and 1.5.weeks.ago = 3.5.days ago Did not modify the behaviour of 1.5.months.ago, as this could meen different things to different people at different times. --- .../active_support/core_ext/time/calculations.rb | 10 ++++++ activesupport/test/core_ext/duration_test.rb | 34 ++++++++++++++++++++ 2 files changed, 44 insertions(+), 0 deletions(-) diff --git a/activesupport/lib/active_support/core_ext/time/calculations.rb b/activesupport/lib/active_support/core_ext/time/calculations.rb index 070f72c..ec2bdc0 100644 --- a/activesupport/lib/active_support/core_ext/time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/time/calculations.rb @@ -98,6 +98,16 @@ module ActiveSupport #:nodoc: # :months, :weeks, :days, :hours, # :minutes, :seconds. def advance(options) + unless options[:weeks].nil? + options[:weeks], partial_weeks = options[:weeks].divmod(1) + options[:days] = (options[:days] || 0) + 7 * partial_weeks + end + + unless options[:days].nil? + options[:days], partial_days = options[:days].divmod(1) + options[:hours] = (options[:hours] || 0) + 24 * partial_days + end + d = to_date.advance(options) time_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day) seconds_to_advance = (options[:seconds] || 0) + (options[:minutes] || 0) * 60 + (options[:hours] || 0) * 3600 diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb index f802ed8..b01fbf2 100644 --- a/activesupport/test/core_ext/duration_test.rb +++ b/activesupport/test/core_ext/duration_test.rb @@ -31,6 +31,40 @@ class DurationTest < Test::Unit::TestCase end uses_mocha 'TestDurationSinceAndAgoWithCurrentTime' do + def test_fractional_weeks + Time.stubs(:now).returns Time.local(2000) + + assert_in_delta((24 * 7 * 1.5).hours, 1.5.weeks, 2 ** -20) + assert_in_delta((24 * 7 * 1.7).hours, 1.7.weeks, 2 ** -20) + end + + def test_fractional_days + Time.stubs(:now).returns Time.local(2000) + + assert_in_delta((24 * 1.5).hours, 1.5.days, 2 ** -20) + assert_in_delta((24 * 1.7).hours, 1.7.days, 2 ** -20) + end + + def test_since_and_ago_with_fractional_days + Time.stubs(:now).returns Time.local(2000) + # since + assert_equal 36.hours.since, 1.5.days.since + assert_equal((24 * 1.7).hours.since, 1.7.days.since) + # ago + assert_equal 36.hours.ago, 1.5.days.ago + assert_equal((24 * 1.7).hours.ago, 1.7.days.ago) + end + + def test_since_and_ago_with_fractional_weeks + Time.stubs(:now).returns Time.local(2000) + # since + assert_equal((7 * 36).hours.since, 1.5.weeks.since) + assert_equal((7 * 24 * 1.7).hours.since, 1.7.weeks.since) + # ago + assert_equal((7 * 36).hours.ago, 1.5.weeks.ago) + assert_equal((7 * 24 * 1.7).hours.ago, 1.7.weeks.ago) + end + def test_since_and_ago_anchored_to_time_now_when_time_zone_default_not_set Time.zone_default = nil with_env_tz 'US/Eastern' do -- 1.6.0.1 From bb7cbcb01095885284c449a96661c8cadc8949a5 Mon Sep 17 00:00:00 2001 From: Tom Lea Date: Thu, 11 Sep 2008 16:41:19 +0100 Subject: [PATCH] Deprecated Float#years and Float#months, moved Numeric#years and Numeric#months into Integer. --- activesupport/lib/active_support/core_ext/float.rb | 2 + .../lib/active_support/core_ext/float/time.rb | 27 ++++++++++++ .../lib/active_support/core_ext/integer.rb | 2 + .../lib/active_support/core_ext/integer/time.rb | 45 ++++++++++++++++++++ .../lib/active_support/core_ext/numeric/time.rb | 10 ---- activesupport/test/core_ext/duration_test.rb | 18 ++++++++ 6 files changed, 94 insertions(+), 10 deletions(-) create mode 100644 activesupport/lib/active_support/core_ext/float/time.rb create mode 100644 activesupport/lib/active_support/core_ext/integer/time.rb diff --git a/activesupport/lib/active_support/core_ext/float.rb b/activesupport/lib/active_support/core_ext/float.rb index 86862b7..af166aa 100644 --- a/activesupport/lib/active_support/core_ext/float.rb +++ b/activesupport/lib/active_support/core_ext/float.rb @@ -1,5 +1,7 @@ require 'active_support/core_ext/float/rounding' +require 'active_support/core_ext/float/time' class Float #:nodoc: include ActiveSupport::CoreExtensions::Float::Rounding + include ActiveSupport::CoreExtensions::Float::Time end diff --git a/activesupport/lib/active_support/core_ext/float/time.rb b/activesupport/lib/active_support/core_ext/float/time.rb new file mode 100644 index 0000000..6229cfe --- /dev/null +++ b/activesupport/lib/active_support/core_ext/float/time.rb @@ -0,0 +1,27 @@ +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module Float #:nodoc: + module Time + # Deprication helper methods not available as core_ext is loaded first. + def years + ::ActiveSupport::Deprecation.warn(self.class.deprecated_method_warning(:years), caller) + years_without_deprecation + end + def months + ::ActiveSupport::Deprecation.warn(self.class.deprecated_method_warning(:months), "Fractional months are not respected. Use .to_i before ", caller) + months_without_deprecation + end + + def months_without_deprecation + ActiveSupport::Duration.new(self * 30.days, [[:months, self]]) + end + alias :month :months + + def years_without_deprecation + ActiveSupport::Duration.new(self * 365.25.days, [[:years, self]]) + end + alias :year :years + end + end + end +end \ No newline at end of file diff --git a/activesupport/lib/active_support/core_ext/integer.rb b/activesupport/lib/active_support/core_ext/integer.rb index d1e6d76..18a7a40 100644 --- a/activesupport/lib/active_support/core_ext/integer.rb +++ b/activesupport/lib/active_support/core_ext/integer.rb @@ -1,7 +1,9 @@ require 'active_support/core_ext/integer/even_odd' require 'active_support/core_ext/integer/inflections' +require 'active_support/core_ext/integer/time' class Integer #:nodoc: include ActiveSupport::CoreExtensions::Integer::EvenOdd include ActiveSupport::CoreExtensions::Integer::Inflections + include ActiveSupport::CoreExtensions::Integer::Time end diff --git a/activesupport/lib/active_support/core_ext/integer/time.rb b/activesupport/lib/active_support/core_ext/integer/time.rb new file mode 100644 index 0000000..356e145 --- /dev/null +++ b/activesupport/lib/active_support/core_ext/integer/time.rb @@ -0,0 +1,45 @@ +module ActiveSupport #:nodoc: + module CoreExtensions #:nodoc: + module Integer #:nodoc: + # Enables the use of time calculations and declarations, like 45.minutes + 2.hours + 4.years. + # + # These methods use Time#advance for precise date calculations when using from_now, ago, etc. + # as well as adding or subtracting their results from a Time object. For example: + # + # # equivalent to Time.now.advance(:months => 1) + # 1.month.from_now + # + # # equivalent to Time.now.advance(:years => 2) + # 2.years.from_now + # + # # equivalent to Time.now.advance(:months => 4, :years => 5) + # (4.months + 5.years).from_now + # + # While these methods provide precise calculation when used as in the examples above, care + # should be taken to note that this is not true if the result of `months', `years', etc is + # converted before use: + # + # # equivalent to 30.days.to_i.from_now + # 1.month.to_i.from_now + # + # # equivalent to 365.25.days.to_f.from_now + # 1.year.to_f.from_now + # + # In such cases, Ruby's core + # Date[http://stdlib.rubyonrails.org/libdoc/date/rdoc/index.html] and + # Time[http://stdlib.rubyonrails.org/libdoc/time/rdoc/index.html] should be used for precision + # date and time arithmetic + module Time + def months + ActiveSupport::Duration.new(self * 30.days, [[:months, self]]) + end + alias :month :months + + def years + ActiveSupport::Duration.new(self * 365.25.days, [[:years, self]]) + end + alias :year :years + end + end + end +end diff --git a/activesupport/lib/active_support/core_ext/numeric/time.rb b/activesupport/lib/active_support/core_ext/numeric/time.rb index aac698f..bc7f180 100644 --- a/activesupport/lib/active_support/core_ext/numeric/time.rb +++ b/activesupport/lib/active_support/core_ext/numeric/time.rb @@ -60,16 +60,6 @@ module ActiveSupport #:nodoc: end alias :fortnight :fortnights - def months - ActiveSupport::Duration.new(self * 30.days, [[:months, self]]) - end - alias :month :months - - def years - ActiveSupport::Duration.new(self * 365.25.days, [[:years, self]]) - end - alias :year :years - # Reads best without arguments: 10.minutes.ago def ago(time = ::Time.now) time - self diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb index b01fbf2..7b767c8 100644 --- a/activesupport/test/core_ext/duration_test.rb +++ b/activesupport/test/core_ext/duration_test.rb @@ -64,6 +64,24 @@ class DurationTest < Test::Unit::TestCase assert_equal((7 * 36).hours.ago, 1.5.weeks.ago) assert_equal((7 * 24 * 1.7).hours.ago, 1.7.weeks.ago) end + + def test_deprecated_fractional_years + assert_deprecated{1.0.years} + assert_deprecated{1.5.years} + assert_not_deprecated{1.years} + assert_deprecated{1.0.year} + assert_deprecated{1.5.year} + assert_not_deprecated{1.year} + end + + def test_deprecated_fractional_months + assert_deprecated{1.5.months} + assert_deprecated{1.0.months} + assert_not_deprecated{1.months} + assert_deprecated{1.5.month} + assert_deprecated{1.0.month} + assert_not_deprecated{1.month} + end def test_since_and_ago_anchored_to_time_now_when_time_zone_default_not_set Time.zone_default = nil -- 1.6.0.1 From 7367c4c22b447759abeb9e9304b4495e6543f7fc Mon Sep 17 00:00:00 2001 From: Tom Lea Date: Tue, 16 Sep 2008 09:18:44 +0100 Subject: [PATCH] Added deprecated warning messages to Float#months and Float#years deprications. --- .../lib/active_support/core_ext/float/time.rb | 4 ++-- activesupport/test/core_ext/duration_test.rb | 18 ++++++++++-------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/activesupport/lib/active_support/core_ext/float/time.rb b/activesupport/lib/active_support/core_ext/float/time.rb index 6229cfe..13f2e0d 100644 --- a/activesupport/lib/active_support/core_ext/float/time.rb +++ b/activesupport/lib/active_support/core_ext/float/time.rb @@ -4,11 +4,11 @@ module ActiveSupport #:nodoc: module Time # Deprication helper methods not available as core_ext is loaded first. def years - ::ActiveSupport::Deprecation.warn(self.class.deprecated_method_warning(:years), caller) + ::ActiveSupport::Deprecation.warn(self.class.deprecated_method_warning(:years, "Fractional years are not respected. Convert value to integer before calling #years."), caller) years_without_deprecation end def months - ::ActiveSupport::Deprecation.warn(self.class.deprecated_method_warning(:months), "Fractional months are not respected. Use .to_i before ", caller) + ::ActiveSupport::Deprecation.warn(self.class.deprecated_method_warning(:months, "Fractional months are not respected. Convert value to integer before calling #months."), caller) months_without_deprecation end diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb index 7b767c8..d1b15fd 100644 --- a/activesupport/test/core_ext/duration_test.rb +++ b/activesupport/test/core_ext/duration_test.rb @@ -66,20 +66,22 @@ class DurationTest < Test::Unit::TestCase end def test_deprecated_fractional_years - assert_deprecated{1.0.years} - assert_deprecated{1.5.years} + years_re = /Fractional years are not respected\. Convert value to integer before calling #years\./ + assert_deprecated(years_re){1.0.years} + assert_deprecated(years_re){1.5.years} assert_not_deprecated{1.years} - assert_deprecated{1.0.year} - assert_deprecated{1.5.year} + assert_deprecated(years_re){1.0.year} + assert_deprecated(years_re){1.5.year} assert_not_deprecated{1.year} end def test_deprecated_fractional_months - assert_deprecated{1.5.months} - assert_deprecated{1.0.months} + months_re = /Fractional months are not respected\. Convert value to integer before calling #months\./ + assert_deprecated(months_re){1.5.months} + assert_deprecated(months_re){1.0.months} assert_not_deprecated{1.months} - assert_deprecated{1.5.month} - assert_deprecated{1.0.month} + assert_deprecated(months_re){1.5.month} + assert_deprecated(months_re){1.0.month} assert_not_deprecated{1.month} end -- 1.6.0.1