Permalink
Browse files

Added Time.business_time_until() extension in the same way as it exte…

…nds Date class. Correspondingly updated README.
  • Loading branch information...
1 parent 6364e3c commit 04bce9b97656d59e2f1bf8865fd6547bd33bec33 Martins Kemme committed Feb 3, 2012
Showing with 95 additions and 0 deletions.
  1. +5 −0 README.rdoc
  2. +39 −0 lib/extensions/time.rb
  3. +51 −0 test/test_time_extensions.rb
View
@@ -82,6 +82,11 @@ I needed this, but taking into account business hours/days and holidays.
friday = Date.parse("December 24, 2010")
monday = Date.parse("December 27, 2010")
friday.business_days_until(monday) #=> 1
+
+ # or you can calculate business duration between two Time objects
+ ticket_reported = Time.parse("February 3, 2012, 10:40 am")
+ ticket_resolved = Time.parse("February 4, 2012, 10:50 am")
+ ticket_reported.business_time_until(ticket_resolved) #=> 8.hours + 10.minutes
== Usage in Rails
The code above should work on a rails console without any issue. You will want to add a line something like:
@@ -63,3 +63,42 @@ def roll_forward(time)
end
end
+
+class Time
+
+ def business_time_until(to_time)
+
+ # Make sure that we will calculate time from A to B "clockwise"
+ direction = 1
+ if self < to_time
+ time_a = self
+ time_b = to_time
+ else
+ time_a = to_time
+ time_b = self
+ direction = -1
+ end
+
+ # Align both times to the closest business hours
+ time_a = Time::roll_forward(time_a)
+ time_b = Time::roll_forward(time_b)
+
+ # If same date, then calculate difference straight forward
+ if time_a.to_date == time_b.to_date
+ result = time_b - time_a
+ return result *= direction
+ end
+
+ # Both times are in different dates
+ result = Time.parse(time_a.strftime('%Y-%m-%d ') + BusinessTime::Config.end_of_workday) - time_a # First day
+ result += time_b - Time.parse(time_b.strftime('%Y-%m-%d ') + BusinessTime::Config.beginning_of_workday) # Last day
+
+ # All days in between
+ duration_of_working_day = Time.parse(BusinessTime::Config.end_of_workday) - Time.parse(BusinessTime::Config.beginning_of_workday)
+ result += (time_a.to_date.business_days_until(time_b.to_date) - 1) * duration_of_working_day
+
+ # Make sure that sign is correct
+ result *= direction
+ end
+
+end
@@ -40,4 +40,55 @@ class TestTimeExtensions < Test::Unit::TestCase
assert_equal expecting, Time.end_of_workday(first)
end
+ # ===================
+
+ should "calculate business time between different times on the same date (clockwise)" do
+ time_a = Time.parse('2012-02-01 10:00')
+ time_b = Time.parse('2012-02-01 14:20')
+ assert_equal time_a.business_time_until(time_b), 260.minutes
+ end
+
+ should "calculate business time between different times on the same date (counter clockwise)" do
+ time_a = Time.parse('2012-02-01 10:00')
+ time_b = Time.parse('2012-02-01 14:20')
+ assert_equal time_b.business_time_until(time_a), -260.minutes
+ end
+
+ should "calculate business time only within business hours even if second endpoint is out of business time" do
+ time_a = Time.parse('2012-02-01 10:00')
+ time_b = Time.parse("2012-02-01 " + BusinessTime::Config.end_of_workday) + 24.minutes
+ first_result = time_a.business_time_until(time_b)
+ time_b = Time.parse('2012-02-01 '+ BusinessTime::Config.end_of_workday)
+ second_result = time_a.business_time_until(time_b)
+ assert_equal first_result, second_result
+ assert_equal first_result, 7.hours
+ end
+
+ should "calculate business time only within business hours even if the first endpoint is out of business time" do
+ time_a = Time.parse("2012-02-01 7:25")
+ time_b = Time.parse("2012-02-01 15:30")
+ first_result = time_a.business_time_until(time_b)
+ assert_equal first_result, 390.minutes
+ end
+
+ should "return correct time between two consecutive days" do
+ time_a = Time.parse('2012-02-01 10:00')
+ time_b = Time.parse('2012-02-02 10:00')
+ working_hours = Time.parse(BusinessTime::Config.end_of_workday) - Time.parse(BusinessTime::Config.beginning_of_workday)
+ assert_equal time_a.business_time_until(time_b), working_hours
+ end
+
+ should "calculate proper timing if there are several days between" do
+ time_a = Time.parse('2012-02-01 10:00')
+ time_b = Time.parse('2012-02-09 11:00')
+ duration_of_working_day = Time.parse(BusinessTime::Config.end_of_workday) - Time.parse(BusinessTime::Config.beginning_of_workday)
+ assert_equal time_a.business_time_until(time_b), 6 * duration_of_working_day + 1.hour
+ assert_equal time_b.business_time_until(time_a), -(6 * duration_of_working_day + 1.hour)
+ end
+
+ should "example provided in the documentation be correct :)" do
+ ticket_reported = Time.parse("February 3, 2012, 10:40 am")
+ ticket_resolved = Time.parse("February 4, 2012, 10:50 am")
+ assert_equal ticket_reported.business_time_until(ticket_resolved), 8.hours + 10.minutes
+ end
end

0 comments on commit 04bce9b

Please sign in to comment.