holidays 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. data/LICENSE +21 -0
  2. data/README +76 -0
  3. data/REFERENCES +16 -0
  4. data/data/SYNTAX +111 -0
  5. data/data/au.yaml +106 -0
  6. data/data/build_defs.rb +152 -0
  7. data/data/ca.yaml +141 -0
  8. data/data/de.yaml +115 -0
  9. data/data/dk.yaml +117 -0
  10. data/data/es.yaml +161 -0
  11. data/data/fr.yaml +70 -0
  12. data/data/gb.yaml +106 -0
  13. data/data/ie.yaml +58 -0
  14. data/data/index.yaml +21 -0
  15. data/data/is.yaml +136 -0
  16. data/data/it.yaml +66 -0
  17. data/data/mx.yaml +106 -0
  18. data/data/nl.yaml +67 -0
  19. data/data/north_america_informal.yaml +49 -0
  20. data/data/pt.yaml +85 -0
  21. data/data/se.yaml +91 -0
  22. data/data/united_nations.yaml +188 -0
  23. data/data/us.yaml +81 -0
  24. data/data/za.yaml +78 -0
  25. data/lib/holidays.rb +404 -0
  26. data/lib/holidays/MANIFEST +23 -0
  27. data/lib/holidays/au.rb +41 -0
  28. data/lib/holidays/ca.rb +68 -0
  29. data/lib/holidays/de.rb +52 -0
  30. data/lib/holidays/dk.rb +47 -0
  31. data/lib/holidays/es.rb +52 -0
  32. data/lib/holidays/europe.rb +215 -0
  33. data/lib/holidays/fr.rb +36 -0
  34. data/lib/holidays/gb.rb +40 -0
  35. data/lib/holidays/ie.rb +32 -0
  36. data/lib/holidays/is.rb +61 -0
  37. data/lib/holidays/it.rb +35 -0
  38. data/lib/holidays/mx.rb +51 -0
  39. data/lib/holidays/nl.rb +36 -0
  40. data/lib/holidays/north_america.rb +107 -0
  41. data/lib/holidays/pt.rb +52 -0
  42. data/lib/holidays/scandinavia.rb +114 -0
  43. data/lib/holidays/se.rb +52 -0
  44. data/lib/holidays/united_nations.rb +24 -0
  45. data/lib/holidays/us.rb +48 -0
  46. data/lib/holidays/za.rb +35 -0
  47. data/test/defs/test_defs_au.rb +36 -0
  48. data/test/defs/test_defs_ca.rb +29 -0
  49. data/test/defs/test_defs_de.rb +46 -0
  50. data/test/defs/test_defs_dk.rb +30 -0
  51. data/test/defs/test_defs_es.rb +57 -0
  52. data/test/defs/test_defs_europe.rb +240 -0
  53. data/test/defs/test_defs_fr.rb +26 -0
  54. data/test/defs/test_defs_gb.rb +36 -0
  55. data/test/defs/test_defs_ie.rb +21 -0
  56. data/test/defs/test_defs_is.rb +33 -0
  57. data/test/defs/test_defs_it.rb +25 -0
  58. data/test/defs/test_defs_mx.rb +22 -0
  59. data/test/defs/test_defs_nl.rb +24 -0
  60. data/test/defs/test_defs_north_america.rb +54 -0
  61. data/test/defs/test_defs_pt.rb +32 -0
  62. data/test/defs/test_defs_scandinavia.rb +75 -0
  63. data/test/defs/test_defs_se.rb +32 -0
  64. data/test/defs/test_defs_us.rb +36 -0
  65. data/test/defs/test_defs_za.rb +25 -0
  66. metadata +118 -0
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ ==== Ruby Holidays Gem License
2
+
3
+ Copyright (c) 2007 Alex Dunae
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,76 @@
1
+ = Ruby Holidays Gem
2
+
3
+ A set of functions to deal with holidays in Ruby.
4
+
5
+ Extends Ruby's built-in Date class and supports custom holiday definition lists.
6
+
7
+ === Installation
8
+
9
+ To install the gem from RubyForge:
10
+
11
+ gem install holidays
12
+
13
+ Or, download the source <tt>.tgz</tt> file from http://rubyforge.org/holidays and
14
+ extract it somewhere in your include path.
15
+
16
+ === Examples
17
+
18
+ For more information, see the notes at the top of the Holidays module.
19
+
20
+ ==== Using the Holidays class
21
+ Get all holidays on April 25, 2008 in Australia.
22
+ date = Date.civil(2008,4,25)
23
+
24
+ Holidays.on(date, :au)
25
+ => [{:name => 'ANZAC Day',...}]
26
+
27
+ Get holidays that are observed on July 2, 2007 in British Columbia, Canada.
28
+ date = Date.civil(2007,7,2)
29
+
30
+ Holidays.on(date, :ca_bc, :observed)
31
+ => [{:name => 'Canada Day',...}]
32
+
33
+ Get all holidays in July, 2008 in Canada and the US.
34
+ from = Date.civil(2008,7,1)
35
+ to = Date.civil(2008,7,31)
36
+
37
+ Holidays.between(from, to, :ca, :us)
38
+ => [{:name => 'Canada Day',...}
39
+ {:name => 'Independence Day',...}]
40
+
41
+ Get informal holidays in February.
42
+ from = Date.civil(2008,2,1)
43
+ to = Date.civil(2008,2,15)
44
+
45
+ Holidays.between(from, to)
46
+ => [{:name => 'Valentine\'s Day',...}]
47
+
48
+
49
+ ==== Extending Ruby's Date class
50
+ Check which holidays occur in Iceland on January 1, 2008.
51
+ d = Date.civil(2008,7,1)
52
+
53
+ d.holidays(:is)
54
+ => [{:name => 'Nýársdagur'}...]
55
+
56
+ Lookup Canada Day in different regions.
57
+ d = Date.civil(2008,7,1)
58
+
59
+ d.holiday?(:ca) # Canada
60
+ => true
61
+
62
+ d.holiday?(:ca_bc) # British Columbia, Canada
63
+ => true
64
+
65
+ d.holiday?(:fr) # France
66
+ => false
67
+
68
+ === Credits and code
69
+
70
+ * Project page: http://code.dunae.ca/holidays
71
+ * Source: http://code.dunae.ca/svn/holidays
72
+ * Docs: http://code.dunae.ca/holidays/doc
73
+
74
+ By Alex Dunae (dunae.ca, e-mail 'code' at the same domain), 2007.
75
+
76
+ Made on Vancouver Island.
data/REFERENCES ADDED
@@ -0,0 +1,16 @@
1
+ === References
2
+
3
+ I am grateful to the following sources.
4
+
5
+ ==== Date calculations
6
+ * http://michaelthompson.org/technikos/holidays.php
7
+
8
+ ==== Easter calculations
9
+ * http://www.assa.org.au/edm.html
10
+ * http://www.smart.net/~mmontes/ec-cal.html
11
+
12
+ ==== World dates
13
+ * http://www.un.org/geninfo/faq/factsheets/FS18.HTM
14
+ * http://en.wikipedia.org/wiki/List_of_holidays_by_country
15
+
16
+
data/data/SYNTAX ADDED
@@ -0,0 +1,111 @@
1
+ == Holiday Gem Definition Syntax
2
+
3
+ All holidays are defined in YAML files in the <tt>data/</tt> directory. These definition files have three main parts: *months*, *methods* and *tests*. Before you start, you may want to look some of the existing files at http://code.dunae.ca/svn/holidays/trunk/data.
4
+
5
+ === Months
6
+
7
+ Holidays are grouped by month from 1 through 12. Each entry within a month can have several fields.
8
+
9
+ [<tt>name</tt>] The name of the holiday.
10
+ [<tt>regions</tt>] One or more region codes.
11
+
12
+ ===== Dates defined by a fixed date (e.g. January 1st)
13
+
14
+ [<tt>wday</tt>] Integer representing day of the month (1 through 31).
15
+
16
+ For example, the following holiday is on the first of January and available in the <tt>ca</tt>, <tt>us</tt> and <tt>au</tt> regions.
17
+
18
+ 1:
19
+ - name: New Year's Day
20
+ regions: [ca, us, au]
21
+ mday: 1
22
+
23
+ ===== Dates defined by a week number (e.g. first Monday of a month)
24
+
25
+ [<tt>wday</tt>] Integer representing day of the week (0 = Sunday through 6 = Saturday).
26
+ [<tt>week</tt>] Integer representing week number (1 = first week, 3 = third week, -1 = last week),
27
+
28
+
29
+ For example, the following holiday is on the first Monday of September and available in the <tt>ca</tt> region.
30
+
31
+ 9:
32
+ - name: Labour Day
33
+ regions: [ca]
34
+ week: 1
35
+ wday: 1
36
+
37
+ === Calculating dates with methods
38
+
39
+ In addition to defining holidays by day or week, you can create custom methods to calculate a date.
40
+
41
+ For example, Canada celebrates Victoria Day, which falls on the Monday on or before May 24. So, under the <tt>methods</tt> section we could create a custom method that returns a Date object.
42
+
43
+ methods:
44
+ ca_victoria_day: |
45
+ def self.ca_victoria_day(year)
46
+ date = Date.civil(year,5,24)
47
+ if date.wday > 1
48
+ date -= (date.wday - 1)
49
+ elsif date.wday == 0
50
+ date -= 6
51
+ end
52
+ date
53
+ end
54
+
55
+ This would be represented in the <tt>months</tt> section as:
56
+
57
+ 5:
58
+ - name: Victoria Day
59
+ regions: [ca]
60
+ function: ca_victoria_day(year)
61
+
62
+ If a holiday can occur in different months (e.g. Easter) it can go in the '0' month.
63
+
64
+ 0:
65
+ - name: Easter Monday
66
+ regions: [ca]
67
+ function: easter(year)+1
68
+
69
+ Calculated-date functions take the year (integer) as a parameter and must return either a Date object or an integer representing the day of the month.
70
+
71
+
72
+ === Calculating observed dates
73
+
74
+ Several built-in methods are available for holidays that are observed on varying dates. For example, for a holiday that is observed on Monday if it falls on a weekend you could write:
75
+
76
+ 7:
77
+ - name: Canada Day
78
+ regions: [ca]
79
+ mday: 1
80
+ observed: to_monday_if_weekend(date)
81
+
82
+ Methods included in the Holidays module are:
83
+
84
+ * Holidays#to_monday_if_sunday
85
+ * Holidays#to_monday_if_weekend
86
+ * Holidays#to_weekday_if_boxing_weekend
87
+ * Holidays#to_weekday_if_weekend
88
+
89
+ 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.
90
+
91
+
92
+
93
+ === Tests
94
+
95
+ All definition files should have tests included. In the YAML file, tests are just a block of Ruby code.
96
+
97
+ tests: |
98
+ {Date.civil(2008,1,1) => 'New Year\'s Day',
99
+ Date.civil(2008,3,21) => 'Good Friday',
100
+ Date.civil(2008,3,24) => 'Easter Monday',
101
+ Date.civil(2008,9,1) => 'Labour Day',
102
+ Date.civil(2008,12,25) => 'Christmas Day',
103
+ Date.civil(2008,12,26) => 'Boxing Day'}.each do |date, name|
104
+ assert_equal name, Holidays.on(date, :ca, :informal)[0][:name]
105
+ end
106
+
107
+ # Victoria Day
108
+ [Date.civil(2004,5,24), Date.civil(2005,5,23), Date.civil(2006,5,22),
109
+ Date.civil(2007,5,21), Date.civil(2008,5,19)].each do |date|
110
+ assert_equal 'Victoria Day', Holidays.on(date, :ca)[0][:name]
111
+ end
data/data/au.yaml ADDED
@@ -0,0 +1,106 @@
1
+ # Australian holiday definitions for the Ruby Holiday gem.
2
+ # Updated: 2008-11-29.
3
+ # Sources:
4
+ # - http://en.wikipedia.org/wiki/Australian_public_holidays
5
+ # - http://www.docep.wa.gov.au/lr/LabourRelations/Content/Wages%20and%20Conditions/Public%20Holidays/Public_Holidays.html
6
+ # - http://www.wst.tas.gov.au/employment_info/public_holidays
7
+ # TODO: missing some regional holidays
8
+ ---
9
+ months:
10
+ 0:
11
+ - name: Good Friday
12
+ regions: [au]
13
+ function: easter(year)-2
14
+ - name: Easter Saturday
15
+ regions: [au]
16
+ function: easter(year)-1
17
+ - name: Easter Monday
18
+ regions: [au]
19
+ function: easter(year)+1
20
+ - name: Easter Monday
21
+ regions: [au_tas]
22
+ function: easter(year)+2
23
+ 1:
24
+ - name: New Year's Day
25
+ regions: [au]
26
+ mday: 1
27
+ - name: Australia Day
28
+ regions: [au]
29
+ mday: 26
30
+ 3:
31
+ - name: Labour Day
32
+ regions: [au_wa]
33
+ week: 1
34
+ wday: 1
35
+ - name: Eight Hours Day
36
+ regions: [au_tas]
37
+ week: 2
38
+ wday: 1
39
+ - name: Labour Day
40
+ regions: [au_vic]
41
+ week: 2
42
+ wday: 1
43
+ 4:
44
+ - name: ANZAC Day
45
+ regions: [au]
46
+ mday: 25
47
+ 5:
48
+ - name: Labour Day
49
+ regions: [au_qld]
50
+ week: 1
51
+ wday: 1
52
+ - name: May Day
53
+ regions: [au_nt]
54
+ week: 1
55
+ wday: 1
56
+ 6:
57
+ - name: Foundation Day
58
+ regions: [au_wa]
59
+ week: 1
60
+ wday: 1
61
+ - name: Queen's Birthday
62
+ regions: [au_act, au_nsw, au_sa, au_tas, au_nt, au_qld, au_vic]
63
+ week: 2
64
+ wday: 1
65
+ - name: Queensland Day
66
+ regions: [au_qld]
67
+ mday: 6
68
+ type: informal
69
+ 10:
70
+ - name: Labour Day
71
+ regions: [au_act, au_nsw, au_sa]
72
+ week: 1
73
+ wday: 1
74
+ 12:
75
+ - name: Christmas Day
76
+ regions: [au]
77
+ mday: 25
78
+ - name: Boxing Day
79
+ regions: [au]
80
+ mday: 26
81
+ tests: |
82
+ {Date.civil(2007,1,1) => 'New Year\'s Day',
83
+ Date.civil(2007,1,26) => 'Australia Day',
84
+ Date.civil(2007,4,6) => 'Good Friday',
85
+ Date.civil(2007,4,9) => 'Easter Monday',
86
+ Date.civil(2007,4,25) => 'ANZAC Day',
87
+ Date.civil(2007,12,25) => 'Christmas Day',
88
+ Date.civil(2007,12,26) => 'Boxing Day'}.each do |date, name|
89
+ assert_equal name, Holidays.on(date, :au, :informal)[0][:name]
90
+ end
91
+
92
+ [:au_sa, :au_act, :au_nsw, :au_].each do |r|
93
+ assert_equal 'Labour Day', Date.civil(2007,10,1).holidays(r)[0][:name]
94
+ end
95
+
96
+ [:au_sa, :au_act, :au_nsw, :au_vic, :au_tas, :au_qld, :au_nt, :au_].each do |r|
97
+ assert_equal 'Queen\'s Birthday', Date.civil(2007,6,11).holidays(r)[0][:name]
98
+ end
99
+
100
+ assert_equal 'Labour Day', Date.civil(2007,3,5).holidays(:au_wa)[0][:name]
101
+ assert_equal 'Labour Day', Date.civil(2007,3,12).holidays(:au_vic)[0][:name]
102
+ assert_equal 'Labour Day', Date.civil(2007,5,7).holidays(:au_qld)[0][:name]
103
+
104
+ assert_equal 'May Day', Date.civil(2007,5,7).holidays(:au_nt)[0][:name]
105
+
106
+ assert_equal 'Eight Hours Day', Date.civil(2007,3,12).holidays(:au_tas)[0][:name]
@@ -0,0 +1,152 @@
1
+ require 'yaml'
2
+
3
+ # Functions are stored in generated files as both Procs (:function) and
4
+ # Strings (:function_id). The String version makes comparisons of Procs much
5
+ # easier.
6
+ #
7
+ # TODO:
8
+ # - better comparison of existing rules
9
+ def parse_holiday_defs(module_name, files)
10
+ regions = []
11
+ rules_by_month = {}
12
+ custom_methods = {}
13
+ test_strs = []
14
+
15
+ files.each do |file|
16
+ def_file = YAML.load_file(file)
17
+ puts " Loading #{file}"
18
+ if def_file['months']
19
+ puts " - importing dates..."
20
+ def_file['months'].each do |month, definitions|
21
+ rules_by_month[month] = [] unless rules_by_month[month]
22
+ definitions.each do |definition|
23
+ rule = {}
24
+ definition.each do |key, val|
25
+ rule[key] = val
26
+ end
27
+
28
+ rule['regions'] = rule['regions'].collect { |r| r.to_sym }
29
+
30
+ regions << rule['regions']
31
+
32
+ exists = false
33
+ rules_by_month[month].each do |ex|
34
+ if ex['name'] == rule['name'] and ex['wday'] == rule['wday'] and ex['mday'] == rule['mday'] and ex['week'] == rule['week'] and ex['type'] == rule['type'] and ex['function'] == rule['function'] and ex['observed'] == rule['observed']
35
+ ex['regions'] << rule['regions'].flatten
36
+ exists = true
37
+ end
38
+ end
39
+ unless exists
40
+ rules_by_month[month] << rule
41
+ end
42
+
43
+ end # /defs.each
44
+ end
45
+ end
46
+
47
+ if def_file['methods']
48
+ puts " - importing methods..."
49
+ def_file['methods'].each do |name, code|
50
+ custom_methods[name] = code
51
+ end # /methods.each
52
+ end
53
+
54
+ if def_file['tests']
55
+ puts " - importing testings..."
56
+ test_strs << def_file['tests']
57
+ end
58
+ end
59
+
60
+ # Build the definitions
61
+ month_strs = []
62
+ rules_by_month.each do |month, rules|
63
+ month_str = " #{month.to_s} => ["
64
+ rule_strings = []
65
+ rules.each do |rule|
66
+ str = '{'
67
+ if rule['mday']
68
+ str << ":mday => #{rule['mday']}, "
69
+ elsif rule['function']
70
+ str << ":function => lambda { |year| Holidays.#{rule['function']} }, "
71
+ str << ":function_id => \"#{rule['function'].to_s}\", "
72
+ else
73
+ str << ":wday => #{rule['wday']}, :week => #{rule['week']}, "
74
+ end
75
+
76
+ if rule['observed']
77
+ str << ":observed => lambda { |date| Holidays.#{rule['observed']}(date) }, "
78
+ str << ":observed_id => \"#{rule['observed'].to_s}\", "
79
+ end
80
+
81
+ if rule['type']
82
+ str << ":type => :#{rule['type']}, "
83
+ end
84
+
85
+ # shouldn't allow the same region twice
86
+ str << ":name => \"#{rule['name']}\", :regions => [:" + rule['regions'].uniq.join(', :') + "]}"
87
+ rule_strings << str
88
+ end
89
+ month_str << rule_strings.join(",\n ") + "]"
90
+ month_strs << month_str
91
+ end
92
+
93
+ month_strs.join(",\n")
94
+
95
+
96
+ # Build the methods
97
+ method_str = ''
98
+ custom_methods.each do |key, code|
99
+ method_str << code + "\n\n"
100
+ end
101
+
102
+
103
+ # Build the module file
104
+ module_src =<<-EOM
105
+ module Holidays
106
+ # This file is generated by the Ruby Holiday gem.
107
+ #
108
+ # Definitions loaded: #{files.join(', ')}
109
+ #
110
+ # To use the definitions in this file, load them right after you load the
111
+ # Holiday gem:
112
+ #
113
+ # require 'holidays'
114
+ # require 'holidays/#{module_name.downcase}'
115
+ #
116
+ # More definitions are available at http://code.dunae.ca/holidays.
117
+ module #{module_name} # :nodoc:
118
+ DEFINED_REGIONS = [:#{regions.flatten.uniq.join(', :')}]
119
+
120
+ HOLIDAYS_BY_MONTH = {
121
+ #{month_strs.join(",\n")}
122
+ }
123
+ end
124
+
125
+ #{method_str}
126
+ end
127
+
128
+ Holidays.merge_defs(Holidays::#{module_name}::DEFINED_REGIONS, Holidays::#{module_name}::HOLIDAYS_BY_MONTH)
129
+ EOM
130
+
131
+
132
+ # Build the test file
133
+ unless test_strs.empty?
134
+ test_src =<<-EndOfTests
135
+ require File.dirname(__FILE__) + '/../test_helper'
136
+ require 'holidays/#{module_name.downcase}'
137
+
138
+ # This file is generated by the Ruby Holiday gem.
139
+ #
140
+ # Definitions loaded: #{files.join(', ')}
141
+ class #{module_name.capitalize}DefinitionTests < Test::Unit::TestCase # :nodoc:
142
+
143
+ def test_#{module_name.downcase}
144
+ #{test_strs.join("\n\n")}
145
+ end
146
+ end
147
+ EndOfTests
148
+ end
149
+
150
+ return module_src, test_src || ''
151
+
152
+ end