# Calculating Business Hours Left

**URL:** <https://rubytalk.org/t/calculating-business-hours-left/36732>\
**Category:** ruby-talk\
**Created:** [6 April 2007 05:55 UTC](https://rubytalk.org/t/calculating-business-hours-left/36732 "2007-04-06T05:55:05Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Gavin\_Kistner2](https://avatars.discourse-cdn.com/v4/letter/g/b9e5f3/32.png) [@Gavin\_Kistner2](https://rubytalk.org/u/Gavin_Kistner2)\
**Post date:** [6 April 2007 05:55 UTC](https://rubytalk.org/t/calculating-business-hours-left/36732/1 "2007-04-06T05:55:05Z")

</div>

current\_time = Time.new  
&nbsp;&nbsp;due\_time = # ... some Time instance in the future  
&nbsp;&nbsp;work\_hours\_left\_before\_I\_am\_screwed = # ... calculate

I'm writing a little task-tracking app to help me put out the most  
urgent fires. As above, given any two Time instances, I'd like to know  
how many hours are left to perform the task. This should skip weekends  
and hours outside of specified start- and end-hours for a work day.

Anyone got such code handy? Or feel like writing it for me? 🙂

Right now, my best idea involves looping over the range one day at a  
time and manually accumulating the available hours. It feels  
inelegant, but it's all I have right now.

---

<div class="post-metadata">

**Author:** ![Keith\_Fahlgren](https://avatars.discourse-cdn.com/v4/letter/k/e9c0ed/32.png) [@Keith\_Fahlgren](https://rubytalk.org/u/Keith_Fahlgren)\
**Post date:** [6 April 2007 14:13 UTC](https://rubytalk.org/t/calculating-business-hours-left/36732/2 "2007-04-06T14:13:31Z")

</div>

Hmm... no idea if this works, but it might be a start:

#!/usr/bin/env ruby  
class WorkHours  
&nbsp;&nbsp;SECONDS\_IN\_HOUR = 3600  
&nbsp;&nbsp;HOURS\_I\_WORK = (7..16)  
&nbsp;&nbsp;DAYS\_I\_WORK = (1..5)  
&nbsp;&nbsp;def self.diff\_times(a, b)  
&nbsp;&nbsp;&nbsp;&nbsp;hours =   
&nbsp;&nbsp;&nbsp;&nbsp;(a.to\_i..b.to\_i).step(SECONDS\_IN\_HOUR) {|t|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;time = Time.at(t)  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hours \<\< t if DAYS\_I\_WORK.include?(time.wday) &&  
HOURS\_I\_WORK.include?(time.hour)  
&nbsp;&nbsp;&nbsp;&nbsp;}  
&nbsp;&nbsp;&nbsp;&nbsp;return hours.length  
&nbsp;&nbsp;end  
end  
nil

now = Time.now  
=\> Fri Apr 06 07:12:08 PDT 2007  
twenty\_days\_from\_now = now + 1728000  
=\> Thu Apr 26 07:12:08 PDT 2007  
one\_day\_from\_now = now + 86400  
=\> Sat Apr 07 07:12:08 PDT 2007  
WorkHours.diff\_times(now, twenty\_days\_from\_now)  
=\> 141  
WorkHours.diff\_times(now, one\_day\_from\_now)  
=\> 10

HTH,  
Keith

> **···**
>
> On 4/5/07, Phrogz \<gavin@refinery.com\> wrote:
> 
> > &nbsp;&nbsp;current\_time = Time.new  
> > &nbsp;&nbsp;due\_time = # ... some Time instance in the future  
> > &nbsp;&nbsp;work\_hours\_left\_before\_I\_am\_screwed = # ... calculate
> > 
> > I'm writing a little task-tracking app to help me put out the most  
> > urgent fires. As above, given any two Time instances, I'd like to know  
> > how many hours are left to perform the task. This should skip weekends  
> > and hours outside of specified start- and end-hours for a work day.
> > 
> > Anyone got such code handy? Or feel like writing it for me? 🙂

---

<div class="post-metadata">

**Author:** ![Gavin\_Kistner2](https://avatars.discourse-cdn.com/v4/letter/g/b9e5f3/32.png) [@Gavin\_Kistner2](https://rubytalk.org/u/Gavin_Kistner2)\
**Post date:** [6 April 2007 14:25 UTC](https://rubytalk.org/t/calculating-business-hours-left/36732/3 "2007-04-06T14:25:09Z")

</div>

That feels like it might be good, thanks! I'll have to investigate  
more. It certainly looks cleaner than what I came up with:

class Time  
&nbsp;&nbsp;def at( hrs, mins=0 )  
&nbsp;&nbsp;&nbsp;&nbsp;self.class.parse strftime("%Y-%b-%d #{hrs}:#{mins}" )  
&nbsp;&nbsp;end  
end

# Fails for tasks one year or farther in the future  
def work\_hours\_until( due\_time, work\_starts\_at=9, work\_ends\_at=17 )  
&nbsp;&nbsp;start\_time = [  
&nbsp;&nbsp;&nbsp;&nbsp;Time.now,  
&nbsp;&nbsp;&nbsp;&nbsp;Time.parse( "#{work\_starts\_at}:00" )  
&nbsp;&nbsp;].max  
&nbsp;&nbsp;end\_time = [  
&nbsp;&nbsp;&nbsp;&nbsp;due\_time,  
&nbsp;&nbsp;&nbsp;&nbsp;due\_time.at( work\_ends\_at )  
&nbsp;&nbsp;].min

&nbsp;&nbsp;weekdays = 1..5  
&nbsp;&nbsp;one\_hour = 3600.0  
&nbsp;&nbsp;one\_day = one\_hour \* 24

&nbsp;&nbsp;if start\_time.yday == end\_time.yday  
&nbsp;&nbsp;&nbsp;&nbsp;if weekdays.include?( start\_time.wday )  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;( end\_time - start\_time ) / one\_hour  
&nbsp;&nbsp;&nbsp;&nbsp;else  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;else  
&nbsp;&nbsp;&nbsp;&nbsp;business\_hours = work\_ends\_at - work\_starts\_at

&nbsp;&nbsp;&nbsp;&nbsp;# Handle partial hours on the first day  
&nbsp;&nbsp;&nbsp;&nbsp;hours = ( start\_time.at( work\_ends\_at ) - start\_time ) / one\_hour

&nbsp;&nbsp;&nbsp;&nbsp;t = start\_time + one\_day  
&nbsp;&nbsp;&nbsp;&nbsp;until t.yday == due\_time.yday  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hours += business\_hours if weekdays.include?( t.wday )  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t += one\_day  
&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;# Handle partial hours on the last day  
&nbsp;&nbsp;&nbsp;&nbsp;if weekdays.include?( t.wday )  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;hours += ( end\_time - end\_time.at( work\_starts\_at ) ) / one\_hour  
&nbsp;&nbsp;&nbsp;&nbsp;end

&nbsp;&nbsp;&nbsp;&nbsp;hours  
&nbsp;&nbsp;end

end

> **···**
>
> On Apr 6, 8:13 am, "Keith Fahlgren" \<k...@audiobeta.com\> wrote:
> 
> > Hmm... no idea if this works, but it might be a start:
