# Finding the date of an event based on related events

**URL:** <https://www.ruby-forum.com/t/finding-the-date-of-an-event-based-on-related-events/143449>\
**Category:** Ruby\
**Created:** [July 18, 2008, 6:28pm UTC](https://www.ruby-forum.com/t/finding-the-date-of-an-event-based-on-related-events/143449 "2008-07-18T18:28:10Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Kaldrenon](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/59ef9b/32.png) [@Kaldrenon](https://www.ruby-forum.com/u/Kaldrenon)\
**Post date:** [July 18, 2008, 6:28pm UTC](https://www.ruby-forum.com/t/finding-the-date-of-an-event-based-on-related-events/143449/1 "2008-07-18T18:28:10Z")

</div>

Hi all,

I’m doing some planning to write a simple utility program for  
maintaining my schedule. The basic scenario is that, in my job, I have  
a series of multi-stage procedures to perform, and for each instance  
of the procedure, the stages need to happen a fixed number of business  
days apart (i.e, if step one happens on Monday, step two is Friday,  
but if step one is Tuesday, step two will be the following Monday). As  
one of the first steps of the program, I’m going to write a script to  
quickly spit out the calendar dates of all steps given the date of the  
first and the relative date (in business days) of all the others.

My question is, can you help me drum up a ‘smart’ way to take weekends  
and holidays into account? I know that with Ruby’s Date class you can  
use the - (minus) operator to subtract x days from the date of an  
existing event. which is how I can find the exact date once I’ve  
determined the number of total days it will be before it has been x  
business days.

But the “human” solution to the problem isn’t very efficient -  
iterating over the days with a counter, checking Date.wday, ignoring  
days that return 0 and 6, and spitting back the date at which the  
counter reaches x. I’d like to find a more elegant and computationally  
efficient solution.

If you’ve worked out this problem before, or a better solution seems  
readily available to you, I’d love input. If my explanation was  
unclear, I’ll gladly clarify anything.

-Andrew Fallows

---

<div class="post-metadata">

**Author:** ![Kaldrenon](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/59ef9b/32.png) [@Kaldrenon](https://www.ruby-forum.com/u/Kaldrenon)\
**Post date:** [July 19, 2008, 12:09am UTC](https://www.ruby-forum.com/t/finding-the-date-of-an-event-based-on-related-events/143449/2 "2008-07-19T00:09:13Z")

</div>

Kaldrenon wrote:

> Hi all,
> 
> I’m doing some planning to write a simple utility program for  
> maintaining my schedule. The basic scenario is that, in my job, I have  
> a series of multi-stage procedures to perform, and for each instance  
> of the procedure, the stages need to happen a fixed number of business  
> days apart (i.e, if step one happens on Monday, step two is Friday,  
> but if step one is Tuesday, step two will be the following Monday). As  
> one of the first steps of the program, I’m going to write a script to  
> quickly spit out the calendar dates of all steps given the date of the  
> first and the relative date (in business days) of all the others.
> 
> My question is, can you help me drum up a ‘smart’ way to take weekends  
> and holidays into account?  
> (…)
> 
> -Andrew Fallows

To exclude just the weekends you could do

class Date  
def add\_workdays(n)  
days\_to\_add =((self.cwday+n-1)/5)\*2 +n  
self + days\_to\_add  
end  
end

Which returns a new Date and seems to work with negative n’s. (Just  
wrote this code, don’t know if it’s bullet proof).

Holidays are a complication.Ideally the solution would allow for  
different holidays for different countries. Working hours could be  
specified, to enable calculating exactly when a 14 hour job starting on  
friday 24 december 15:15 in the US would finish.

Two applications I work with have these features. I’m not aware of a  
ruby solution/gem.

Regards,

Siep

---

<div class="post-metadata">

**Author:** ![Kaldrenon](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/59ef9b/32.png) [@Kaldrenon](https://www.ruby-forum.com/u/Kaldrenon)\
**Post date:** [July 19, 2008, 1:03pm UTC](https://www.ruby-forum.com/t/finding-the-date-of-an-event-based-on-related-events/143449/3 "2008-07-19T13:03:57Z")

</div>

On Fri, Jul 18, 2008 at 5:04 PM, Siep K. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> wrote this code, don’t know if it’s bullet proof).  
> It isn’t. It won’t work if you start from a weekend day.

Use today (Saturday), and do

d = Date.today.add\_workdays(5)  
puts d

=\> 2008-07-28

I like the approach, though.

Todd

---

<div class="post-metadata">

**Author:** ![Kaldrenon](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/59ef9b/32.png) [@Kaldrenon](https://www.ruby-forum.com/u/Kaldrenon)\
**Post date:** [July 19, 2008, 1:24pm UTC](https://www.ruby-forum.com/t/finding-the-date-of-an-event-based-on-related-events/143449/4 "2008-07-19T13:24:16Z")

</div>

-------- Original-Nachricht --------

> Datum: Sat, 19 Jul 2008 01:20:12 +0900  
> Von: Kaldrenon [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
> An: removed\_email\_address@domain.invalid  
> Betreff: Finding the date of an event based on related events.

> first and the relative date (in business days) of all the others.  
> days that return 0 and 6, and spitting back the date at which the  
> counter reaches x. I’d like to find a more elegant and computationally  
> efficient solution.
> 
> If you’ve worked out this problem before, or a better solution seems  
> readily available to you, I’d love input. If my explanation was  
> unclear, I’ll gladly clarify anything.
> 
> -Andrew Fallows

Dear Andrew,

reading previous responses to your post, I’d like to mention that you  
can get a list of public holidays from the Wikipedia

[List of holidays by country - Wikipedia](http://en.wikipedia.org/wiki/List_of_holidays_by_country),

for many countries, the movable holidays are mostly Easter and  
Pentecost,  
there is a listing of the Easter dates here (and Pentecost is, I  
believe, just 7 weeks later):

[http://www.assa.org.au/edm.html#List20](http://www.assa.org.au/edm.html#List20)

and, secondly, that for the main task you have – scheduling — you  
could use a “Constraint Programming” framework,  
such as this:

[http://gecoder.rubyforge.org/](http://gecoder.rubyforge.org/)

where you input all the conditions you have and get back a solution…

Best regards,

Axel

---

<div class="post-metadata">

**Author:** ![Kaldrenon](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/59ef9b/32.png) [@Kaldrenon](https://www.ruby-forum.com/u/Kaldrenon)\
**Post date:** [July 19, 2008, 8:52pm UTC](https://www.ruby-forum.com/t/finding-the-date-of-an-event-based-on-related-events/143449/5 "2008-07-19T20:52:17Z")

</div>

On Sat, Jul 19, 2008 at 1:13 PM, Todd B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> w\_days = [nil] + (Date.today…Date.today +  
> some\_number\_of\_days).map.select {|day| (day.cwday / 5).zero?}

That should be a 6 not a 5.

Todd

---

<div class="post-metadata">

**Author:** ![Kaldrenon](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/59ef9b/32.png) [@Kaldrenon](https://www.ruby-forum.com/u/Kaldrenon)\
**Post date:** [July 19, 2008, 8:15pm UTC](https://www.ruby-forum.com/t/finding-the-date-of-an-event-based-on-related-events/143449/6 "2008-07-19T20:15:23Z")

</div>

On Fri, Jul 18, 2008 at 11:20 AM, Kaldrenon [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> first and the relative date (in business days) of all the others.  
> days that return 0 and 6, and spitting back the date at which the  
> counter reaches x. I’d like to find a more elegant and computationally  
> efficient solution.
> 
> If you’ve worked out this problem before, or a better solution seems  
> readily available to you, I’d love input. If my explanation was  
> unclear, I’ll gladly clarify anything.
> 
> -Andrew Fallows

Maybe build a calendar beforehand that only includes work days…

w\_days = [nil] + (Date.today…Date.today +  
some\_number\_of\_days).map.select {|day| (day.cwday / 5).zero?}

…and then later…

w\_days -= holiday\_dates #which is an array of holiday Date objects  
chosen by you

…which afterwards you could walk through 6 at a time.

That, to me is somewhat elegant and robust, but Siep’s idea will work  
if the script/program will always run from a weekday. You will notice  
the peculiarity that Saturday acts like Monday and Sunday acts like  
Tuesday with Siep’s example.

I’d probably create a WorkCalendar class, though.

Todd

---

<div class="post-metadata">

**Author:** ![Kaldrenon](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/59ef9b/32.png) [@Kaldrenon](https://www.ruby-forum.com/u/Kaldrenon)\
**Post date:** [July 21, 2008, 12:14pm UTC](https://www.ruby-forum.com/t/finding-the-date-of-an-event-based-on-related-events/143449/7 "2008-07-21T12:14:47Z")

</div>

Following error message:  
===\> Patching for ruby18-gems-1.2.0  
===\> ruby18-gems-1.2.0 depends on file: /usr/local/bin/ruby18 - found  
===\> Applying FreeBSD patches for ruby18-gems-1.2.0  
=\> Patch patch-lib-rubygems-source\_info\_cache.rb failed to apply  
cleanly.  
\*\*\* Error code 1

Stop in /usr/ports/devel/ruby-gems

FreeBSD \*\*\*.vizion2000.net 7.0-STABLE FreeBSD 7.0-STABLE #0: Wed Jul 16  
09:27:38 PDT 2008 @\*\*\*.vizion2000.net:/usr/obj/usr/src/sys/GENERIC  
amd64

This system has just been upgraded from 6.3 to 7.0-Stable. Is there a  
possible connection here?

After getting this error I checked to make sure the port tree was  
uptofate  
and tried again with the same result.  
I am currently recompiling ruby\* ports on the system after a portsclean  
with:  
portupgrade -fr ruby\*  
Has anyone else experienced a similar problem?  
I will report result of recompile when it finishes.

David

---

<div class="post-metadata">

**Author:** ![Kaldrenon](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/59ef9b/32.png) [@Kaldrenon](https://www.ruby-forum.com/u/Kaldrenon)\
**Post date:** [July 21, 2008, 12:20pm UTC](https://www.ruby-forum.com/t/finding-the-date-of-an-event-based-on-related-events/143449/8 "2008-07-21T12:20:03Z")

</div>

> ===\> Patching for ruby18-gems-1.2.0  
> 09:27:38 PDT 2008  
> portupgrade -fr ruby\*  
> Has anyone else experienced a similar problem?  
> I will report result of recompile when it finishes.
> 
> David

The recompile produced the same result for ruby-gems.  
Is a pr needed here or is someone on to it already?  
David

---

<div class="post-metadata">

**Author:** ![Kaldrenon](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/k/59ef9b/32.png) [@Kaldrenon](https://www.ruby-forum.com/u/Kaldrenon)\
**Post date:** [July 21, 2008, 4:10pm UTC](https://www.ruby-forum.com/t/finding-the-date-of-an-event-based-on-related-events/143449/9 "2008-07-21T16:10:54Z")

</div>

On Jul 19, 2:08 pm, Todd B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> That, to me is somewhat elegant and robust, but Siep’s idea will work  
> if the script/program will always run from a weekday.

The general idea is that it will, given that the input will always be  
an event that the user is scheduling, and the context is scheduling  
for a M-F 5-day workweek setting. However, in the interest of  
versatility, I like to avoid coding in a “assuming the user knows what  
format to input” setup.

Thanks to all for the replies and advice! This is kind of a side  
project for me at the moment, so I haven’t yet gotten a chance to  
implement any of these things or test them, but I will be sure to get  
back to the group with my results when I do.

As for my holiday list, I think the simplest initial concept, for  
testing the basic functionality, is a Hash of Date objects based on my  
employer’s list of holidays for which employees get time off, as  
opposed to a list of all US holidays, but I’ll look into a flexible  
way to plug in a holiday list at a later point.

Thanks again,  
Andrew
