From 7107c831075d755fa4a745b189b2f9b000080868 Mon Sep 17 00:00:00 2001 From: Rich Daley Date: Mon, 4 Dec 2017 13:40:37 +0000 Subject: [PATCH] Add an in_calendar_months feature --- README.md | 3 ++ lib/time_difference.rb | 26 +++++++++++++++-- spec/time_difference_spec.rb | 54 ++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7d2189a..9158917 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,9 @@ TimeDifference.between(start_time, end_time).in_years TimeDifference.between(start_time, end_time).in_months => 12.0 +TimeDifference.between(start_time, end_time).in_calendar_months +=> 12.0 + TimeDifference.between(start_time, end_time).in_weeks => 52.14 diff --git a/lib/time_difference.rb b/lib/time_difference.rb index 589e202..20b0ec3 100644 --- a/lib/time_difference.rb +++ b/lib/time_difference.rb @@ -18,6 +18,10 @@ def in_years def in_months (@time_diff / (1.day * 30.42)).round(2) end + + def in_calendar_months + months_between(@start_time, @end_time) + end def in_weeks in_component(:weeks) @@ -82,10 +86,13 @@ def humanize private def initialize(start_time, end_time) - start_time = time_in_seconds(start_time) - end_time = time_in_seconds(end_time) + @start_time = start_time.to_time + @end_time = end_time.to_time + + start_time_s = time_in_seconds(start_time) + end_time_s = time_in_seconds(end_time) - @time_diff = (end_time - start_time).abs + @time_diff = (end_time_s - start_time_s).abs end def time_in_seconds(time) @@ -95,5 +102,18 @@ def time_in_seconds(time) def in_component(component) (@time_diff / 1.send(component)).round(2) end + + def months_between(t1, t2) + months_excl_days = (t2.year*12 + t2.month) - (t1.year*12 + t1.month) + if t2.day > t1.day + months_excl_days + elsif t2.day < t1.day + months_excl_days - 1 + elsif t2.seconds_since_midnight >= t1.seconds_since_midnight + months_excl_days + else + months_excl_days - 1 + end + end end diff --git a/spec/time_difference_spec.rb b/spec/time_difference_spec.rb index e1e7f8c..26bddda 100644 --- a/spec/time_difference_spec.rb +++ b/spec/time_difference_spec.rb @@ -181,4 +181,58 @@ def self.with_each_class(&block) end end end + + describe '#in_calendar_months' do + with_each_class do |clazz| + it 'considers Sep-4 to Dec-4 to be 3 months' do + start_time = clazz.new(2017, 9, 4) + end_time = clazz.new(2017, 12, 4) + + expect(TimeDifference.between(start_time, end_time).in_calendar_months).to eq(3) + end + it 'considers Aug-4 to Nov-4 to be 3 months' do + start_time = clazz.new(2017, 8, 4) + end_time = clazz.new(2017, 11, 4) + + expect(TimeDifference.between(start_time, end_time).in_calendar_months).to eq(3) + end + it 'considers Sep-4 to Dec-3 to be 2 months' do + start_time = clazz.new(2017, 9, 4) + end_time = clazz.new(2017, 12, 3) + + expect(TimeDifference.between(start_time, end_time).in_calendar_months).to eq(2) + end + it 'considers Sep-4 to Dec-31 to be 3 months' do + start_time = clazz.new(2017, 9, 4) + end_time = clazz.new(2017, 12, 31) + + expect(TimeDifference.between(start_time, end_time).in_calendar_months).to eq(3) + end + it 'considers 2016-Sep-4 to 2017-Sep-4 to be 12 months' do + start_time = clazz.new(2016, 9, 4) + end_time = clazz.new(2017, 9, 4) + + expect(TimeDifference.between(start_time, end_time).in_calendar_months).to eq(12) + end + it 'considers 2016-Sep-4 to 2017-Dec-31 to be 15 months' do + start_time = clazz.new(2016, 9, 4) + end_time = clazz.new(2017, 12, 31) + + expect(TimeDifference.between(start_time, end_time).in_calendar_months).to eq(15) + end + end + it 'counts months on the day when time2 > time1' do + start_time = Time.new(2017, 9, 4, 12, 15) + end_time = Time.new(2017, 12, 4, 12, 22) + + expect(TimeDifference.between(start_time, end_time).in_calendar_months).to eq(3) + end + it 'does not count months on the day when time2 < time1' do + start_time = Time.new(2017, 9, 4, 12, 15) + end_time = Time.new(2017, 12, 4, 12, 10) + + expect(TimeDifference.between(start_time, end_time).in_calendar_months).to eq(2) + end + end + end