Forum: Ruby Detecting holidays

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Aee77dba395ece0a04c688b05b07cd63?d=identicon&s=25 Daniel Berger (Guest)
on 2007-01-02 17:36
(Received via mailing list)
Hi all,

Well, it took seven years, but I've finally been annoyed enough by
reports failing on national holidays to say something.  Report writers
know the routine:

Them: Why did the report fail for Jan. 1st?
Me: National holiday. There was no data to grab.  Ignore the failure.
Them: Oh, right.

Repeat again for Memorial Day, July 4th, Thanksgiving, and Christmas.

Is there a package out there that deals with national holidays (for any
nation)?  The only thing I came across what date2, but that only seems
to handle Japanese national holidays.  I guess I'm looking for
something like Perl's Date::Calc [1] module or, more specifically, it's
Date::Calendar::Profiles [2] module.  Or something like Perl's
Date::Holidays::XXX [3] approach (I'm not sure which is preferred these
days).

Ideally, I'd like to be able to do something like:

if Date.today.is_national_holiday?
   exit # Don't run report on this day
end

And no, it's not a simple matter of using something more flexible than
cron because some reports pull data from X days back or ahead, not on
the date they're run.

Thoughts?

- Dan

[1] http://search.cpan.org/~stbey/Date-Calc-5.4/Calendar.pod
[2]
http://search.cpan.org/~stbey/Date-Calc-5.4/lib/Da...
[3]
http://search.cpan.org/~jonasbn/Date-Holidays-0.08...
6d3c187a8b3ef53b08e3e7e8572c4fea?d=identicon&s=25 Jeremy McAnally (Guest)
on 2007-01-02 17:56
(Received via mailing list)
Try this:

class Date
  def is_national_holiday?
     this_year = self.year.to_s
     # Not perfect; Thanksgiving and Easter change...
     dates = [this_year + '-12-25', this_year + '-12-24', this_year +
'-1-1', this_year + '-7-4', this_year + '-11-28']

     if (dates.include?(self.to_s)):
        return true
     else
        return false
     end
   end
end



irb(main):263:0> christmas = Date.parse('2007-12-25')
=> #<Date: 4908919/2,0,2299161>
irb(main):264:0> christmas.is_national_holiday?
=> true
irb(main):265:0> today = Date.today
=> #<Date: 4908205/2,0,2299161>
irb(main):266:0> today.is_national_holiday?
=> false

Again, it doesn't get Thanksgiving right or others that change like
Easter.  If you want, I could hack it in; otherwise, this should get
you on the right path. ;)

--Jeremy

On 1/2/07, Daniel Berger <djberg96@gmail.com> wrote:
> Repeat again for Memorial Day, July 4th, Thanksgiving, and Christmas.
>
> - Dan
>
> [1] http://search.cpan.org/~stbey/Date-Calc-5.4/Calendar.pod
> [2]
> http://search.cpan.org/~stbey/Date-Calc-5.4/lib/Da...
> [3]
> http://search.cpan.org/~jonasbn/Date-Holidays-0.08...
>
>
>


--
My free Ruby e-book:
http://www.humblelittlerubybook.com/book/

My blogs:
http://www.mrneighborly.com/
http://www.rubyinpractice.com/
4e2169cb8a701ab84f57d3eb52206a78?d=identicon&s=25 Kieran Tully (Guest)
on 2007-01-02 18:10
(Received via mailing list)
On 1/2/07, Daniel Berger <djberg96@gmail.com> wrote:

> Them: Why did the report fail for Jan. 1st?
> Me: National holiday. There was no data to grab.  Ignore the failure.
> Them: Oh, right.
[snip]
> Ideally, I'd like to be able to do something like:
>
> if Date.today.is_national_holiday?
>   exit # Don't run report on this day
> end

Nice, but won't this just change the problem to:

 Them: Why is there no report for Jan. 1st?


What currently happens when the report 'fails'? Could you generate an
empty report that says

 'No data available for today. Was it a holiday?'

That might solve your actual problem, without introducing a 'holidays'
module. Though if your reports often fail for other reasons, perhaps
you do need to detect holidays to distinguish them rom real error
conditions.
Aee77dba395ece0a04c688b05b07cd63?d=identicon&s=25 Daniel Berger (Guest)
on 2007-01-02 18:21
(Received via mailing list)
Kieran Tully wrote:
> > end
>
> Nice, but won't this just change the problem to:
>
>  Them: Why is there no report for Jan. 1st?
>
>
> What currently happens when the report 'fails'? Could you generate an
> empty report that says
>
>  'No data available for today. Was it a holiday?'

True, I may end up doing that in practice.

> That might solve your actual problem, without introducing a 'holidays'
> module. Though if your reports often fail for other reasons, perhaps
> you do need to detect holidays to distinguish them rom real error
> conditions.

Yes, sometimes they fail for other reasons, such as the network or
database flaking out briefly.  So, in practice I see myself doing
something like:

begin
    # main report body
rescue ReportException
   if Date.today.is_national_holiday?
      # note in log that it was a holiday, in case anyone asks.
   else
      raise
   end
end

It might be a little trickier than that in practice, but that's the
general idea.

Regards,

Dan
439c401f95ee2fac0be4c1727dd74dea?d=identicon&s=25 Bira (Guest)
on 2007-01-02 18:35
(Received via mailing list)
On 1/2/07, Daniel Berger <djberg96@gmail.com> wrote:
> Hi all,
>
> Well, it took seven years, but I've finally been annoyed enough by
> reports failing on national holidays to say something.  Report writers
> know the routine:

<...>

The best way I know of checking for holidays is somehow keeping a
record of which dates are holidays in a given year. It can be a
database table, or some sort of configuration files when that isn't
possible.

This record would have to be mantained manually, but it would be just
a simple case of editing the table/file every time you buy a new
calendar :).
E0c987f680cd640c14912ebfbf0f0f07?d=identicon&s=25 unknown (Guest)
on 2007-01-02 18:59
(Received via mailing list)
On 1/2/07, Daniel Berger <djberg96@gmail.com> wrote:
> if Date.today.is_national_holiday?
>    exit # Don't run report on this day
> end

You may be able to build something that checks againt an iCalendar
file of holidays.

* webcal://ical.mac.com/ical/US32Holidays.ics
* http://www.infinitenil.com/developers.html
* http://www.macdevcenter.com/pub/a/mac/2003/09/03/r...
Fc784eadb3b54531fdc3d2053db6f83f?d=identicon&s=25 Mat Schaffer (Guest)
on 2007-01-02 19:59
(Received via mailing list)
On Jan 2, 2007, at 11:56 AM, Jeremy McAnally wrote:

>        return true
> irb(main):264:0> christmas.is_national_holiday?
> => true
> irb(main):265:0> today = Date.today
> => #<Date: 4908205/2,0,2299161>
> irb(main):266:0> today.is_national_holiday?
> => false
>
> Again, it doesn't get Thanksgiving right or others that change like
> Easter.  If you want, I could hack it in; otherwise, this should get
> you on the right path. ;)

For those sort of holidays you could use the Chronic gem to parse a
textual date:

irb(main):010:0> Chronic.parse('4th thursday in november')
=> Thu Nov 22 11:00:00 -0500 2007

Still kind of a shame there isn't just a 'holidays' gem.

-Mat
6d3c187a8b3ef53b08e3e7e8572c4fea?d=identicon&s=25 Jeremy McAnally (Guest)
on 2007-01-02 20:05
(Received via mailing list)
I thought of Chronic (a fine library that I use often!); I'm toying
around with it right now and I think I have it figured out (without
using Chronic)...

I'll re-post the code later on...and maybe make a little gem for those
(i.e, four people) who need it. ;)

--Jeremy

On 1/2/07, Mat Schaffer <schapht@gmail.com> wrote:
> > '-1-1', this_year + '-7-4', this_year + '-11-28']
> >
> > Easter.  If you want, I could hack it in; otherwise, this should get
> -Mat
>
>


--
My free Ruby e-book:
http://www.humblelittlerubybook.com/book/

My blogs:
http://www.mrneighborly.com/
http://www.rubyinpractice.com/
526d60de6472502bb570a9df2842b33b?d=identicon&s=25 Nick Sieger (Guest)
on 2007-01-02 20:05
(Received via mailing list)
On 1/2/07, Mat Schaffer <schapht@gmail.com> wrote:
>
>
> For those sort of holidays you could use the Chronic gem to parse a
> textual date:
>
> irb(main):010:0> Chronic.parse('4th thursday in november')
> => Thu Nov 22 11:00:00 -0500 2007
>
> Still kind of a shame there isn't just a 'holidays' gem.


Emacs has a really robust holidays library that's not too lengthy,
perhaps a
good topic for a Ruby quiz or someone's spare time to just port it to
Ruby?

/Nick
Aee77dba395ece0a04c688b05b07cd63?d=identicon&s=25 Daniel Berger (Guest)
on 2007-01-02 20:05
(Received via mailing list)
Bira wrote:
> record of which dates are holidays in a given year. It can be a
> database table, or some sort of configuration files when that isn't
> possible.
>
> This record would have to be mantained manually, but it would be just
> a simple case of editing the table/file every time you buy a new
> calendar :).

For fixed holidays, sure - I think that's what Date::Calc does (i.e.
read an external file in, base on the selected country).  But for
floating holidays I would prefer a general algorithm.  Surely someone
can come up with a general algorithm for "3rd Thursday in November",
etc.  I'll bet the Rails folks already have something, but I haven't
looked.

Regards,

Dan
5ecfb4046c8d8333bdd13464b3d123c0?d=identicon&s=25 Kenosis (Guest)
on 2007-01-02 20:15
(Received via mailing list)
Daniel Berger wrote:
> > The best way I know of checking for holidays is somehow keeping a
> floating holidays I would prefer a general algorithm.  Surely someone
> can come up with a general algorithm for "3rd Thursday in November",
> etc.  I'll bet the Rails folks already have something, but I haven't
> looked.
>
> Regards,
>
> Dan
And whatever solution, it needs to be dynamically updatable to account
for suddenly announced national "holidays", like today happens to be -
doh!

Ken
6d3c187a8b3ef53b08e3e7e8572c4fea?d=identicon&s=25 Jeremy McAnally (Guest)
on 2007-01-02 20:37
(Received via mailing list)
Well, the way I'm working it out is like AR's dynamic finders.  It
will have a few groups of dates hardcoded (like national holidays and
such), but then you can give it new groups in the form hashes of
arrays of dates with named "work_holidays" or "surprise_offdays" and
then call the method like is_a_work_holiday? or is_a_surprise_offday?.
  I'm still working on it...I'll post when I've got it done.

--Jeremy

On 1/2/07, Kenosis <kenosis@gmail.com> wrote:
> > > <...>
> > For fixed holidays, sure - I think that's what Date::Calc does (i.e.
> for suddenly announced national "holidays", like today happens to be -
> doh!
>
> Ken
>
>
>


--
My free Ruby e-book:
http://www.humblelittlerubybook.com/book/

My blogs:
http://www.mrneighborly.com/
http://www.rubyinpractice.com/
Fc784eadb3b54531fdc3d2053db6f83f?d=identicon&s=25 Mat Schaffer (Guest)
on 2007-01-02 20:55
(Received via mailing list)
On Jan 2, 2007, at 2:37 PM, Jeremy McAnally wrote:

> Well, the way I'm working it out is like AR's dynamic finders.  It
> will have a few groups of dates hardcoded (like national holidays and
> such), but then you can give it new groups in the form hashes of
> arrays of dates with named "work_holidays" or "surprise_offdays" and
> then call the method like is_a_work_holiday? or is_a_surprise_offday?.
>  I'm still working on it...I'll post when I've got it done.
>
> --Jeremy

Sounds neat.  Just please bottom post when replying :)
-Mat
Aee77dba395ece0a04c688b05b07cd63?d=identicon&s=25 Daniel Berger (Guest)
on 2007-01-02 20:55
(Received via mailing list)
Jeremy McAnally wrote:
> Well, the way I'm working it out is like AR's dynamic finders.  It
> will have a few groups of dates hardcoded (like national holidays and
> such), but then you can give it new groups in the form hashes of
> arrays of dates with named "work_holidays" or "surprise_offdays" and
> then call the method like is_a_work_holiday? or is_a_surprise_offday?.
>   I'm still working on it...I'll post when I've got it done.

Actually, once I took a stab at it, I think it's fairly easy for the
national holidays IF I'm using Date#cweek correctly and reliably here:

require 'date'

class Date
   def thanksgiving?
      month == 11 && wday == 4 && cweek == 3
   end

   def christmas?
      month == 12 && day == 25
   end

   def new_years?
      month == 1 && day == 1
   end

   alias new_year new_years
   alias new_years_day new_years

   def memorial_day?
      if month == 5 && wday == 1 && cweek == 5
   end

   def independence_day?
      month == 7 && day == 4
   end

   alias fourth_of_july? independence_day?

   def national_holiday?
      new_years? && memorial_day? && independence_day? && thanksgiving?
&&
      christmas?
   end
end

How's that?

Regards,

Dan
Fc784eadb3b54531fdc3d2053db6f83f?d=identicon&s=25 Mat Schaffer (Guest)
on 2007-01-02 21:30
(Received via mailing list)
On Jan 2, 2007, at 2:55 PM, Daniel Berger wrote:
> national holidays IF I'm using Date#cweek correctly and reliably here:
>
> require 'date'
>
> class Date
>    def thanksgiving?
>       month == 11 && wday == 4 && cweek == 3
>    end

I think it would be cweek == 4, but I like the idea.  This particular
implementation doesn't seem very extensible.  Not sure what would be
the best way to define some sort of custom holidays file that could
be read by a gem...  Procs in a hash comes to mind.
-Mat
Aee77dba395ece0a04c688b05b07cd63?d=identicon&s=25 Daniel Berger (Guest)
on 2007-01-02 22:02
(Received via mailing list)
Mat Schaffer wrote:
> > Actually, once I took a stab at it, I think it's fairly easy for the
> implementation doesn't seem very extensible.  Not sure what would be
> the best way to define some sort of custom holidays file that could
> be read by a gem...  Procs in a hash comes to mind.

Yeah, I think you're right about the cweek.  You're also right about
this implementation not being very extensible.

On a side note, I was thinking of something like this for a theoretical
layout:

lib/
   date/
      holiday/
         us.rb
         uk.rb
         jp.rb
         ...

And then the end user would simply do "require 'date/holiday/us'" to
get the US holidays, etc.  I'm not certain, though.

Regards,

Dan

PS - The Date#national_holiday? method I posted is wrong.  There should
be "||" not "&&" between the method checks.
Ee04bc0ca6dcdad4a7e8a8e1d4efb5d0?d=identicon&s=25 Michael W. Ryder (Guest)
on 2007-01-02 22:26
(Received via mailing list)
Daniel Berger wrote:
>> record of which dates are holidays in a given year. It can be a
> can come up with a general algorithm for "3rd Thursday in November",
> etc.  I'll bet the Rails folks already have something, but I haven't
> looked.
>
> Regards,
>
> Dan
>
I have an old copy of Computer Language that includes the C source for
Julian dates.  One of the functions is the determination of Easter for
any given year.  If you are interested in just that algorithm or the
entire code let me know.  I assume that the determination of
Thanksgiving (for the US) would be trivial from there.
The only other real problem is that some states, Nevada for example,
change at least one of the holidays, where the state doesn't take
Columbus day off but takes off October 31st -- state admission day.
6d3c187a8b3ef53b08e3e7e8572c4fea?d=identicon&s=25 Jeremy McAnally (Guest)
on 2007-01-03 03:39
(Received via mailing list)
Okay, I got the code done.  I just need to create lists of holidays
now. I can do the U.S. holidays (if I need any help algorithm-wise,
I'll let you guys know...), but I have no clue about UK or anyone
else's holidays.  Anyone from another locality care to englighten me?

I called it "special_days" because Im hoping it can be used for
purposes other than just holidays (birthdays?  patch_days?  The
possibilities are approaching limitless!).

I'm working on getting a gem together right now...

--Jeremy

On 1/2/07, Daniel Berger <djberg96@gmail.com> wrote:
> Repeat again for Memorial Day, July 4th, Thanksgiving, and Christmas.
>
> - Dan
>
> [1] http://search.cpan.org/~stbey/Date-Calc-5.4/Calendar.pod
> [2]
> http://search.cpan.org/~stbey/Date-Calc-5.4/lib/Da...
> [3]
> http://search.cpan.org/~jonasbn/Date-Holidays-0.08...
>
>
>


--
My free Ruby e-book:
http://www.humblelittlerubybook.com/book/

My blogs:
http://www.mrneighborly.com/
http://www.rubyinpractice.com/
6329e9ce6b0c23f8bcf64a6c46a2bb81?d=identicon&s=25 matt (Guest)
on 2007-01-03 03:47
(Received via mailing list)
On Wed, 2007-01-03 at 11:38 +0900, Jeremy McAnally wrote:
> Okay, I got the code done.  I just need to create lists of holidays
> now. I can do the U.S. holidays (if I need any help algorithm-wise,
> I'll let you guys know...), but I have no clue about UK or anyone
> else's holidays.  Anyone from another locality care to englighten me?
>
> I called it "special_days" because Im hoping it can be used for
> purposes other than just holidays (birthdays?  patch_days?  The
> possibilities are approaching limitless!).

RubyConf Days?
918c6daad03c85e51ad1a11f57017947?d=identicon&s=25 Devin Mullins (twifkak)
on 2007-01-03 04:35
(Received via mailing list)
No! I insist that you top post!*

Oh, and for some actual content:
   http://en.wikipedia.org/wiki/Computus#Algorithms
Good luck with that.

Martin Fowler had an article/series of articles on building a DSL for
recurring dates. You might want to investigate.

Devin

Mat Schaffer wrote:
>> --Jeremy
>
>
> Sounds neat.  Just please bottom post when replying :)
> -Mat
>
>

* I'm joking, mostly. I use Thunderbird, ATM, so top posts are much more
convenient for me. I know, I know, majority rules... just... trim, if
you bottom post.

Devin
Ad7805c9fcc1f13efc6ed11251a6c4d2?d=identicon&s=25 Alex Young (regularfry)
on 2007-01-03 09:19
(Received via mailing list)
Jeremy McAnally wrote:
> Okay, I got the code done.  I just need to create lists of holidays
> now. I can do the U.S. holidays (if I need any help algorithm-wise,
> I'll let you guys know...), but I have no clue about UK or anyone
> else's holidays.  Anyone from another locality care to englighten me?
http://www.dti.gov.uk/employment/bank-public-holid...

This may also be of use:

http://en.wikipedia.org/wiki/Category:Public_holid...

Unfortunately, there doesn't seem to be much explanation of the logic
behind them.
6d3c187a8b3ef53b08e3e7e8572c4fea?d=identicon&s=25 Jeremy McAnally (Guest)
on 2007-01-06 19:30
(Received via mailing list)
I haven't forgotten!  I'm trying to get the architecture right (I was
modifying the Date class directly, but now I made a module), but I'm
having some testing problems (for some reason it's not including the
default Date class first before my extensions...even though I'm
requiring it.

I'm working on it!

--Jeremy

On 1/3/07, Alex Young <alex@blackkettle.org> wrote:
>
> Unfortunately, there doesn't seem to be much explanation of the logic
> behind them.
>
> --
> Alex
>
>


--
My free Ruby e-book:
http://www.humblelittlerubybook.com/book/

My blogs:
http://www.mrneighborly.com/
http://www.rubyinpractice.com/
Aee77dba395ece0a04c688b05b07cd63?d=identicon&s=25 Daniel Berger (Guest)
on 2007-01-06 19:31
(Received via mailing list)
Jeremy McAnally wrote:
> I haven't forgotten!  I'm trying to get the architecture right (I was
> modifying the Date class directly, but now I made a module), but I'm
> having some testing problems (for some reason it's not including the
> default Date class first before my extensions...even though I'm
> requiring it.
>
> I'm working on it!

I tinkered a bit with the notion of using a module instead of monkey
patching the Date class (or subclassing) but I wasn't satisfied with
the interface.  I'll be curious to see what you come up with.

Regards,

Dan
This topic is locked and can not be replied to.