diff --git a/README b/README index 6628ca6..8b95a19 100644 --- a/README +++ b/README @@ -1,44 +1,70 @@ = Ruby Holidays Gem -A set of classes to deal with holidays in Ruby. +A set of functions to deal with holidays in Ruby. Extends Ruby's built-in Date class and supports custom holiday definition lists. -=== Examples - -==== Using the Holidays class - # Get all holidays on April 25, 2008 in Australia - date = Date.civil(2008,4,25) - Holidays.by_day(date, :au) - => [{:name => 'ANZAC Day',...}] - - - # Get all holidays in July, 2008 in Canada and the US - from = Date.civil(2008,7,1) - to = Date.civil(2008,7,31) - Holidays.between(from, to, :ca,:us) - => [{:name => 'Canada Day',...} - {:name => 'Independence Day',...}] - - -==== Extending Ruby's Date class - # Lookup Canada Day in the :ca region - Date.civil(2008,7,1).holiday?(:ca) - => true - - # Lookup Canada Day in the :fr region - Date.civil(2008,7,1).holiday?(:fr) - => false - === Installation To install the gem from RubyForge: gem install holidays -Or, download the source .tgz file from http://rubyforge.org/holidays/ and +Or, download the source .tgz file from http://rubyforge.org/holidays and extract it somewhere in your include path. +=== Examples + +For more information, see the notes at the top of the Holidays module. + +==== Using the Holidays class +Get all holidays on April 25, 2008 in Australia. + date = Date.civil(2008,4,25) + + Holidays.by_day(date, :au) + => [{:name => 'ANZAC Day',...}] + +Get holidays that are observed on July 2, 2007 in British Columbia, Canada. + date = Date.civil(2007,7,2) + + Holidays.by_day(date, :ca_bc, :observed) + => [{:name => 'Canada Day',...}] + +Get all holidays in July, 2008 in Canada and the US. + from = Date.civil(2008,7,1) + to = Date.civil(2008,7,31) + + Holidays.between(from, to, :ca, :us) + => [{:name => 'Canada Day',...} + {:name => 'Independence Day',...}] + +Get informal holidays in February. + from = Date.civil(2008,2,1) + to = Date.civil(2008,2,15) + + Holidays.between(from, to) + => [{:name => 'Valentine\'s Day',...}] + + +==== Extending Ruby's Date class +Check which holidays occur in Iceland on January 1, 2008. + d = Date.civil(2008,7,1) + + d.holidays(:is) + => [{:name => 'Nýársdagur'}...] + +Lookup Canada Day in different regions. + d = Date.civil(2008,7,1) + + d.holiday?(:ca) # Canada + => true + + d.holiday?(:ca_bc) # British Columbia, Canada + => true + + d.holiday?(:fr) # France + => false + === Credits and code * Project page: http://code.dunae.ca/holidays diff --git a/data/SYNTAX b/data/SYNTAX index fe138d1..8d37e14 100644 --- a/data/SYNTAX +++ b/data/SYNTAX @@ -79,6 +79,13 @@ Several built-in methods are available for holidays that are observed on varying mday: 1 observed: to_monday_if_weekend(date) +Methods included in the Holidays module are: + +* Holidays#to_monday_if_sunday +* Holidays#to_monday_if_weekend +* Holidays#to_weekday_if_boxing_weekend +* Holidays#to_weekday_if_weekend + Observed-date functions take a Date object as a parameter and must return either a Date object or an integer representing the day of the month. diff --git a/data/lv.yaml b/data/lv.yaml deleted file mode 100644 index 548b7a4..0000000 --- a/data/lv.yaml +++ /dev/null @@ -1,49 +0,0 @@ -# Latvian holiday definitions for the Ruby Holiday gem. -# -# Updated: 2008-11-23. -# Sources: -# - http://en.wikipedia.org/wiki/Holidays_in_Latvia ---- -months: - 0: - - name: Liela Piektdiena - regions: [lv] - function: easter(year)-2 - - name: Lieldienas - regions: [lv] - function: easter(year) - - name: 2. Lieldienas - regions: [lv] - function: easter(year)+1 - 1: - - name: Jaunais Gads - regions: [lv] - mday: 1 - 5: - - name: Darba svetki - regions: [lv] - mday: 1 - - name: Neatkaribas deklaracijas pasludinaÅ¡anas diena - regions: [lv] - mday: 4 - 6: - - name: Ligo Diena - regions: [lv] - mday: 23 - - name: Jani - regions: [lv] - mday: 24 - 11: - - name: Latvijas Republikas proklameÅ¡anas diena - regions: [lv] - mday: 18 - 12: - - name: Ziemassvetki - regions: [lv] - mday: 25 - - name: 2. Ziemassvetki - regions: [lv] - mday: 25 - - name: Vecgada vakars - regions: [lv] - mday: 31 \ No newline at end of file diff --git a/lib/holidays.rb b/lib/holidays.rb index e5ceca0..2475d20 100644 --- a/lib/holidays.rb +++ b/lib/holidays.rb @@ -70,9 +70,17 @@ module Holidays # Returns an array of hashes or nil. # # Each holiday is returned as a hash with the following fields: - # [:date] Ruby Date object. - # [:name] String. - # [:options] One or more region symbols, :informal and/or :observed. + # [start_date] Ruby Date object. + # [end_date] Ruby Date object. + # [options] One or more region symbols, :informal and/or :observed. + # + # ==== Example + # from = Date.civil(2008,7,1) + # to = Date.civil(2008,7,31) + # + # Holidays.between(from, to, :ca, :us) + # => [{:name => 'Canada Day', :regions => [:ca]...} + # {:name => 'Independence Day'', :regions => [:us], ...}] def self.between(start_date, end_date, *options) regions, observed, informal = parse_options(options) holidays = [] @@ -105,7 +113,6 @@ module Holidays mday = h[:mday] || Date.calculate_mday(year, month, h[:week], h[:wday]) end - begin date = Date.new(year, month, mday) rescue; next; end @@ -142,6 +149,7 @@ module Holidays exists = false @@holidays_by_month[month].each do |ex| + # TODO: gross. if ex[:name] == holiday_def[:name] and ex[:wday] == holiday_def[:wday] and ex[:mday] == holiday_def[:mday] and ex[:week] == holiday_def[:week] and ex[:function_id] == holiday_def[:function_id] and ex[:type] == holiday_def[:type] and ex[:observed_id] == holiday_def[:observed_id] # append regions ex[:regions] << holiday_def[:regions] @@ -153,26 +161,14 @@ module Holidays end end - unless exists - @@holidays_by_month[month] << holiday_def - if holiday_def[:function] - #puts "New func #{holiday_def[:function].methods.join(', ')}" -# puts "New func #{holiday_def[:function] }" - end - end + @@holidays_by_month[month] << holiday_def unless exists end end end # Get the date of Easter Sunday in a given year. From Easter Sunday, it is # possible to calculate many traditional holidays in Western countries. - # - # +year+ must be a valid Gregorian year. - # # Returns a Date object. - #-- - # from http://snippets.dzone.com/posts/show/765 - # TODO: check year to ensure Gregorian def self.easter(year) y = year a = y % 19 @@ -223,7 +219,6 @@ module Holidays date end - private # Returns [(arr)regions, (bool)observed, (bool)informal] def self.parse_options(*options) # :nodoc: @@ -322,8 +317,8 @@ end # Date.civil(2008,7,1).holiday?(:fr) # => false # -# Lookup holidays in North America in January 1. -# Date.civil(2008,1,1).holidays([:ca, :mx, :us]) +# Lookup holidays on North America in January 1. +# Date.civil(2008,1,1).holidays(:ca, :mx, :us, :informal, :observed) # => [{:name => 'New Year\'s Day'...}] class Date include Holidays @@ -333,8 +328,8 @@ class Date # Returns an array of hashes or nil. See Holidays#between for options # and the output format. # - # Date.civil('2008-01-01').holidays(:ca) - # => [{:name => 'Canada Day',...}] + # Date.civil('2008-01-01').holidays(:ca_) + # => [{:name => 'New Year\'s Day',...}] # # Also available via Holidays#on. def holidays(*options) @@ -343,8 +338,7 @@ class Date # Check if the current date is a holiday. # - # Returns an array of hashes or nil. See Holidays#between for options - # and the output format. + # Returns true or false. # # Date.civil('2008-01-01').holiday?(:ca) # => true @@ -368,15 +362,15 @@ class Date # # ===== Examples # First Monday of January, 2008: - # calculate_mday(2008, 1, :first, :monday) + # Date.calculate_mday(2008, 1, :first, :monday) # => 7 # # Third Thursday of December, 2008: - # calculate_mday(2008, 12, :third, 4) + # Date.calculate_mday(2008, 12, :third, 4) # => 18 # # Last Monday of January, 2008: - # calculate_mday(2008, 1, :last, 1) + # Date.calculate_mday(2008, 1, :last, 1) # => 28 #-- # see http://www.irt.org/articles/js050/index.htm diff --git a/lib/holidays/MANIFEST b/lib/holidays/MANIFEST index f1f503e..5d1e8a0 100644 --- a/lib/holidays/MANIFEST +++ b/lib/holidays/MANIFEST @@ -13,11 +13,12 @@ installation: * holidays/ie * holidays/is * holidays/it -* holidays/lv * holidays/mx * holidays/nl * holidays/north_america +* holidays/pt * holidays/scandinavia +* holidays/se * holidays/united_nations * holidays/us * holidays/za diff --git a/test/benchmark.rb b/test/benchmark.rb deleted file mode 100644 index 163ed00..0000000 --- a/test/benchmark.rb +++ /dev/null @@ -1,45 +0,0 @@ -require File.dirname(__FILE__) + '/test_helper' -require 'date' -require 'holidays' -require 'holidays/ca' -require 'benchmark' - - - -n = 10000 -dt = Date.civil(2035,3,23) -Benchmark.bm do |x| - - x.report('0001') do - 1.times do - r = Holidays.on(dt, :any) - end - end - - - x.report('0010') do - 10.times do - r = Holidays.on(dt, :any) - end - end - - x.report('0100') do - 100.times do - r = Holidays.on(dt, :any) - end - end - - x.report('1000') do - 1000.times do - r = Holidays.on(dt, :any) - end - end - - - x.report('5000') do - 5000.times do - r = Holidays.on(dt, :any) - end - end - -end \ No newline at end of file diff --git a/test/fixtures/ca.rb b/test/fixtures/ca.rb deleted file mode 100644 index e83fc8e..0000000 --- a/test/fixtures/ca.rb +++ /dev/null @@ -1,82 +0,0 @@ -# This file is generated by the Ruby Holiday gem. -# -# To use the definitions in the file, load them right after you load the -# Holiday gem: -# -# require 'holidays' -# require 'path/to/testmodule' -# -# More definitions are available at http://code.dunae.ca/holidays. -# -# Definitions loaded: data/ca.yaml -module Holidays - module TestModule - DEFINED_REGIONS = [:ca] - - HOLIDAYS_BY_MONTH = { - 5 => [{:function => lambda { |year| ca_victoria_day(year) }, :name => "Victoria Day", :regions => [:ca]}, - {:function => lambda { |year| ca_victoria_day(year) }, :name => "National Patriotes Day", :regions => [:ca_qc]}], - 0 => [{:function => lambda { |year| easter(year)-2 }, :name => "Good Friday", :regions => [:ca]}, - {:function => lambda { |year| easter(year)+1 }, :name => "Easter Monday", :regions => [:ca_qc]}], - 11 => [{:mday => 11, :name => "Rememberance Day", :regions => [:ca]}], - 6 => [{:mday => 24, :name => "Discovery Day", :regions => [:ca_nf]}, - {:mday => 24, :name => "Fête Nationale", :regions => [:ca_qc]}, - {:mday => 21, :name => "National Aboriginal Day", :regions => [:ca_nt]}], - 1 => [{:mday => 1, :name => "New Year's Day", :regions => [:ca]}, - {:mday => 2, :name => "New Year's", :regions => [:ca_qc]}], - 12 => [{:mday => 25, :name => "Christmas Day", :regions => [:ca]}, - {:mday => 26, :name => "Boxing Day", :regions => [:ca]}], - 7 => [{:mday => 1, :name => "Canada Day", :regions => [:ca]}, - {:mday => 12, :name => "Orangemen's Day", :regions => [:ca]}, - {:mday => 9, :name => "Nunavut Day", :regions => [:ca_nu]}], - 2 => [{:wday => 1, :week => 3, :name => "Family Day", :regions => [:ca_ab, :ca_on, :ca_sk]}, - {:wday => 1, :week => 3, :name => "Louis Riel Day", :regions => [:ca_mb]}], - 8 => [{:wday => 1, :week => 1, :name => "BC Day", :regions => [:ca_bc]}, - {:wday => 1, :week => 1, :name => "Saskatchewan Day", :regions => [:ca_sk]}, - {:wday => 1, :week => 1, :name => "Heritage Day", :regions => [:ca_ab]}, - {:wday => 1, :week => 1, :name => "Natal Day", :regions => [:ca_ns]}, - {:wday => 1, :week => 1, :name => "Civic Holiday", :regions => [:ca_on]}, - {:wday => 1, :week => 3, :name => "Discovery Day", :regions => [:ca_yk]}], - 3 => [{:mday => 23, :name => "St. George's Day", :regions => [:ca_nf]}], - 9 => [{:wday => 1, :week => 1, :name => "Labour Day", :regions => [:ca]}], - 10 => [{:wday => 1, :week => 2, :name => "Thanksgiving", :regions => [:ca]}] - } - -def self.easter(year) - Date.civil(2008,1,1) -end - - -# Monday on or before May 24 -def self.ca_victoria_day(year) - date = Date.civil(year,5,24) - if date.wday > 1 - date -= (date.wday - 1) - elsif date.wday == 0 - date -= 6 - end - date -end - - - end -end - -Holidays.class_eval do - existing_regions = [] - if const_defined?(:DEFINED_REGIONS) - existing_regions = const_get(:DEFINED_REGIONS) - remove_const(:DEFINED_REGIONS) - end - const_set(:DEFINED_REGIONS, existing_regions | Holidays::TestModule::DEFINED_REGIONS) - - existing_defs = {} - if const_defined?(:HOLIDAYS_BY_MONTH) - existing_defs = const_get(:HOLIDAYS_BY_MONTH) - remove_const(:HOLIDAYS_BY_MONTH) - end - #const_set(:HOLIDAYS_BY_MONTH, existing_defs.merge(Holidays::TestModule::HOLIDAYS_BY_MONTH)) - const_set(:HOLIDAYS_BY_MONTH, Holidays::TestModule::HOLIDAYS_BY_MONTH) - - include Holidays::TestModule -end