From b2ae07f0b218b7e92be1e8d7c23f9f9fb7aae56e Mon Sep 17 00:00:00 2001 From: Shay Davidson Date: Fri, 30 Aug 2013 12:05:25 +0300 Subject: Added partial days support to `DateTime`'s `advance` method. You can now add partial days (e.g. 2.5.days) to `DateTime` with the advance method. This was acheived by mimicing the `advance` implementation in `Time`. --- activesupport/CHANGELOG.md | 4 ++++ .../core_ext/date_time/calculations.rb | 20 +++++++++++++++----- activesupport/test/core_ext/date_time_ext_test.rb | 6 ++++++ 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index f15297f279..97cb66b358 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -189,4 +189,8 @@ *Daniel Schierbeck* +* DateTime `advance` now supports partial days (`days: 1.5`) + + *Shay Davidson* + Please check [4-0-stable](https://github.com/rails/rails/blob/4-0-stable/activesupport/CHANGELOG.md) for previous changes. diff --git a/activesupport/lib/active_support/core_ext/date_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_time/calculations.rb index 8e5d723074..2d33a86466 100644 --- a/activesupport/lib/active_support/core_ext/date_time/calculations.rb +++ b/activesupport/lib/active_support/core_ext/date_time/calculations.rb @@ -53,17 +53,27 @@ class DateTime # :months, :weeks, :days, :hours, # :minutes, :seconds. def advance(options) + unless options[:weeks].nil? + options[:weeks], partial_weeks = options[:weeks].divmod(1) + options[:days] = options.fetch(:days, 0) + 7 * partial_weeks + end + + unless options[:days].nil? + options[:days], partial_days = options[:days].divmod(1) + options[:hours] = options.fetch(:hours, 0) + 24 * partial_days + end + d = to_date.advance(options) - datetime_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day) + time_advanced_by_date = change(:year => d.year, :month => d.month, :day => d.day) seconds_to_advance = \ options.fetch(:seconds, 0) + - options.fetch(:minutes, 0) * 60 + - options.fetch(:hours, 0) * 3600 + options.fetch(:minutes, 0) * 60 + + options.fetch(:hours, 0) * 3600 if seconds_to_advance.zero? - datetime_advanced_by_date + time_advanced_by_date else - datetime_advanced_by_date.since seconds_to_advance + time_advanced_by_date.since(seconds_to_advance) end end diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb index 0a40aeb96c..224172e39f 100644 --- a/activesupport/test/core_ext/date_time_ext_test.rb +++ b/activesupport/test/core_ext/date_time_ext_test.rb @@ -162,6 +162,12 @@ class DateTimeExtCalculationsTest < ActiveSupport::TestCase assert_equal DateTime.civil(2013,10,17,20,22,19), DateTime.civil(2005,2,28,15,15,10).advance(:years => 7, :months => 19, :weeks => 2, :days => 5, :hours => 5, :minutes => 7, :seconds => 9) end + def test_advance_partial_days + assert_equal DateTime.civil(2012,9,29,13,15,10), DateTime.civil(2012,9,28,1,15,10).advance(:days => 1.5) + assert_equal DateTime.civil(2012,9,28,13,15,10), DateTime.civil(2012,9,28,1,15,10).advance(:days => 0.5) + assert_equal DateTime.civil(2012,10,29,13,15,10), DateTime.civil(2012,9,28,1,15,10).advance(:days => 1.5, :months => 1) + end + def test_advanced_processes_first_the_date_deltas_and_then_the_time_deltas # If the time deltas were processed first, the following datetimes would be advanced to 2010/04/01 instead. assert_equal DateTime.civil(2010, 3, 29), DateTime.civil(2010, 2, 28, 23, 59, 59).advance(:months => 1, :seconds => 1) -- cgit v1.2.3 From 0fb33f3fda3958865fb62969ea6898acf7016aaf Mon Sep 17 00:00:00 2001 From: Shay Davidson Date: Mon, 2 Sep 2013 09:00:21 +0300 Subject: Fixed changelog --- activesupport/CHANGELOG.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 97cb66b358..60dfdd8c88 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,15 @@ +* DateTime `advance` now supports partial days. + + Before: + + DateTime.now.advance(days: 1, hours: 12) + + After: + + DateTime.now.advance(days: 1.5) + + *Shay Davidson* + * Ensure that autoloaded constants in all-caps nestings are marked as autoloaded. @@ -189,8 +201,4 @@ *Daniel Schierbeck* -* DateTime `advance` now supports partial days (`days: 1.5`) - - *Shay Davidson* - Please check [4-0-stable](https://github.com/rails/rails/blob/4-0-stable/activesupport/CHANGELOG.md) for previous changes. -- cgit v1.2.3