Permalink
Browse files

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`.
  • Loading branch information...
1 parent f90aa72 commit b2ae07f0b218b7e92be1e8d7c23f9f9fb7aae56e @ShayDavidson ShayDavidson committed Aug 30, 2013
@@ -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.
@@ -53,17 +53,27 @@ def change(options)
# <tt>:months</tt>, <tt>:weeks</tt>, <tt>:days</tt>, <tt>:hours</tt>,
# <tt>:minutes</tt>, <tt>:seconds</tt>.
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
@@ -162,6 +162,12 @@ def test_advance
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)

0 comments on commit b2ae07f

Please sign in to comment.