wombleton-holidays 0.9.6

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 (90) hide show
  1. data/.gitignore +3 -0
  2. data/CHANGELOG +22 -0
  3. data/LICENSE +21 -0
  4. data/README.rdoc +77 -0
  5. data/REFERENCES +16 -0
  6. data/VERSION +1 -0
  7. data/data/SYNTAX +111 -0
  8. data/data/au.yaml +111 -0
  9. data/data/build_defs.rb +152 -0
  10. data/data/ca.yaml +141 -0
  11. data/data/cz.yaml +68 -0
  12. data/data/de.yaml +111 -0
  13. data/data/dk.yaml +117 -0
  14. data/data/es.yaml +161 -0
  15. data/data/fr.yaml +70 -0
  16. data/data/gb.yaml +106 -0
  17. data/data/ie.yaml +58 -0
  18. data/data/index.yaml +26 -0
  19. data/data/is.yaml +136 -0
  20. data/data/it.yaml +66 -0
  21. data/data/mx.yaml +106 -0
  22. data/data/nl.yaml +67 -0
  23. data/data/no.yaml +82 -0
  24. data/data/north_america_informal.yaml +49 -0
  25. data/data/nyse.yaml +63 -0
  26. data/data/nz.yaml +141 -0
  27. data/data/pt.yaml +85 -0
  28. data/data/se.yaml +91 -0
  29. data/data/united_nations.yaml +188 -0
  30. data/data/ups.yaml +56 -0
  31. data/data/us.yaml +81 -0
  32. data/data/za.yaml +78 -0
  33. data/holidays.gemspec +16 -0
  34. data/lib/holidays/MANIFEST +28 -0
  35. data/lib/holidays/au.rb +43 -0
  36. data/lib/holidays/ca.rb +69 -0
  37. data/lib/holidays/cz.rb +36 -0
  38. data/lib/holidays/de.rb +51 -0
  39. data/lib/holidays/dk.rb +48 -0
  40. data/lib/holidays/es.rb +53 -0
  41. data/lib/holidays/europe.rb +236 -0
  42. data/lib/holidays/fr.rb +37 -0
  43. data/lib/holidays/gb.rb +41 -0
  44. data/lib/holidays/ie.rb +33 -0
  45. data/lib/holidays/is.rb +62 -0
  46. data/lib/holidays/it.rb +36 -0
  47. data/lib/holidays/mx.rb +52 -0
  48. data/lib/holidays/nl.rb +37 -0
  49. data/lib/holidays/no.rb +40 -0
  50. data/lib/holidays/north_america.rb +108 -0
  51. data/lib/holidays/nyse.rb +33 -0
  52. data/lib/holidays/nz.rb +69 -0
  53. data/lib/holidays/pt.rb +38 -0
  54. data/lib/holidays/scandinavia.rb +115 -0
  55. data/lib/holidays/se.rb +53 -0
  56. data/lib/holidays/united_nations.rb +25 -0
  57. data/lib/holidays/ups.rb +32 -0
  58. data/lib/holidays/us.rb +49 -0
  59. data/lib/holidays/za.rb +36 -0
  60. data/lib/holidays.rb +408 -0
  61. data/rakefile.rb +103 -0
  62. data/test/defs/test_defs_au.rb +35 -0
  63. data/test/defs/test_defs_ca.rb +28 -0
  64. data/test/defs/test_defs_cz.rb +25 -0
  65. data/test/defs/test_defs_de.rb +48 -0
  66. data/test/defs/test_defs_dk.rb +29 -0
  67. data/test/defs/test_defs_es.rb +56 -0
  68. data/test/defs/test_defs_europe.rb +277 -0
  69. data/test/defs/test_defs_fr.rb +25 -0
  70. data/test/defs/test_defs_gb.rb +35 -0
  71. data/test/defs/test_defs_ie.rb +20 -0
  72. data/test/defs/test_defs_is.rb +32 -0
  73. data/test/defs/test_defs_it.rb +24 -0
  74. data/test/defs/test_defs_mx.rb +21 -0
  75. data/test/defs/test_defs_nl.rb +23 -0
  76. data/test/defs/test_defs_no.rb +28 -0
  77. data/test/defs/test_defs_north_america.rb +53 -0
  78. data/test/defs/test_defs_nyse.rb +21 -0
  79. data/test/defs/test_defs_nz.rb +21 -0
  80. data/test/defs/test_defs_pt.rb +31 -0
  81. data/test/defs/test_defs_scandinavia.rb +75 -0
  82. data/test/defs/test_defs_se.rb +32 -0
  83. data/test/defs/test_defs_ups.rb +20 -0
  84. data/test/defs/test_defs_us.rb +22 -0
  85. data/test/defs/test_defs_za.rb +24 -0
  86. data/test/test_date.rb +101 -0
  87. data/test/test_helper.rb +11 -0
  88. data/test/test_holidays.rb +117 -0
  89. data/test/test_multiple_regions.rb +20 -0
  90. metadata +172 -0
data/lib/holidays.rb ADDED
@@ -0,0 +1,408 @@
1
+ # coding: utf-8
2
+ $:.unshift File.dirname(__FILE__)
3
+
4
+ require 'digest/md5'
5
+ require 'date'
6
+
7
+ # == Region options
8
+ # Holidays can be defined as belonging to one or more regions and sub regions.
9
+ # The Holidays#on, Holidays#between, Date#holidays and Date#holiday? methods
10
+ # each allow you to specify a specific region.
11
+ #
12
+ # There are several different ways that you can specify a region:
13
+ #
14
+ # [<tt>:region</tt>]
15
+ # By region. For example, return holidays in the Canada with <tt>:ca</tt>.
16
+ # [<tt>:region_</tt>]
17
+ # By region and sub regions. For example, return holidays in Germany
18
+ # and all its sub regions with <tt>:de_</tt>.
19
+ # [<tt>:region_sub</tt>]
20
+ # By sub region. Return national holidays in Spain plus holidays in Spain's
21
+ # Valencia region with <tt>:es_v</tt>.
22
+ # [<tt>:any</tt>]
23
+ # Any region. Return holidays from any loaded region.
24
+ #
25
+ # == Other options
26
+ # [<tt>:observed</tt>] Return holidays on the day they are observed (e.g. on a Monday if they fall on a Sunday).
27
+ # [<tt>:informal</tt>] Include informal holidays (e.g. Valentine's Day)
28
+ #
29
+ # == Examples
30
+ # Return all holidays in the <tt>:ca</tt> and <tt>:us</tt> regions on the day that they are
31
+ # observed.
32
+ #
33
+ # Holidays.between(from, to, :ca, :us, :observed)
34
+ #
35
+ # Return all holidays in <tt>:ca</tt> and any <tt>:ca</tt> sub-region.
36
+ #
37
+ # Holidays.between(from, to, :ca_)
38
+ #
39
+ # Return all holidays in <tt>:ca_bc</tt> sub-region (which includes the <tt>:ca</tt>), including informal holidays.
40
+ #
41
+ # Holidays.between(from, to, :ca_bc, :informal)
42
+ module Holidays
43
+ # Exception thrown when an unknown region is requested.
44
+ class UnknownRegionError < ArgumentError; end
45
+
46
+ VERSION = '0.9.2'
47
+
48
+ @@regions = []
49
+ @@holidays_by_month = {}
50
+ @@proc_cache = {}
51
+
52
+ WEEKS = {:first => 1, :second => 2, :third => 3, :fourth => 4, :fifth => 5, :last => -1, :second_last => -2, :third_last => -3}
53
+ MONTH_LENGTHS = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
54
+ DAY_SYMBOLS = Date::DAYNAMES.collect { |n| n.downcase.intern }
55
+
56
+ # Get all holidays on a given date.
57
+ #
58
+ # [<tt>date</tt>] A Date object.
59
+ # [<tt>:options</tt>] One or more region symbols, <tt>:informal</tt> and/or <tt>:observed</tt>.
60
+ #
61
+ # Returns an array of hashes or nil. See Holidays#between for the output
62
+ # format.
63
+ #
64
+ # Also available via Date#holidays.
65
+ def self.on(date, *options)
66
+ self.between(date, date, options)
67
+ end
68
+
69
+ # Get all holidays occuring between two dates, inclusively.
70
+ #
71
+ # Returns an array of hashes or nil.
72
+ #
73
+ # Each holiday is returned as a hash with the following fields:
74
+ # [<tt>start_date</tt>] Ruby Date object.
75
+ # [<tt>end_date</tt>] Ruby Date object.
76
+ # [<tt>options</tt>] One or more region symbols, <tt>:informal</tt> and/or <tt>:observed</tt>.
77
+ #
78
+ # ==== Example
79
+ # from = Date.civil(2008,7,1)
80
+ # to = Date.civil(2008,7,31)
81
+ #
82
+ # Holidays.between(from, to, :ca, :us)
83
+ # => [{:name => 'Canada Day', :regions => [:ca]...}
84
+ # {:name => 'Independence Day'', :regions => [:us], ...}]
85
+ def self.between(start_date, end_date, *options)
86
+ start_date = start_date.to_date if start_date.respond_to?(:to_date)
87
+ end_date = end_date.to_date if end_date.respond_to?(:to_date)
88
+ regions, observed, informal = parse_options(options)
89
+ holidays = []
90
+
91
+ dates = {}
92
+ (start_date..end_date).each do |date|
93
+ # Always include month '0' for variable-month holidays
94
+ dates[date.year] = [0] unless dates[date.year]
95
+ # TODO: test this, maybe should push then flatten
96
+ dates[date.year] << date.month unless dates[date.year].include?(date.month)
97
+ end
98
+
99
+ dates.each do |year, months|
100
+ months.each do |month|
101
+ next unless hbm = @@holidays_by_month[month]
102
+
103
+ hbm.each do |h|
104
+ next unless in_region?(regions, h[:regions])
105
+
106
+ # Skip informal holidays unless they have been requested
107
+ next if h[:type] == :informal and not informal
108
+
109
+ if h[:function]
110
+ # Holiday definition requires a calculation
111
+ result = call_proc(h[:function], year)
112
+
113
+ # Procs may return either Date or an integer representing mday
114
+ if result.kind_of?(Date)
115
+ month = result.month
116
+ mday = result.mday
117
+ else
118
+ mday = result
119
+ end
120
+ else
121
+ # Calculate the mday
122
+ mday = h[:mday] || Date.calculate_mday(year, month, h[:week], h[:wday])
123
+ end
124
+
125
+ # Silently skip bad mdays
126
+ begin
127
+ date = Date.civil(year, month, mday)
128
+ rescue; next; end
129
+
130
+ # If the :observed option is set, calculate the date when the holiday
131
+ # is observed.
132
+ if observed and h[:observed]
133
+ date = call_proc(h[:observed], date)
134
+ end
135
+
136
+ if date.between?(start_date, end_date)
137
+ holidays << {:date => date, :name => h[:name], :regions => h[:regions]}
138
+ end
139
+
140
+ end
141
+ end
142
+ end
143
+
144
+ holidays
145
+ end
146
+
147
+ # Merge a new set of definitions into the Holidays module.
148
+ #
149
+ # This method is automatically called when including holiday definition
150
+ # files.
151
+ def self.merge_defs(regions, holidays) # :nodoc:
152
+ @@regions = @@regions | regions
153
+ @@regions.uniq!
154
+
155
+ holidays.each do |month, holiday_defs|
156
+ @@holidays_by_month[month] = [] unless @@holidays_by_month[month]
157
+ holiday_defs.each do |holiday_def|
158
+
159
+ exists = false
160
+ @@holidays_by_month[month].each do |ex|
161
+ # TODO: gross.
162
+ 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]
163
+ # append regions
164
+ ex[:regions] << holiday_def[:regions]
165
+
166
+ # Should do this once we're done
167
+ ex[:regions].flatten!
168
+ ex[:regions].uniq!
169
+ exists = true
170
+ end
171
+ end
172
+
173
+ @@holidays_by_month[month] << holiday_def unless exists
174
+ end
175
+ end
176
+ end
177
+
178
+ # Get the date of Easter Sunday in a given year. From Easter Sunday, it is
179
+ # possible to calculate many traditional holidays in Western countries.
180
+ # Returns a Date object.
181
+ def self.easter(year)
182
+ y = year
183
+ a = y % 19
184
+ b = y / 100
185
+ c = y % 100
186
+ d = b / 4
187
+ e = b % 4
188
+ f = (b + 8) / 25
189
+ g = (b - f + 1) / 3
190
+ h = (19 * a + b - d - g + 15) % 30
191
+ i = c / 4
192
+ k = c % 4
193
+ l = (32 + 2 * e + 2 * i - h - k) % 7
194
+ m = (a + 11 * h + 22 * l) / 451
195
+ month = (h + l - 7 * m + 114) / 31
196
+ day = ((h + l - 7 * m + 114) % 31) + 1
197
+ Date.civil(year, month, day)
198
+ end
199
+
200
+ # Move date to Monday if it occurs on a Sunday.
201
+ # Used as a callback function.
202
+ def self.to_monday_if_sunday(date)
203
+ date += 1 if date.wday == 0
204
+ date
205
+ end
206
+
207
+ # Move date to Monday if it occurs on a Saturday on Sunday.
208
+ # Used as a callback function.
209
+ def self.to_monday_if_weekend(date)
210
+ date += 1 if date.wday == 0
211
+ date += 2 if date.wday == 6
212
+ date
213
+ end
214
+
215
+ # Move Boxing Day if it falls on a weekend, leaving room for Christmas.
216
+ # Used as a callback function.
217
+ def self.to_weekday_if_boxing_weekend(date)
218
+ date += 2 if date.wday == 6 or date.wday == 0
219
+ date
220
+ end
221
+
222
+ # Move date to Monday if it occurs on a Sunday or to Friday if it occurs on a
223
+ # Saturday.
224
+ # Used as a callback function.
225
+ def self.to_weekday_if_weekend(date)
226
+ date += 1 if date.wday == 0
227
+ date -= 1 if date.wday == 6
228
+ date
229
+ end
230
+
231
+ private
232
+ # Returns [(arr)regions, (bool)observed, (bool)informal]
233
+ def self.parse_options(*options) # :nodoc:
234
+ options.flatten!
235
+ observed = options.delete(:observed) ? true : false
236
+ informal = options.delete(:informal) ? true : false
237
+ regions = parse_regions(options)
238
+ return regions, observed, informal
239
+ end
240
+
241
+ # Check regions against list of supported regions and return an array of
242
+ # symbols.
243
+ #
244
+ # If a wildcard region is found (e.g. <tt>:ca_</tt>) it is expanded into all
245
+ # of its available sub regions.
246
+ def self.parse_regions(regions) # :nodoc:
247
+ regions = [regions] unless regions.kind_of?(Array)
248
+ return [:any] if regions.empty?
249
+
250
+ regions = regions.collect { |r| r.to_sym }
251
+
252
+ # Found sub region wild-card
253
+ regions.delete_if do |reg|
254
+ if reg.to_s =~ /_$/
255
+ regions << @@regions.select { |dr| dr.to_s =~ Regexp.new("^#{reg}") }
256
+ true
257
+ end
258
+ end
259
+
260
+ regions.flatten!
261
+
262
+ require "holidays/north_america" if regions.include?(:us) # special case for north_america/US cross-linking
263
+
264
+ raise UnknownRegionError unless regions.all? { |r| r == :any or @@regions.include?(r) or begin require "holidays/#{r.to_s}"; rescue LoadError; false; end }
265
+ regions
266
+ end
267
+
268
+ # Check sub regions.
269
+ #
270
+ # When request :any, all holidays should be returned.
271
+ # When requesting :ca_bc, holidays in :ca or :ca_bc should be returned.
272
+ # When requesting :ca, holidays in :ca but not its subregions should be returned.
273
+ def self.in_region?(requested, available) # :nodoc:
274
+ return true if requested.include?(:any)
275
+
276
+ # When an underscore is encountered, derive the parent regions
277
+ # symbol and include both in the requested array.
278
+ requested = requested.collect do |r|
279
+ r.to_s =~ /_/ ? [r, r.to_s.gsub(/_[\w]*$/, '').to_sym] : r
280
+ end
281
+
282
+ requested = requested.flatten.uniq
283
+
284
+ available.any? { |avail| requested.include?(avail) }
285
+ end
286
+
287
+ # Call a proc function defined in a holiday definition file.
288
+ #
289
+ # Procs are cached.
290
+ #
291
+ # ==== Benchmarks
292
+ #
293
+ # Lookup Easter Sunday, with caching, by number of iterations:
294
+ #
295
+ # user system total real
296
+ # 0001 0.000000 0.000000 0.000000 ( 0.000000)
297
+ # 0010 0.000000 0.000000 0.000000 ( 0.000000)
298
+ # 0100 0.078000 0.000000 0.078000 ( 0.078000)
299
+ # 1000 0.641000 0.000000 0.641000 ( 0.641000)
300
+ # 5000 3.172000 0.015000 3.187000 ( 3.219000)
301
+ #
302
+ # Lookup Easter Sunday, without caching, by number of iterations:
303
+ #
304
+ # user system total real
305
+ # 0001 0.000000 0.000000 0.000000 ( 0.000000)
306
+ # 0010 0.016000 0.000000 0.016000 ( 0.016000)
307
+ # 0100 0.125000 0.000000 0.125000 ( 0.125000)
308
+ # 1000 1.234000 0.000000 1.234000 ( 1.234000)
309
+ # 5000 6.094000 0.031000 6.125000 ( 6.141000)
310
+ def self.call_proc(function, year) # :nodoc:
311
+ proc_key = Digest::MD5.hexdigest("#{function.to_s}_#{year.to_s}")
312
+ @@proc_cache[proc_key] = function.call(year) unless @@proc_cache[proc_key]
313
+ @@proc_cache[proc_key]
314
+ end
315
+ end
316
+
317
+ # === Extending Ruby's Date class with the Holidays gem
318
+ # The Holidays gem automatically extends Ruby's Date class and gives you access
319
+ # to three new methods: holiday?, #holidays and #calculate_mday.
320
+ #
321
+ # ==== Examples
322
+ # Lookup Canada Day in the <tt>:ca</tt> region
323
+ # Date.civil(2008,7,1).holiday?(:ca)
324
+ # => true
325
+ #
326
+ # Lookup Canada Day in the <tt>:fr</tt> region
327
+ # Date.civil(2008,7,1).holiday?(:fr)
328
+ # => false
329
+ #
330
+ # Lookup holidays on North America in January 1.
331
+ # Date.civil(2008,1,1).holidays(:ca, :mx, :us, :informal, :observed)
332
+ # => [{:name => 'New Year\'s Day'...}]
333
+ class Date
334
+ include Holidays
335
+
336
+ # Get holidays on the current date.
337
+ #
338
+ # Returns an array of hashes or nil. See Holidays#between for options
339
+ # and the output format.
340
+ #
341
+ # Date.civil('2008-01-01').holidays(:ca_)
342
+ # => [{:name => 'New Year\'s Day',...}]
343
+ #
344
+ # Also available via Holidays#on.
345
+ def holidays(*options)
346
+ Holidays.on(self, options)
347
+ end
348
+
349
+ # Check if the current date is a holiday.
350
+ #
351
+ # Returns true or false.
352
+ #
353
+ # Date.civil('2008-01-01').holiday?(:ca)
354
+ # => true
355
+ def holiday?(*options)
356
+ holidays = self.holidays(options)
357
+ holidays && !holidays.empty?
358
+ end
359
+
360
+ # Calculate day of the month based on the week number and the day of the
361
+ # week.
362
+ #
363
+ # ==== Parameters
364
+ # [<tt>year</tt>] Integer.
365
+ # [<tt>month</tt>] Integer from 1-12.
366
+ # [<tt>week</tt>] One of <tt>:first</tt>, <tt>:second</tt>, <tt>:third</tt>,
367
+ # <tt>:fourth</tt>, <tt>:fifth</tt> or <tt>:last</tt>.
368
+ # [<tt>wday</tt>] Day of the week as an integer from 0 (Sunday) to 6
369
+ # (Saturday) or as a symbol (e.g. <tt>:monday</tt>).
370
+ #
371
+ # Returns an integer.
372
+ #
373
+ # ===== Examples
374
+ # First Monday of January, 2008:
375
+ # Date.calculate_mday(2008, 1, :first, :monday)
376
+ # => 7
377
+ #
378
+ # Third Thursday of December, 2008:
379
+ # Date.calculate_mday(2008, 12, :third, :thursday)
380
+ # => 18
381
+ #
382
+ # Last Monday of January, 2008:
383
+ # Date.calculate_mday(2008, 1, :last, 1)
384
+ # => 28
385
+ #--
386
+ # see http://www.irt.org/articles/js050/index.htm
387
+ def self.calculate_mday(year, month, week, wday)
388
+ raise ArgumentError, "Week parameter must be one of Holidays::WEEKS (provided #{week})." unless WEEKS.include?(week) or WEEKS.has_value?(week)
389
+
390
+ unless wday.kind_of?(Numeric) and wday.between?(0,6) or DAY_SYMBOLS.index(wday)
391
+ raise ArgumentError, "Wday parameter must be an integer between 0 and 6 or one of Date::DAY_SYMBOLS."
392
+ end
393
+
394
+ week = WEEKS[week] if week.kind_of?(Symbol)
395
+ wday = DAY_SYMBOLS.index(wday) if wday.kind_of?(Symbol)
396
+
397
+ # :first, :second, :third, :fourth or :fifth
398
+ if week > 0
399
+ return ((week - 1) * 7) + 1 + ((7 + wday - Date.civil(year, month,(week-1)*7 + 1).wday) % 7)
400
+ end
401
+
402
+ days = MONTH_LENGTHS[month-1]
403
+
404
+ days = 29 if month == 2 and Date.leap?(year)
405
+
406
+ return days - ((Date.civil(year, month, days).wday - wday + 7) % 7) - (7 * (week.abs - 1))
407
+ end
408
+ end
data/rakefile.rb ADDED
@@ -0,0 +1,103 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+ require 'rake/gempackagetask'
5
+ require 'yaml'
6
+ require 'fileutils'
7
+ require 'lib/holidays'
8
+ require 'data/build_defs'
9
+
10
+ desc 'Run all tests'
11
+ task :test => ["test:lib", "test:defs"]
12
+
13
+ namespace :test do
14
+ desc 'Run the unit tests.'
15
+ Rake::TestTask.new(:defs) do |t|
16
+ t.libs << 'lib'
17
+ t.test_files = FileList['test/defs/test*.rb'].exclude('test_helper.rb')
18
+ t.verbose = false
19
+ end
20
+
21
+ desc 'Run the definition tests.'
22
+ Rake::TestTask.new(:lib) do |t|
23
+ t.libs << 'lib'
24
+ t.test_files = FileList['test/test*.rb'].exclude('test_helper.rb')
25
+ t.verbose = false
26
+ end
27
+ end
28
+
29
+ task :doc => ["defs:manifest", :rdoc]
30
+
31
+ desc 'Generate documentation.'
32
+ Rake::RDocTask.new(:rdoc) do |rdoc|
33
+ rdoc.rdoc_dir = 'doc'
34
+ rdoc.title = 'Ruby Holidays Gem'
35
+ rdoc.options << '--all' << '--inline-source' << '--line-numbers'
36
+ rdoc.options << '--charset' << 'utf-8'
37
+ rdoc.rdoc_files.include('README.rdoc')
38
+ rdoc.rdoc_files.include('data/SYNTAX')
39
+ rdoc.rdoc_files.include('lib/holidays/MANIFEST')
40
+ rdoc.rdoc_files.include('REFERENCES')
41
+ rdoc.rdoc_files.include('CHANGELOG')
42
+ rdoc.rdoc_files.include('LICENSE')
43
+ rdoc.rdoc_files.include('lib/*.rb')
44
+ end
45
+
46
+ desc 'Definition file tasks'
47
+ namespace :defs do
48
+ DATA_PATH = 'data'
49
+
50
+ desc 'Build holiday definition files'
51
+ task :build_all do
52
+ # load the index
53
+ def_index = YAML.load_file("#{DATA_PATH}/index.yaml")
54
+
55
+ # create a dir for the generated tests
56
+ FileUtils.mkdir_p('test/defs')
57
+
58
+ def_index['defs'].each do |region, files|
59
+ puts "Building #{region} definition module:"
60
+ files = files.collect { |f| "#{DATA_PATH}/#{f}" }
61
+ files.uniq!
62
+
63
+ module_src, test_src = parse_holiday_defs(region, files)
64
+ File.open("lib/holidays/#{region.downcase.to_s}.rb","w") do |file|
65
+ file.puts module_src
66
+ end
67
+ unless test_src.empty?
68
+ File.open("test/defs/test_defs_#{region.downcase.to_s}.rb","w") do |file|
69
+ file.puts test_src
70
+ end
71
+ end
72
+ puts "Done.\n\n"
73
+ end
74
+ end
75
+
76
+ desc 'Build the definition manifest.'
77
+ task :manifest do
78
+ File.open("lib/holidays/MANIFEST","w") do |file|
79
+ file.puts <<-EOH
80
+ ==== Regional definitions
81
+ The following definition files are included in this installation:
82
+
83
+ EOH
84
+ FileList.new('lib/holidays/*.rb').each do |str|
85
+ file.puts('* ' + str.gsub(/^lib\/|\.rb$/, ''))
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ begin
92
+ require 'jeweler'
93
+ Jeweler::Tasks.new do |gemspec|
94
+ gemspec.name = "wombleton-holidays"
95
+ gemspec.summary = "A collection of Ruby methods to deal with statutory and other holidays. You deserve a holiday!"
96
+ gemspec.description = "A collection of Ruby methods to deal with statutory and other holidays. You deserve a holiday!"
97
+ gemspec.email = "wombleton@gmail.com"
98
+ gemspec.homepage = "http://github.com/wombleton/holidays"
99
+ gemspec.authors = ["Alex Dunae", "Rowan Crawford"]
100
+ end
101
+ rescue LoadError
102
+ puts "Jeweler not available. Install it with: gem install jeweler"
103
+ end
@@ -0,0 +1,35 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ # This file is generated by the Ruby Holiday gem.
4
+ #
5
+ # Definitions loaded: data/au.yaml
6
+ class AuDefinitionTests < Test::Unit::TestCase # :nodoc:
7
+
8
+ def test_au
9
+ {Date.civil(2007,1,1) => 'New Year\'s Day',
10
+ Date.civil(2007,1,26) => 'Australia Day',
11
+ Date.civil(2007,4,6) => 'Good Friday',
12
+ Date.civil(2007,4,9) => 'Easter Monday',
13
+ Date.civil(2007,4,25) => 'ANZAC Day',
14
+ Date.civil(2007,12,25) => 'Christmas Day',
15
+ Date.civil(2007,12,26) => 'Boxing Day'}.each do |date, name|
16
+ assert_equal name, (Holidays.on(date, :au, :informal)[0] || {})[:name]
17
+ end
18
+
19
+ [:au_sa, :au_act, :au_nsw, :au_].each do |r|
20
+ assert_equal 'Labour Day', Date.civil(2007,10,1).holidays(r)[0][:name]
21
+ end
22
+
23
+ [:au_sa, :au_act, :au_nsw, :au_vic, :au_tas, :au_qld, :au_nt, :au_].each do |r|
24
+ assert_equal 'Queen\'s Birthday', Date.civil(2007,6,11).holidays(r)[0][:name]
25
+ end
26
+
27
+ assert_equal 'Labour Day', Date.civil(2007,3,5).holidays(:au_wa)[0][:name]
28
+ assert_equal 'Labour Day', Date.civil(2007,3,12).holidays(:au_vic)[0][:name]
29
+ assert_equal 'Labour Day', Date.civil(2007,5,7).holidays(:au_qld)[0][:name]
30
+
31
+ assert_equal 'May Day', Date.civil(2007,5,7).holidays(:au_nt)[0][:name]
32
+
33
+ assert_equal 'Eight Hours Day', Date.civil(2007,3,12).holidays(:au_tas)[0][:name]
34
+ end
35
+ end
@@ -0,0 +1,28 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ # This file is generated by the Ruby Holiday gem.
4
+ #
5
+ # Definitions loaded: data/ca.yaml, data/north_america_informal.yaml
6
+ class CaDefinitionTests < Test::Unit::TestCase # :nodoc:
7
+
8
+ def test_ca
9
+ {Date.civil(2008,1,1) => 'New Year\'s Day',
10
+ Date.civil(2008,3,21) => 'Good Friday',
11
+ Date.civil(2008,3,24) => 'Easter Monday',
12
+ Date.civil(2008,5,19) => 'Victoria Day',
13
+ Date.civil(2008,7,1) => 'Canada Day',
14
+ Date.civil(2008,9,1) => 'Labour Day',
15
+ Date.civil(2008,10,13) => 'Thanksgiving',
16
+ Date.civil(2008,11,11) => 'Rememberance Day',
17
+ Date.civil(2008,12,25) => 'Christmas Day',
18
+ Date.civil(2008,12,26) => 'Boxing Day'}.each do |date, name|
19
+ assert_equal name, (Holidays.on(date, :ca, :informal)[0] || {})[:name]
20
+ end
21
+
22
+ # Victoria Day
23
+ [Date.civil(2004,5,24), Date.civil(2005,5,23), Date.civil(2006,5,22),
24
+ Date.civil(2007,5,21), Date.civil(2008,5,19)].each do |date|
25
+ assert_equal 'Victoria Day', Holidays.on(date, :ca)[0][:name]
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ # This file is generated by the Ruby Holiday gem.
4
+ #
5
+ # Definitions loaded: data/cz.yaml
6
+ class CzDefinitionTests < Test::Unit::TestCase # :nodoc:
7
+
8
+ def test_cz
9
+ {Date.civil(2010,1,1) => 'Den obnovy samostatného českého státu',
10
+ Date.civil(2010,4,5) => 'Velikonoční pondělí',
11
+ Date.civil(2010,5,1) => 'Svátek práce',
12
+ Date.civil(2010,5,8) => 'Den vítězství',
13
+ Date.civil(2010,7,5) => 'Den slovanských věrozvěstů Cyrila a Metoděje',
14
+ Date.civil(2010,7,6) => 'Den upálení mistra Jana Husa',
15
+ Date.civil(2010,9,28) => 'Den české státnosti',
16
+ Date.civil(2010,10,28) => 'Den vzniku samostatného československého státu',
17
+ Date.civil(2010,11,17) => 'Den boje za svobodu a demokracii',
18
+ Date.civil(2010,12,24) => 'Štědrý den',
19
+ Date.civil(2010,12,25) => '1. svátek vánoční',
20
+ Date.civil(2010,12,26) => '2. svátek vánoční'}.each do |date, name|
21
+ assert_equal name, (Holidays.on(date, :cz, :informal)[0] || {})[:name]
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,48 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ # This file is generated by the Ruby Holiday gem.
4
+ #
5
+ # Definitions loaded: data/de.yaml
6
+ class DeDefinitionTests < Test::Unit::TestCase # :nodoc:
7
+
8
+ def test_de
9
+ {Date.civil(2009,1,1) => 'Neujahrstag',
10
+ Date.civil(2009,4,10) => 'Karfreitag',
11
+ Date.civil(2009,4,13) => 'Ostermontag',
12
+ Date.civil(2009,5,1) => 'Tag der Arbeit',
13
+ Date.civil(2009,5,21) => 'Christi Himmelfahrt',
14
+ Date.civil(2009,6,1) => 'Pfingstmontag',
15
+ Date.civil(2009,10,3) => 'Tag der Deutschen Einheit',
16
+ Date.civil(2009,12,25) => '1. Weihnachtstag',
17
+ Date.civil(2009,12,26) => '2. Weihnachtstag'}.each do |date, name|
18
+ assert_equal name, (Holidays.on(date, :de, :informal)[0] || {})[:name]
19
+ end
20
+
21
+ [:de_bw, :de_by, :de_st, :de_].each do |r|
22
+ assert_equal 'Heilige Drei Könige', Date.civil(2009,1,6).holidays(r)[0][:name]
23
+ end
24
+
25
+ [:de_bw, :de_by, :de_he, :de_nw, :de_rp, :de_sl, :de_].each do |r|
26
+ assert_equal 'Fronleichnam', Date.civil(2009,6,11).holidays(r)[0][:name]
27
+ end
28
+
29
+ [:de_by, :de_sl, :de_].each do |r|
30
+ assert_equal 'Mariä Himmelfahrt', Date.civil(2009,8,15).holidays(r)[0][:name]
31
+ end
32
+
33
+ [:de_bb, :de_mv, :de_sn, :de_st, :de_th, :de_].each do |r|
34
+ assert_equal 'Reformationstag', Date.civil(2009,10,31).holidays(r)[0][:name]
35
+ end
36
+
37
+ [:de_bw, :de_by, :de_nw, :de_rp, :de_sl, :de_].each do |r|
38
+ assert_equal 'Allerheiligen', Date.civil(2009,11,1).holidays(r)[0][:name]
39
+ end
40
+
41
+ # Repentance Day
42
+ assert_equal 'Buß- und Bettag', Date.civil(2004,11,17).holidays(:de_sn)[0][:name]
43
+ assert_equal 'Buß- und Bettag', Date.civil(2005,11,16).holidays(:de_sn)[0][:name]
44
+ assert_equal 'Buß- und Bettag', Date.civil(2006,11,22).holidays(:de_sn)[0][:name]
45
+ assert_equal 'Buß- und Bettag', Date.civil(2009,11,18).holidays(:de_sn)[0][:name]
46
+
47
+ end
48
+ end
@@ -0,0 +1,29 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ # This file is generated by the Ruby Holiday gem.
4
+ #
5
+ # Definitions loaded: data/dk.yaml
6
+ class DkDefinitionTests < Test::Unit::TestCase # :nodoc:
7
+
8
+ def test_dk
9
+ {Date.civil(2007,1,1) => 'Nytårsdag',
10
+ Date.civil(2007,2,18) => 'Fastelavn',
11
+ Date.civil(2007,4,9) => 'Danmarks besættelse',
12
+ Date.civil(2007,4,16) => 'Dronningens fødselsdag',
13
+ Date.civil(2007,4,5) => 'Skærtorsdag',
14
+ Date.civil(2007,4,6) => 'Langfredag',
15
+ Date.civil(2007,4,8) => 'Påskedag',
16
+ Date.civil(2007,4,9) => '2. påskedag',
17
+ Date.civil(2007,5,1) => 'Arbejdernes kampdag',
18
+ Date.civil(2007,5,4) => 'Store Bededag',
19
+ Date.civil(2007,5,17) => 'Kristi Himmelfartsdag',
20
+ Date.civil(2007,5,27) => 'Pinsedag',
21
+ Date.civil(2007,5,28) => '2. Pinsedag',
22
+ Date.civil(2007,6,5) => 'Grundlovsdag',
23
+ Date.civil(2007,12,24) => 'Juleaftensdag',
24
+ Date.civil(2007,12,25) => '1. juledag',
25
+ Date.civil(2007,12,26) => '2. juledag'}.each do |date, name|
26
+ assert_equal name, (Holidays.on(date, :dk, :informal)[0] || {})[:name]
27
+ end
28
+ end
29
+ end