holidays 4.0.0 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a3ae038d2ecc81231efdb1dfb62b8aa5f8a9a08b
4
- data.tar.gz: 0ee05da812d8db5409bad033938d44d127c5a9a7
3
+ metadata.gz: daf9f996b85b5c11645266f2604847ceddf8d4a3
4
+ data.tar.gz: 1c37b24104b546431ba477bf22ed8ac35a622c5f
5
5
  SHA512:
6
- metadata.gz: d89718606e9235afedb475611e069cc5cfeae83951f28881418df6299287cd947bff46df32ee6fbec68eb3794f42622c90ca8d69b4fc764bc9a0464542a1e36f
7
- data.tar.gz: 1005849766e633f5fad96e4cdc37f8d5ab021c63b5a50c921bd066239eedd69d07d22f0b83474af958fc32db75cfee83ff7216f6d8a146b4788466e05702fc1b
6
+ metadata.gz: 4d782ce1901f6e8efab46412277d807d310e88881f87a283ef9a5e94108a2dcbc9d13f25f1c30927024cc0c24263fee77514ce8d73113c6130c0290cd978593a
7
+ data.tar.gz: 9e23cb50fdaa0889020463b8e104726922300f07d0536ca3d0ab39b1838756082fdfcc1e48552d6fba787424ef46383f6151e66b69da21a39eeec44ef1b4dbf2
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Ruby Holidays Gem CHANGELOG
2
2
 
3
+ ## 4.1.0
4
+
5
+ * Issue-161: correctly report St Andrews Day as informal 2006 and earlier in `gb_sct`
6
+ * Issue-169: set correct years of observance for Family Day in various `ca` provinces
7
+ * Issue-163: Add `next_holidays` method. See README for usage (https://github.com/ttwo32)
8
+
3
9
  ## 4.0.0
4
10
 
5
11
  Major refactor with breaking changes! Sorry for the wall of text but there is a lot of info here.
@@ -0,0 +1,74 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ In the interest of fostering an open and welcoming environment, we as
6
+ contributors and maintainers pledge to making participation in our project and
7
+ our community a harassment-free experience for everyone, regardless of age, body
8
+ size, disability, ethnicity, gender identity and expression, level of experience,
9
+ nationality, personal appearance, race, religion, or sexual identity and
10
+ orientation.
11
+
12
+ ## Our Standards
13
+
14
+ Examples of behavior that contributes to creating a positive environment
15
+ include:
16
+
17
+ * Using welcoming and inclusive language
18
+ * Being respectful of differing viewpoints and experiences
19
+ * Gracefully accepting constructive criticism
20
+ * Focusing on what is best for the community
21
+ * Showing empathy towards other community members
22
+
23
+ Examples of unacceptable behavior by participants include:
24
+
25
+ * The use of sexualized language or imagery and unwelcome sexual attention or
26
+ advances
27
+ * Trolling, insulting/derogatory comments, and personal or political attacks
28
+ * Public or private harassment
29
+ * Publishing others' private information, such as a physical or electronic
30
+ address, without explicit permission
31
+ * Other conduct which could reasonably be considered inappropriate in a
32
+ professional setting
33
+
34
+ ## Our Responsibilities
35
+
36
+ Project maintainers are responsible for clarifying the standards of acceptable
37
+ behavior and are expected to take appropriate and fair corrective action in
38
+ response to any instances of unacceptable behavior.
39
+
40
+ Project maintainers have the right and responsibility to remove, edit, or
41
+ reject comments, commits, code, wiki edits, issues, and other contributions
42
+ that are not aligned to this Code of Conduct, or to ban temporarily or
43
+ permanently any contributor for other behaviors that they deem inappropriate,
44
+ threatening, offensive, or harmful.
45
+
46
+ ## Scope
47
+
48
+ This Code of Conduct applies both within project spaces and in public spaces
49
+ when an individual is representing the project or its community. Examples of
50
+ representing a project or community include using an official project e-mail
51
+ address, posting via an official social media account, or acting as an appointed
52
+ representative at an online or offline event. Representation of a project may be
53
+ further defined and clarified by project maintainers.
54
+
55
+ ## Enforcement
56
+
57
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
+ reported by contacting the project team at holidaysgem@gmail.com. All
59
+ complaints will be reviewed and investigated and will result in a response that
60
+ is deemed necessary and appropriate to the circumstances. The project team is
61
+ obligated to maintain confidentiality with regard to the reporter of an incident.
62
+ Further details of specific enforcement policies may be posted separately.
63
+
64
+ Project maintainers who do not follow or enforce the Code of Conduct in good
65
+ faith may face temporary or permanent repercussions as determined by other
66
+ members of the project's leadership.
67
+
68
+ ## Attribution
69
+
70
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
+ available at [http://contributor-covenant.org/version/1/4][version]
72
+
73
+ [homepage]: http://contributor-covenant.org
74
+ [version]: http://contributor-covenant.org/version/1/4/
data/CONTRIBUTING.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  There are multiple ways to help! We rely on users around the world to help keep our definitions accurate and up to date. In addition, pull requests to address bugs or implement new features are always welcome.
4
4
 
5
+ ## Code of Conduct
6
+
7
+ Please read our [Code of Conduct](CODE_OF_CONDUCT.md) before contributing. Everyone interacting with this project (or associated projects) is expected to abide by its terms.
8
+
5
9
  ## For definition updates
6
10
 
7
11
  Our definitions are written in YAML. You can find a complete guide to our format in the [definitions README](definitions/README.md). We take the YAML definitions and generate final ruby classes that are loaded at runtime for fast calculations.
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Ruby Holidays Gem [![Build Status](https://travis-ci.org/holidays/holidays.svg?branch=master)](https://travis-ci.org/holidays/holidays) [![Coverage Status](https://coveralls.io/repos/holidays/holidays/badge.svg)](https://coveralls.io/r/holidays/holidays)
1
+ # Ruby Holidays Gem [![Build Status](https://travis-ci.org/holidays/holidays.svg?branch=master)](https://travis-ci.org/holidays/holidays) [![Coverage Status](https://coveralls.io/repos/github/holidays/holidays/badge.svg?branch=master)](https://coveralls.io/github/holidays/holidays?branch=master)
2
2
 
3
3
  A set of functions to deal with holidays in Ruby.
4
4
 
@@ -65,6 +65,13 @@ To check if there are any holidays taking place during a specified work week:
65
65
  Holidays.any_holidays_during_work_week?(Date.civil(2016, 1, 1))
66
66
  => true
67
67
 
68
+ To find and return the next holidays occurring from date, inclusively:
69
+
70
+ Holidays.next_holidays(3, [:us, :informal], Date.civil(2016, 2, 23))
71
+ => [{:name => "St. Patrick's Day",...}, {:name => "Good Friday",...}, {:name => "Easter Sunday",...}]
72
+
73
+ Will default to `Date.today` if no date is provided.
74
+
68
75
  ### Loading Custom Definitions on the fly
69
76
 
70
77
  Load custom definitions file on the fly and use them immediately.
data/definitions/ca.yaml CHANGED
@@ -1,5 +1,8 @@
1
1
  # Canadian holiday definitions for the Ruby Holiday gem.
2
- # Updated 2014-11-12.
2
+ # Updated 2016-04-29.
3
+ #
4
+ # Notes:
5
+ # - 'Family Day' in various provinces are only celebrated after certain years: http://www.timeanddate.com/holidays/canada/family-day
3
6
  ---
4
7
  months:
5
8
  0:
@@ -24,25 +27,43 @@ months:
24
27
  mday: 2
25
28
  2:
26
29
  - name: Family Day
27
- regions: [ca_ab, ca_on, ca_sk]
30
+ regions: [ca_ab]
31
+ wday: 1
32
+ week: 3
33
+ year_ranges:
34
+ - after: 1990
35
+ - name: Family Day
36
+ regions: [ca_sk]
37
+ wday: 1
38
+ week: 3
39
+ year_ranges:
40
+ - after: 2007
41
+ - name: Family Day
42
+ regions: [ca_on]
28
43
  wday: 1
29
44
  week: 3
45
+ year_ranges:
46
+ - after: 2008
47
+ - name: Family Day
48
+ regions: [ca_bc]
49
+ wday: 1
50
+ week: 2
51
+ year_ranges:
52
+ - after: 2013
30
53
  - name: Louis Riel Day
31
54
  regions: [ca_mb]
32
55
  wday: 1
33
56
  week: 3
34
- - name: Nova Scotia Heritage Day # Ideally would be restricted to 2015 or later
57
+ - name: Nova Scotia Heritage Day
35
58
  regions: [ca_ns]
36
59
  wday: 1
37
60
  week: 3
61
+ year_ranges:
62
+ - after: 2015
38
63
  - name: Islander Day
39
64
  regions: [ca_pe]
40
65
  wday: 1
41
66
  week: 3
42
- - name: BC Family Day # Ideally would be restricted to 2013 or later
43
- regions: [ca_bc]
44
- wday: 1
45
- week: 2
46
67
  3:
47
68
  - name: St. Patrick's Day
48
69
  regions: [ca_nf]
@@ -156,16 +177,104 @@ tests: |
156
177
  assert_equal name, (Holidays.on(date, :ca, :informal)[0] || {})[:name]
157
178
  end
158
179
 
159
- # Family Day in BC
160
- [ Date.civil(2013,2,11), Date.civil(2014,2,10) ].each do |date|
161
- assert_equal 'BC Family Day', Holidays.on(date, :ca_bc)[0][:name]
180
+ # Family Day in Alberta - Should only be active on 1990 or later
181
+ [
182
+ Date.civil(1990,2,19),
183
+ Date.civil(2013,2,18),
184
+ Date.civil(2014,2,17),
185
+ Date.civil(2044,2,15),
186
+ ].each do |date|
187
+ assert_equal 'Family Day', Holidays.on(date, :ca_ab)[0][:name]
162
188
  end
163
189
 
164
- # Nova Scotia Heritage Day
165
- [ Date.civil(2015,2,16), Date.civil(2016,2,15) ].each do |date|
190
+ # Family Day in Alberta - should not be active before 1990
191
+ [
192
+ Date.civil(1970,2,16),
193
+ Date.civil(1988,2,15),
194
+ Date.civil(1989,2,20),
195
+ ].each do |date|
196
+ assert_equal [], Holidays.on(date, :ca_ab)
197
+ end
198
+
199
+ # Family Day in Saskatchewan - Should only be active on 2007 or later
200
+ [
201
+ Date.civil(2007,2,19),
202
+ Date.civil(2013,2,18),
203
+ Date.civil(2014,2,17),
204
+ Date.civil(2044,2,15),
205
+ ].each do |date|
206
+ assert_equal 'Family Day', Holidays.on(date, :ca_sk)[0][:name]
207
+ end
208
+
209
+ # Family Day in Saskatchewan - should not be active before 2007
210
+ [
211
+ Date.civil(1970,2,16),
212
+ Date.civil(1988,2,15),
213
+ Date.civil(1989,2,20),
214
+ Date.civil(2006,2,20),
215
+ ].each do |date|
216
+ assert_equal [], Holidays.on(date, :ca_sk)
217
+ end
218
+
219
+ # Family Day in Ontario - Should only be active on 2008 or later
220
+ [
221
+ Date.civil(2008,2,18),
222
+ Date.civil(2013,2,18),
223
+ Date.civil(2014,2,17),
224
+ Date.civil(2044,2,15),
225
+ ].each do |date|
226
+ assert_equal 'Family Day', Holidays.on(date, :ca_on)[0][:name]
227
+ end
228
+
229
+ # Family Day in Ontario - should not be active before 2008
230
+ [
231
+ Date.civil(1970,2,16),
232
+ Date.civil(1988,2,15),
233
+ Date.civil(1989,2,20),
234
+ Date.civil(2006,2,20),
235
+ Date.civil(2007,2,19),
236
+ ].each do |date|
237
+ assert_equal [], Holidays.on(date, :ca_on)
238
+ end
239
+
240
+ # Family Day in BC - Should only be active on 2013 or later
241
+ [
242
+ Date.civil(2013,2,11),
243
+ Date.civil(2014,2,10),
244
+ Date.civil(2044,2,8),
245
+ ].each do |date|
246
+ assert_equal 'Family Day', Holidays.on(date, :ca_bc)[0][:name]
247
+ end
248
+
249
+ # Family Day in BC - should not be active before 2013
250
+ [
251
+ Date.civil(2000,2,14),
252
+ Date.civil(2011,2,14),
253
+ Date.civil(2012,2,13),
254
+ ].each do |date|
255
+ assert_equal [], Holidays.on(date, :ca_bc)
256
+ end
257
+
258
+ # Nova Scotia Heritage Day - should only be active on 2015 and later
259
+ [
260
+ Date.civil(2015,2,16),
261
+ Date.civil(2016,2,15),
262
+ Date.civil(2017,2,20),
263
+ Date.civil(2044,2,15),
264
+ ].each do |date|
166
265
  assert_equal 'Nova Scotia Heritage Day', Holidays.on(date, :ca_ns)[0][:name]
167
266
  end
168
267
 
268
+ # Nova Scotia Heritage Day - should not be active before 2015
269
+ [
270
+ Date.civil(2000,2,21),
271
+ Date.civil(2012,2,20),
272
+ Date.civil(2013,2,18),
273
+ Date.civil(2014,2,17),
274
+ ].each do |date|
275
+ assert_equal [], Holidays.on(date, :ca_ns)
276
+ end
277
+
169
278
  # Islander Day in PE
170
279
  [ Date.civil(2013,2,18), Date.civil(2014,2,17) ].each do |date|
171
280
  assert_equal 'Islander Day', Holidays.on(date, :ca_pe)[0][:name]
data/definitions/gb.yaml CHANGED
@@ -3,13 +3,14 @@
3
3
  # Including England, Wales, Scotland, N. Ireland, the Isle of Man, Guernsey
4
4
  # and Jersey.
5
5
  #
6
- # Updated: 2008-11-28.
6
+ # Updated: 2016-04-29
7
7
  # Sources:
8
8
  # - http://en.wikipedia.org/wiki/List_of_holidays_by_country#United_Kingdom_and_Crown_dependencies
9
9
  #
10
10
  # Notes:
11
11
  # - Jersey, Guernsey and the Isle of Man are encode with both their ISO 3166-1 and ISO 3-3166-2 codes.
12
12
  # - England and Wales together should be encoded as [gb_eng, gb_wls, gb_eaw...]
13
+ # - For :gb_sct, St. Andrew's Day is 'informal' 2006 and earlier but a bank holiday from 2007 on.
13
14
  ---
14
15
  months:
15
16
  0:
@@ -78,6 +79,14 @@ months:
78
79
  mday: 30
79
80
  type: informal
80
81
  observed: to_monday_if_weekend(date)
82
+ year_ranges:
83
+ - before: 2006
84
+ - name: St. Andrew's Day
85
+ regions: [gb_sct]
86
+ mday: 30
87
+ observed: to_monday_if_weekend(date)
88
+ year_ranges:
89
+ - after: 2007
81
90
  12:
82
91
  - name: Christmas Day
83
92
  regions: [gb]
@@ -99,7 +108,23 @@ tests: |
99
108
  end
100
109
 
101
110
  assert_equal 'St. Patrick\'s Day', Holidays.on(Date.civil(2008,3,17), :gb_nir, :informal)[0][:name]
102
- assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2008,11,30), :gb_sct, :informal)[0][:name]
111
+
112
+ # St. Andrew's Day is informal 2006 and earlier. Should only show up when :informal is passed
113
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2006,11,30), :gb_sct, :informal)[0][:name]
114
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2006,11,30), :gb_sct, :informal, :observed)[0][:name]
115
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2002,12,2), :gb_sct, :informal, :observed)[0][:name]
116
+ assert_equal [], Holidays.on(Date.civil(2004,11,30), :gb_sct)
117
+ assert_equal [], Holidays.on(Date.civil(2005,11,30), :gb_sct)
118
+ assert_equal [], Holidays.on(Date.civil(2006,11,30), :gb_sct)
119
+
120
+ # St. Andrew's Day is considered a formal bank holiday 2007 and later. It should show up regardless of whether
121
+ # :informal is specified
122
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2007,11,30), :gb_sct)[0][:name]
123
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2007,11,30), :gb_sct, :informal)[0][:name]
124
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2007,11,30), :gb_sct, :informal, :observed)[0][:name]
125
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2016,11,30), :gb_sct)[0][:name]
126
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2019,11,30), :gb_sct)[0][:name]
127
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2019,12,2), :gb_sct, :observed)[0][:name]
103
128
 
104
129
  assert_equal 'Christmas Day', Holidays.on(Date.civil(2008,12,25), :gb_, :observed)[0][:name]
105
130
  assert_equal 'Christmas Day', Holidays.on(Date.civil(2009,12,25), :gb_, :observed)[0][:name]
@@ -1,4 +1,4 @@
1
1
  # encoding: utf-8
2
2
  module Holidays
3
- REGIONS = [:ar, :at, :au, :au_nsw, :au_vic, :au_qld, :au_nt, :au_act, :au_sa, :au_tas_south, :au_wa, :au_tas, :au_qld_cairns, :au_qld_brisbane, :au_tas_north, :au_vic_melbourne, :be_fr, :be_nl, :br, :bg_en, :bg_bg, :ca, :ca_qc, :ca_ab, :ca_on, :ca_sk, :ca_mb, :ca_ns, :ca_pe, :ca_bc, :ca_nf, :ca_nt, :ca_nu, :ca_nb, :ca_yk, :us, :ch_zh, :ch_be, :ch_lu, :ch_ur, :ch_sz, :ch_ow, :ch_nw, :ch_gl, :ch_zg, :ch_fr, :ch_so, :ch_bs, :ch_bl, :ch_sh, :ch_ar, :ch_ai, :ch_sg, :ch_gr, :ch_ag, :ch_tg, :ch_ti, :ch_vd, :ch_ne, :ch_ge, :ch_ju, :ch_vs, :ch, :cl, :cr, :cz, :dk, :de, :de_bw, :de_by, :de_he, :de_nw, :de_rp, :de_sl, :de_sn_aux, :de_th_aux, :de_sn, :de_st, :de_by_aux, :de_bb, :de_mv, :de_th, :ecb_target, :el, :es_pv, :es_na, :es_an, :es_ib, :es_cm, :es_mu, :es_m, :es_ar, :es_cl, :es_cn, :es_lo, :es_ga, :es_ce, :es_o, :es_ex, :es, :es_ct, :es_v, :es_vc, :federal_reserve, :fedex, :fi, :fr, :gb, :gb_eng, :gb_wls, :gb_eaw, :gb_nir, :gb_sct, :gb_con, :je, :gb_jsy, :gg, :gb_gsy, :im, :gb_iom, :hr, :hu, :ie, :is, :it, :li, :lt, :ma, :mx, :mx_pue, :us, :ca, :nerc, :nl, :no, :nyse, :nz, :nz_sl, :nz_we, :nz_ak, :nz_nl, :nz_ne, :nz_ot, :nz_ta, :nz_sc, :nz_hb, :nz_mb, :nz_ca, :nz_ch, :nz_wl, :ph, :pl, :pt, :ro, :se, :us, :us_dc, :us_ca, :ca, :united_nations, :ups, :za, :ca, :ca_qc, :ca_ab, :ca_on, :ca_sk, :ca_mb, :ca_ns, :ca_pe, :ca_bc, :ca_nf, :ca_nt, :ca_nu, :ca_nb, :ca_yk, :mx, :mx_pue, :us, :us_dc, :us_ca, :dk, :is, :no, :se, :fi, :at, :be_fr, :be_nl, :ch_zh, :ch_be, :ch_lu, :ch_ur, :ch_sz, :ch_ow, :ch_nw, :ch_gl, :ch_zg, :ch_fr, :ch_so, :ch_bs, :ch_bl, :ch_sh, :ch_ar, :ch_ai, :ch_sg, :ch_gr, :ch_ag, :ch_tg, :ch_ti, :ch_vd, :ch_ne, :ch_ge, :ch_ju, :ch_vs, :ch, :cz, :dk, :de, :de_bw, :de_by, :de_he, :de_nw, :de_rp, :de_sl, :de_sn_aux, :de_th_aux, :de_sn, :de_st, :de_by_aux, :de_bb, :de_mv, :de_th, :el, :es_pv, :es_na, :es_an, :es_ib, :es_cm, :es_mu, :es_m, :es_ar, :es_cl, :es_cn, :es_lo, :es_ga, :es_ce, :es_o, :es_ex, :es, :es_ct, :es_v, :es_vc, :fr, :gb, :gb_eng, :gb_wls, :gb_eaw, :gb_nir, :gb_sct, :gb_con, :je, :gb_jsy, :gg, :gb_gsy, :im, :gb_iom, :hr, :hu, :ie, :is, :it, :li, :lt, :nl, :no, :pl, :pt, :ro, :sk, :si, :bg_en, :bg_bg, :jp, :ve, :vi, :sk, :si, :sg]
3
+ REGIONS = [:ar, :at, :au, :au_nsw, :au_vic, :au_qld, :au_nt, :au_act, :au_sa, :au_tas_south, :au_wa, :au_tas, :au_qld_cairns, :au_qld_brisbane, :au_tas_north, :au_vic_melbourne, :be_fr, :be_nl, :br, :bg_en, :bg_bg, :ca, :ca_qc, :ca_ab, :ca_sk, :ca_on, :ca_bc, :ca_mb, :ca_ns, :ca_pe, :ca_nf, :ca_nt, :ca_nu, :ca_nb, :ca_yk, :us, :ch_zh, :ch_be, :ch_lu, :ch_ur, :ch_sz, :ch_ow, :ch_nw, :ch_gl, :ch_zg, :ch_fr, :ch_so, :ch_bs, :ch_bl, :ch_sh, :ch_ar, :ch_ai, :ch_sg, :ch_gr, :ch_ag, :ch_tg, :ch_ti, :ch_vd, :ch_ne, :ch_ge, :ch_ju, :ch_vs, :ch, :cl, :cr, :cz, :dk, :de, :de_bw, :de_by, :de_he, :de_nw, :de_rp, :de_sl, :de_sn_aux, :de_th_aux, :de_sn, :de_st, :de_by_aux, :de_bb, :de_mv, :de_th, :ecb_target, :el, :es_pv, :es_na, :es_an, :es_ib, :es_cm, :es_mu, :es_m, :es_ar, :es_cl, :es_cn, :es_lo, :es_ga, :es_ce, :es_o, :es_ex, :es, :es_ct, :es_v, :es_vc, :federal_reserve, :fedex, :fi, :fr, :gb, :gb_eng, :gb_wls, :gb_eaw, :gb_nir, :gb_sct, :gb_con, :je, :gb_jsy, :gg, :gb_gsy, :im, :gb_iom, :hr, :hu, :ie, :is, :it, :li, :lt, :ma, :mx, :mx_pue, :us, :ca, :nerc, :nl, :no, :nyse, :nz, :nz_sl, :nz_we, :nz_ak, :nz_nl, :nz_ne, :nz_ot, :nz_ta, :nz_sc, :nz_hb, :nz_mb, :nz_ca, :nz_ch, :nz_wl, :ph, :pl, :pt, :ro, :se, :us, :us_dc, :us_ca, :ca, :united_nations, :ups, :za, :ca, :ca_qc, :ca_ab, :ca_sk, :ca_on, :ca_bc, :ca_mb, :ca_ns, :ca_pe, :ca_nf, :ca_nt, :ca_nu, :ca_nb, :ca_yk, :mx, :mx_pue, :us, :us_dc, :us_ca, :dk, :is, :no, :se, :fi, :at, :be_fr, :be_nl, :ch_zh, :ch_be, :ch_lu, :ch_ur, :ch_sz, :ch_ow, :ch_nw, :ch_gl, :ch_zg, :ch_fr, :ch_so, :ch_bs, :ch_bl, :ch_sh, :ch_ar, :ch_ai, :ch_sg, :ch_gr, :ch_ag, :ch_tg, :ch_ti, :ch_vd, :ch_ne, :ch_ge, :ch_ju, :ch_vs, :ch, :cz, :dk, :de, :de_bw, :de_by, :de_he, :de_nw, :de_rp, :de_sl, :de_sn_aux, :de_th_aux, :de_sn, :de_st, :de_by_aux, :de_bb, :de_mv, :de_th, :el, :es_pv, :es_na, :es_an, :es_ib, :es_cm, :es_mu, :es_m, :es_ar, :es_cl, :es_cn, :es_lo, :es_ga, :es_ce, :es_o, :es_ex, :es, :es_ct, :es_v, :es_vc, :fr, :gb, :gb_eng, :gb_wls, :gb_eaw, :gb_nir, :gb_sct, :gb_con, :je, :gb_jsy, :gg, :gb_gsy, :im, :gb_iom, :hr, :hu, :ie, :is, :it, :li, :lt, :nl, :no, :pl, :pt, :ro, :sk, :si, :bg_en, :bg_bg, :jp, :ve, :vi, :sk, :si, :sg]
4
4
  end
@@ -13,7 +13,7 @@ module Holidays
13
13
  # All the definitions are available at https://github.com/holidays/holidays
14
14
  module CA # :nodoc:
15
15
  def self.defined_regions
16
- [:ca, :ca_qc, :ca_ab, :ca_on, :ca_sk, :ca_mb, :ca_ns, :ca_pe, :ca_bc, :ca_nf, :ca_nt, :ca_nu, :ca_nb, :ca_yk, :us]
16
+ [:ca, :ca_qc, :ca_ab, :ca_sk, :ca_on, :ca_bc, :ca_mb, :ca_ns, :ca_pe, :ca_nf, :ca_nt, :ca_nu, :ca_nb, :ca_yk, :us]
17
17
  end
18
18
 
19
19
  def self.holidays_by_month
@@ -23,11 +23,13 @@ module Holidays
23
23
  {:function => "easter(year)", :function_arguments => [:year], :function_modifier => 1, :type => :informal, :name => "Easter Monday", :regions => [:ca]}],
24
24
  1 => [{:mday => 1, :name => "New Year's Day", :regions => [:ca]},
25
25
  {:mday => 2, :name => "New Year's", :regions => [:ca_qc]}],
26
- 2 => [{:wday => 1, :week => 3, :name => "Family Day", :regions => [:ca_ab, :ca_on, :ca_sk]},
26
+ 2 => [{:wday => 1, :week => 3, :year_ranges => [{:after => 1990}],:name => "Family Day", :regions => [:ca_ab]},
27
+ {:wday => 1, :week => 3, :year_ranges => [{:after => 2007}],:name => "Family Day", :regions => [:ca_sk]},
28
+ {:wday => 1, :week => 3, :year_ranges => [{:after => 2008}],:name => "Family Day", :regions => [:ca_on]},
29
+ {:wday => 1, :week => 2, :year_ranges => [{:after => 2013}],:name => "Family Day", :regions => [:ca_bc]},
27
30
  {:wday => 1, :week => 3, :name => "Louis Riel Day", :regions => [:ca_mb]},
28
- {:wday => 1, :week => 3, :name => "Nova Scotia Heritage Day", :regions => [:ca_ns]},
31
+ {:wday => 1, :week => 3, :year_ranges => [{:after => 2015}],:name => "Nova Scotia Heritage Day", :regions => [:ca_ns]},
29
32
  {:wday => 1, :week => 3, :name => "Islander Day", :regions => [:ca_pe]},
30
- {:wday => 1, :week => 2, :name => "BC Family Day", :regions => [:ca_bc]},
31
33
  {:mday => 2, :type => :informal, :name => "Groundhog Day", :regions => [:us, :ca]},
32
34
  {:mday => 14, :type => :informal, :name => "Valentine's Day", :regions => [:us, :ca]}],
33
35
  3 => [{:mday => 23, :name => "St. George's Day", :regions => [:ca_nf]},
@@ -296,7 +296,8 @@ module Holidays
296
296
  {:mday => 1, :name => "Toussaint", :regions => [:fr]},
297
297
  {:mday => 11, :name => "Armistice 1918", :regions => [:fr]},
298
298
  {:mday => 5, :type => :informal, :name => "Guy Fawkes Day", :regions => [:gb]},
299
- {:mday => 30, :observed => "to_monday_if_weekend(date)", :observed_arguments => [:date], :type => :informal, :name => "St. Andrew's Day", :regions => [:gb_sct]},
299
+ {:mday => 30, :year_ranges => [{:before => 2006}],:observed => "to_monday_if_weekend(date)", :observed_arguments => [:date], :type => :informal, :name => "St. Andrew's Day", :regions => [:gb_sct]},
300
+ {:mday => 30, :year_ranges => [{:after => 2007}],:observed => "to_monday_if_weekend(date)", :observed_arguments => [:date], :name => "St. Andrew's Day", :regions => [:gb_sct]},
300
301
  {:mday => 1, :name => "Dan svih svetih", :regions => [:hr]},
301
302
  {:mday => 1, :name => "Mindenszentek", :regions => [:hu]},
302
303
  {:mday => 16, :name => "Dagur íslenskrar tungu", :regions => [:is]},
@@ -33,7 +33,8 @@ module Holidays
33
33
  8 => [{:wday => 1, :week => 1, :name => "Bank Holiday", :regions => [:gb_sct]},
34
34
  {:wday => 1, :week => -1, :name => "Bank Holiday", :regions => [:gb_eng, :gb_wls, :gb_eaw, :gb_nir]}],
35
35
  11 => [{:mday => 5, :type => :informal, :name => "Guy Fawkes Day", :regions => [:gb]},
36
- {:mday => 30, :observed => "to_monday_if_weekend(date)", :observed_arguments => [:date], :type => :informal, :name => "St. Andrew's Day", :regions => [:gb_sct]}],
36
+ {:mday => 30, :year_ranges => [{:before => 2006}],:observed => "to_monday_if_weekend(date)", :observed_arguments => [:date], :type => :informal, :name => "St. Andrew's Day", :regions => [:gb_sct]},
37
+ {:mday => 30, :year_ranges => [{:after => 2007}],:observed => "to_monday_if_weekend(date)", :observed_arguments => [:date], :name => "St. Andrew's Day", :regions => [:gb_sct]}],
37
38
  12 => [{:mday => 25, :observed => "to_monday_if_weekend(date)", :observed_arguments => [:date], :name => "Christmas Day", :regions => [:gb]},
38
39
  {:mday => 26, :observed => "to_weekday_if_boxing_weekend(date)", :observed_arguments => [:date], :name => "Boxing Day", :regions => [:gb]}]
39
40
  }
@@ -13,7 +13,7 @@ module Holidays
13
13
  # All the definitions are available at https://github.com/holidays/holidays
14
14
  module NORTH_AMERICA # :nodoc:
15
15
  def self.defined_regions
16
- [:ca, :ca_qc, :ca_ab, :ca_on, :ca_sk, :ca_mb, :ca_ns, :ca_pe, :ca_bc, :ca_nf, :ca_nt, :ca_nu, :ca_nb, :ca_yk, :mx, :mx_pue, :us, :us_dc, :us_ca]
16
+ [:ca, :ca_qc, :ca_ab, :ca_sk, :ca_on, :ca_bc, :ca_mb, :ca_ns, :ca_pe, :ca_nf, :ca_nt, :ca_nu, :ca_nb, :ca_yk, :mx, :mx_pue, :us, :us_dc, :us_ca]
17
17
  end
18
18
 
19
19
  def self.holidays_by_month
@@ -30,11 +30,13 @@ module Holidays
30
30
  {:mday => 1, :observed => "to_weekday_if_weekend(date)", :observed_arguments => [:date], :name => "New Year's Day", :regions => [:us]},
31
31
  {:wday => 1, :week => 3, :name => "Martin Luther King, Jr. Day", :regions => [:us]},
32
32
  {:function => "us_inauguration_day(year)", :function_arguments => [:year], :name => "Inauguration Day", :regions => [:us_dc]}],
33
- 2 => [{:wday => 1, :week => 3, :name => "Family Day", :regions => [:ca_ab, :ca_on, :ca_sk]},
33
+ 2 => [{:wday => 1, :week => 3, :year_ranges => [{:after => 1990}],:name => "Family Day", :regions => [:ca_ab]},
34
+ {:wday => 1, :week => 3, :year_ranges => [{:after => 2007}],:name => "Family Day", :regions => [:ca_sk]},
35
+ {:wday => 1, :week => 3, :year_ranges => [{:after => 2008}],:name => "Family Day", :regions => [:ca_on]},
36
+ {:wday => 1, :week => 2, :year_ranges => [{:after => 2013}],:name => "Family Day", :regions => [:ca_bc]},
34
37
  {:wday => 1, :week => 3, :name => "Louis Riel Day", :regions => [:ca_mb]},
35
- {:wday => 1, :week => 3, :name => "Nova Scotia Heritage Day", :regions => [:ca_ns]},
38
+ {:wday => 1, :week => 3, :year_ranges => [{:after => 2015}],:name => "Nova Scotia Heritage Day", :regions => [:ca_ns]},
36
39
  {:wday => 1, :week => 3, :name => "Islander Day", :regions => [:ca_pe]},
37
- {:wday => 1, :week => 2, :name => "BC Family Day", :regions => [:ca_bc]},
38
40
  {:wday => 1, :week => 1, :name => "Día de la Constitución", :regions => [:mx]},
39
41
  {:wday => 1, :week => 3, :name => "Presidents' Day", :regions => [:us]},
40
42
  {:mday => 2, :type => :informal, :name => "Groundhog Day", :regions => [:us, :ca]},
data/lib/holidays.rb CHANGED
@@ -122,6 +122,40 @@ module Holidays
122
122
  UseCaseFactory.between.call(start_date, end_date, date_driver_hash, regions, observed, informal)
123
123
  end
124
124
 
125
+ # Get next holidays occuring from date, inclusively.
126
+ #
127
+ # Returns an array of hashes or nil.
128
+ #
129
+ # Incoming arguments are below:
130
+ # [<tt>holidays_count</tt>] Ruby Numeric object. This is the number of holidays to return
131
+ # [<tt>options</tt>] One or more region symbols, <tt>:informal</tt> and/or <tt>:observed</tt>.
132
+ # [<tt>from_date</tt>] Ruby Date object. This is an optional param, defaulted today.
133
+ #
134
+ # ==== Example
135
+ # Date.today
136
+ # => Tue, 23 Feb 2016
137
+ #
138
+ # regions = [:us, :informal]
139
+ #
140
+ # Holidays.next_holidays(3, regions)
141
+ # => [{:name => "St. Patrick's Day",...},
142
+ # {:name => "Good Friday",...},
143
+ # {:name => "Easter Sunday",...}]
144
+ def next_holidays(holidays_count, options, from_date = Date.today)
145
+ raise ArgumentError unless holidays_count
146
+ raise ArgumentError if options.empty?
147
+ raise ArgumentError unless options.is_a?(Array)
148
+
149
+ # remove the timezone
150
+ from_date = from_date.new_offset(0) + from_date.offset if from_date.respond_to?(:new_offset)
151
+
152
+ from_date = get_date(from_date)
153
+ regions, observed, informal = OptionFactory.parse_options.call(options)
154
+ date_driver_hash = UseCaseFactory.dates_driver_builder.build(from_date)
155
+
156
+ UseCaseFactory.next_holiday.call(holidays_count, from_date, date_driver_hash, regions, observed, informal)
157
+ end
158
+
125
159
  # Allows a developer to explicitly calculate and cache holidays within a given period
126
160
  def cache_between(start_date, end_date, *options)
127
161
  start_date, end_date = get_date(start_date), get_date(end_date)
@@ -2,6 +2,8 @@ module Holidays
2
2
  module UseCase
3
3
  module Context
4
4
  class Between
5
+ include ContextCommon
6
+
5
7
  def initialize(holidays_by_month_repo, day_of_month_calculator, custom_methods_repo, proc_result_cache_repo)
6
8
  @holidays_by_month_repo = holidays_by_month_repo
7
9
  @day_of_month_calculator = day_of_month_calculator
@@ -13,101 +15,17 @@ module Holidays
13
15
  validate!(start_date, end_date, dates_driver, regions)
14
16
 
15
17
  holidays = []
16
-
17
- dates_driver.each do |year, months|
18
- months.each do |month|
19
- next unless hbm = holidays_by_month_repo.find_by_month(month)
20
- hbm.each do |h|
21
- next unless in_region?(regions, h[:regions])
22
- next if h[:type] == :informal && !informal
23
-
24
- # range check feature.
25
- if h[:year_ranges]
26
- valid_range_year = false
27
- h[:year_ranges].each do |year_range|
28
- next unless year_range.is_a?(Hash) && year_range.length == 1
29
- next unless year_range.select{
30
- |operator,year|[:before,"before",:after,"after",:limited,"limited",:between,"between"].include?(operator)}.count > 0
31
- case year_range.keys.first
32
- when :before,"before"
33
- valid_range_year = true if year <= year_range[year_range.keys.first]
34
- when :after,"after"
35
- valid_range_year = true if year >= year_range[year_range.keys.first]
36
- when :limited,"limited"
37
- valid_range_year = true if year_range[year_range.keys.first].include?(year)
38
- when :between,"between"
39
- year_range[year_range.keys.first] = Range.new(*year_range[year_range.keys.first].split("..").map(&:to_i)) if year_range[year_range.keys.first].is_a?(String)
40
- valid_range_year = true if year_range[year_range.keys.first].cover?(year)
41
- end
42
- break if valid_range_year
43
- end
44
- next unless valid_range_year
45
- end
46
-
47
- #FIXME I don't like this entire if/else. If it's a function, do something, else do some
48
- # weird mday logic? Bollocks. I think this should be a refactor target.
49
- if h[:function]
50
- function_arguments = []
51
-
52
- #FIXME This is a refactor target. We should also allow 'date'. Right now these are the only
53
- # three things that we allow in. I think having a more testable, robust approach here is vital.
54
- if h[:function_arguments].include?(:year)
55
- function_arguments << year
56
- end
57
-
58
- if h[:function_arguments].include?(:month)
59
- function_arguments << month
60
- end
61
-
62
- if h[:function_arguments].include?(:day)
63
- function_arguments << h[:mday]
64
- end
65
-
66
- result = call_proc(h[:function], *function_arguments)
67
-
68
- #FIXME This is a dangerous assumption. We should raise an error or something
69
- # if these procs return something unexpected.
70
- #
71
- # Procs may return either Date or an integer representing mday
72
- if result.kind_of?(Date)
73
- if h[:function_modifier]
74
- result = result + h[:function_modifier] # NOTE: This could be a positive OR negative number.
75
- end
76
-
77
- month = result.month
78
- mday = result.mday
79
- else
80
- mday = result
81
- end
82
- else
83
- mday = h[:mday] || day_of_month_calculator.call(year, month, h[:week], h[:wday])
84
- end
85
-
86
- # Silently skip bad mdays
87
- begin
88
- date = Date.civil(year, month, mday)
89
- rescue; next; end
90
-
91
- #FIXME We should be checking the function arguments and passing in what is specified.
92
- # Right now all 'observed' functions require 'date' but that is by convention. Nothing
93
- # is requiring that. We should be more explicit.
94
- if observed && h[:observed]
95
- date = call_proc(h[:observed], date)
96
- end
97
-
98
- if date.between?(start_date, end_date)
99
- holidays << {:date => date, :name => h[:name], :regions => h[:regions]}
100
- end
101
- end
102
- end
103
- end
104
-
18
+ holidays = make_date_array(dates_driver, regions, observed, informal)
19
+ holidays = holidays.select{|holiday|holiday[:date].between?(start_date, end_date)}
105
20
  holidays.sort{|a, b| a[:date] <=> b[:date] }
106
21
  end
107
22
 
108
23
  private
109
24
 
110
- attr_reader :holidays_by_month_repo, :day_of_month_calculator, :custom_methods_repo, :proc_result_cache_repo
25
+ attr_reader :holidays_by_month_repo,
26
+ :day_of_month_calculator,
27
+ :custom_methods_repo,
28
+ :proc_result_cache_repo
111
29
 
112
30
  def validate!(start_date, end_date, dates_driver, regions)
113
31
  raise ArgumentError unless start_date
@@ -121,32 +39,6 @@ module Holidays
121
39
 
122
40
  raise ArgumentError if regions.nil? || regions.empty?
123
41
  end
124
-
125
- def call_proc(function_id, *arguments)
126
- function = custom_methods_repo.find(function_id)
127
- raise Holidays::FunctionNotFound.new("Unable to find function with id '#{function_id}'") if function.nil?
128
-
129
- proc_result_cache_repo.lookup(function, *arguments)
130
- end
131
-
132
- # Check sub regions.
133
- #
134
- # When request :any, all holidays should be returned.
135
- # When requesting :ca_bc, holidays in :ca or :ca_bc should be returned.
136
- # When requesting :ca, holidays in :ca but not its subregions should be returned.
137
- def in_region?(requested, available) # :nodoc:
138
- return true if requested.include?(:any)
139
-
140
- # When an underscore is encountered, derive the parent regions
141
- # symbol and include both in the requested array.
142
- requested = requested.collect do |r|
143
- r.to_s =~ /_/ ? [r, r.to_s.gsub(/_[\w]*$/, '').to_sym] : r
144
- end
145
-
146
- requested = requested.flatten.uniq
147
-
148
- available.any? { |avail| requested.include?(avail) }
149
- end
150
42
  end
151
43
  end
152
44
  end
@@ -0,0 +1,123 @@
1
+ module Holidays
2
+ module UseCase
3
+ module Context
4
+ module ContextCommon
5
+ def make_date_array(dates_driver, regions, observed, informal)
6
+ holidays = []
7
+ dates_driver.each do |year, months|
8
+ months.each do |month|
9
+ next unless hbm = holidays_by_month_repo.find_by_month(month)
10
+ hbm.each do |h|
11
+ next unless in_region?(regions, h[:regions])
12
+ next if h[:type] == :informal && !informal
13
+
14
+ # range check feature.
15
+ if h[:year_ranges]
16
+ valid_range_year = false
17
+ h[:year_ranges].each do |year_range|
18
+ next unless year_range.is_a?(Hash) && year_range.length == 1
19
+ next unless year_range.select{
20
+ |operator,year|[:before,"before",:after,"after",:limited,"limited",:between,"between"].include?(operator)}.count > 0
21
+ case year_range.keys.first
22
+ when :before,"before"
23
+ valid_range_year = true if year <= year_range[year_range.keys.first]
24
+ when :after,"after"
25
+ valid_range_year = true if year >= year_range[year_range.keys.first]
26
+ when :limited,"limited"
27
+ valid_range_year = true if year_range[year_range.keys.first].include?(year)
28
+ when :between,"between"
29
+ year_range[year_range.keys.first] = Range.new(*year_range[year_range.keys.first].split("..").map(&:to_i)) if year_range[year_range.keys.first].is_a?(String)
30
+ valid_range_year = true if year_range[year_range.keys.first].cover?(year)
31
+ end
32
+ break if valid_range_year
33
+ end
34
+ next unless valid_range_year
35
+ end
36
+
37
+ #FIXME I don't like this entire if/else. If it's a function, do something, else do some
38
+ # weird mday logic? Bollocks. I think this should be a refactor target.
39
+ if h[:function]
40
+ function_arguments = []
41
+
42
+ #FIXME This is a refactor target. We should also allow 'date'. Right now these are the only
43
+ # three things that we allow in. I think having a more testable, robust approach here is vital.
44
+ if h[:function_arguments].include?(:year)
45
+ function_arguments << year
46
+ end
47
+
48
+ if h[:function_arguments].include?(:month)
49
+ function_arguments << month
50
+ end
51
+
52
+ if h[:function_arguments].include?(:day)
53
+ function_arguments << h[:mday]
54
+ end
55
+
56
+ result = call_proc(h[:function], *function_arguments)
57
+
58
+ #FIXME This is a dangerous assumption. We should raise an error or something
59
+ # if these procs return something unexpected.
60
+ #
61
+ # Procs may return either Date or an integer representing mday
62
+ if result.kind_of?(Date)
63
+ if h[:function_modifier]
64
+ result = result + h[:function_modifier] # NOTE: This could be a positive OR negative number.
65
+ end
66
+
67
+ month = result.month
68
+ mday = result.mday
69
+ else
70
+ mday = result
71
+ end
72
+ else
73
+ mday = h[:mday] || day_of_month_calculator.call(year, month, h[:week], h[:wday])
74
+ end
75
+
76
+ # Silently skip bad mdays
77
+ begin
78
+ date = Date.civil(year, month, mday)
79
+ rescue; next; end
80
+
81
+ #FIXME We should be checking the function arguments and passing in what is specified.
82
+ # Right now all 'observed' functions require 'date' but that is by convention. Nothing
83
+ # is requiring that. We should be more explicit.
84
+ if observed && h[:observed]
85
+ date = call_proc(h[:observed], date)
86
+ end
87
+
88
+ holidays << {:date => date, :name => h[:name], :regions => h[:regions]}
89
+ end
90
+ end
91
+ end
92
+ holidays
93
+ end
94
+
95
+ def call_proc(function_id, *arguments)
96
+ function = custom_methods_repo.find(function_id)
97
+ raise Holidays::FunctionNotFound.new("Unable to find function with id '#{function_id}'") if function.nil?
98
+
99
+ proc_result_cache_repo.lookup(function, *arguments)
100
+ end
101
+
102
+ # Check sub regions.
103
+ #
104
+ # When request :any, all holidays should be returned.
105
+ # When requesting :ca_bc, holidays in :ca or :ca_bc should be returned.
106
+ # When requesting :ca, holidays in :ca but not its subregions should be returned.
107
+ def in_region?(requested, available) # :nodoc:
108
+ return true if requested.include?(:any)
109
+
110
+ # When an underscore is encountered, derive the parent regions
111
+ # symbol and include both in the requested array.
112
+ requested = requested.collect do |r|
113
+ r.to_s =~ /_/ ? [r, r.to_s.gsub(/_[\w]*$/, '').to_sym] : r
114
+ end
115
+
116
+ requested = requested.flatten.uniq
117
+
118
+ available.any? { |avail| requested.include?(avail) }
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -11,16 +11,18 @@ module Holidays
11
11
  def call(start_date, end_date)
12
12
  dates_driver = {}
13
13
 
14
- (start_date..end_date).each do |current_date|
15
- dates_driver[current_date.year] = [] unless dates_driver[current_date.year]
16
- dates_driver[current_date.year] << current_date.month
17
-
18
- dates_driver = add_border_months(current_date, dates_driver)
19
- end
20
-
14
+ (start_date..end_date).map{|current_date|build(dates_driver, current_date)}
21
15
  clean(dates_driver)
22
16
  end
23
17
 
18
+ def build(dates_driver = {}, date)
19
+ raise ArgumentError unless dates_driver
20
+ raise ArgumentError unless date
21
+ dates_driver[date.year] = [] unless dates_driver[date.year]
22
+ dates_driver[date.year] << date.month
23
+ dates_driver = add_border_months(date, dates_driver)
24
+ end
25
+
24
26
  private
25
27
 
26
28
  # As part of https://github.com/holidays/holidays/issues/146 I am returning
@@ -0,0 +1,54 @@
1
+ module Holidays
2
+ module UseCase
3
+ module Context
4
+ class NextHoliday
5
+ include ContextCommon
6
+
7
+ def initialize(holidays_by_month_repo, day_of_month_calculator, custom_methods_repo, proc_result_cache_repo)
8
+ @holidays_by_month_repo = holidays_by_month_repo
9
+ @day_of_month_calculator = day_of_month_calculator
10
+ @custom_methods_repo = custom_methods_repo
11
+ @proc_result_cache_repo = proc_result_cache_repo
12
+ end
13
+
14
+ def call(holidays_count, from_date, dates_driver, regions, observed, informal)
15
+ validate!(holidays_count, from_date, dates_driver, regions)
16
+ holidays = []
17
+ ret_holidays = []
18
+
19
+ ret_holidays = make_date_array(dates_driver, regions, observed, informal)
20
+ ret_holidays.each do |holiday|
21
+ if holiday[:date] >= from_date
22
+ holidays << holiday
23
+ holidays_count -= 1
24
+ break if holidays_count == 0
25
+ end
26
+ end
27
+
28
+ holidays.sort{|a, b| a[:date] <=> b[:date] }
29
+ end
30
+
31
+ private
32
+
33
+ attr_reader :holidays_by_month_repo,
34
+ :day_of_month_calculator,
35
+ :custom_methods_repo,
36
+ :proc_result_cache_repo
37
+
38
+ def validate!(holidays_count, from_date, dates_driver, regions)
39
+ raise ArgumentError unless holidays_count
40
+ raise ArgumentError if holidays_count <= 0
41
+ raise ArgumentError unless from_date
42
+
43
+ raise ArgumentError if dates_driver.nil? || dates_driver.empty?
44
+
45
+ dates_driver.each do |year, months|
46
+ raise ArgumentError if months.nil? || months.empty?
47
+ end
48
+
49
+ raise ArgumentError if regions.nil? || regions.empty?
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -1,4 +1,6 @@
1
+ require 'holidays/use_case/context/context_common'
1
2
  require 'holidays/use_case/context/between'
3
+ require 'holidays/use_case/context/next_holiday'
2
4
  require 'holidays/use_case/context/dates_driver_builder'
3
5
 
4
6
  module Holidays
@@ -12,6 +14,14 @@ module Holidays
12
14
  DefinitionFactory.proc_result_cache_repository,
13
15
  )
14
16
  end
17
+ def next_holiday
18
+ UseCase::Context::NextHoliday.new(
19
+ DefinitionFactory.holidays_by_month_repository,
20
+ DateCalculatorFactory.day_of_month_calculator,
21
+ DefinitionFactory.custom_methods_repository,
22
+ DefinitionFactory.proc_result_cache_repository,
23
+ )
24
+ end
15
25
 
16
26
  def dates_driver_builder
17
27
  UseCase::Context::DatesDriverBuilder.new
@@ -1,3 +1,3 @@
1
1
  module Holidays
2
- VERSION = '4.0.0'
2
+ VERSION = '4.1.0'
3
3
  end
@@ -21,16 +21,104 @@ class CaDefinitionTests < Test::Unit::TestCase # :nodoc:
21
21
  assert_equal name, (Holidays.on(date, :ca, :informal)[0] || {})[:name]
22
22
  end
23
23
 
24
- # Family Day in BC
25
- [ Date.civil(2013,2,11), Date.civil(2014,2,10) ].each do |date|
26
- assert_equal 'BC Family Day', Holidays.on(date, :ca_bc)[0][:name]
24
+ # Family Day in Alberta - Should only be active on 1990 or later
25
+ [
26
+ Date.civil(1990,2,19),
27
+ Date.civil(2013,2,18),
28
+ Date.civil(2014,2,17),
29
+ Date.civil(2044,2,15),
30
+ ].each do |date|
31
+ assert_equal 'Family Day', Holidays.on(date, :ca_ab)[0][:name]
27
32
  end
28
33
 
29
- # Nova Scotia Heritage Day
30
- [ Date.civil(2015,2,16), Date.civil(2016,2,15) ].each do |date|
34
+ # Family Day in Alberta - should not be active before 1990
35
+ [
36
+ Date.civil(1970,2,16),
37
+ Date.civil(1988,2,15),
38
+ Date.civil(1989,2,20),
39
+ ].each do |date|
40
+ assert_equal [], Holidays.on(date, :ca_ab)
41
+ end
42
+
43
+ # Family Day in Saskatchewan - Should only be active on 2007 or later
44
+ [
45
+ Date.civil(2007,2,19),
46
+ Date.civil(2013,2,18),
47
+ Date.civil(2014,2,17),
48
+ Date.civil(2044,2,15),
49
+ ].each do |date|
50
+ assert_equal 'Family Day', Holidays.on(date, :ca_sk)[0][:name]
51
+ end
52
+
53
+ # Family Day in Saskatchewan - should not be active before 2007
54
+ [
55
+ Date.civil(1970,2,16),
56
+ Date.civil(1988,2,15),
57
+ Date.civil(1989,2,20),
58
+ Date.civil(2006,2,20),
59
+ ].each do |date|
60
+ assert_equal [], Holidays.on(date, :ca_sk)
61
+ end
62
+
63
+ # Family Day in Ontario - Should only be active on 2008 or later
64
+ [
65
+ Date.civil(2008,2,18),
66
+ Date.civil(2013,2,18),
67
+ Date.civil(2014,2,17),
68
+ Date.civil(2044,2,15),
69
+ ].each do |date|
70
+ assert_equal 'Family Day', Holidays.on(date, :ca_on)[0][:name]
71
+ end
72
+
73
+ # Family Day in Ontario - should not be active before 2008
74
+ [
75
+ Date.civil(1970,2,16),
76
+ Date.civil(1988,2,15),
77
+ Date.civil(1989,2,20),
78
+ Date.civil(2006,2,20),
79
+ Date.civil(2007,2,19),
80
+ ].each do |date|
81
+ assert_equal [], Holidays.on(date, :ca_on)
82
+ end
83
+
84
+ # Family Day in BC - Should only be active on 2013 or later
85
+ [
86
+ Date.civil(2013,2,11),
87
+ Date.civil(2014,2,10),
88
+ Date.civil(2044,2,8),
89
+ ].each do |date|
90
+ assert_equal 'Family Day', Holidays.on(date, :ca_bc)[0][:name]
91
+ end
92
+
93
+ # Family Day in BC - should not be active before 2013
94
+ [
95
+ Date.civil(2000,2,14),
96
+ Date.civil(2011,2,14),
97
+ Date.civil(2012,2,13),
98
+ ].each do |date|
99
+ assert_equal [], Holidays.on(date, :ca_bc)
100
+ end
101
+
102
+ # Nova Scotia Heritage Day - should only be active on 2015 and later
103
+ [
104
+ Date.civil(2015,2,16),
105
+ Date.civil(2016,2,15),
106
+ Date.civil(2017,2,20),
107
+ Date.civil(2044,2,15),
108
+ ].each do |date|
31
109
  assert_equal 'Nova Scotia Heritage Day', Holidays.on(date, :ca_ns)[0][:name]
32
110
  end
33
111
 
112
+ # Nova Scotia Heritage Day - should not be active before 2015
113
+ [
114
+ Date.civil(2000,2,21),
115
+ Date.civil(2012,2,20),
116
+ Date.civil(2013,2,18),
117
+ Date.civil(2014,2,17),
118
+ ].each do |date|
119
+ assert_equal [], Holidays.on(date, :ca_ns)
120
+ end
121
+
34
122
  # Islander Day in PE
35
123
  [ Date.civil(2013,2,18), Date.civil(2014,2,17) ].each do |date|
36
124
  assert_equal 'Islander Day', Holidays.on(date, :ca_pe)[0][:name]
@@ -307,7 +307,23 @@ end
307
307
  end
308
308
 
309
309
  assert_equal 'St. Patrick\'s Day', Holidays.on(Date.civil(2008,3,17), :gb_nir, :informal)[0][:name]
310
- assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2008,11,30), :gb_sct, :informal)[0][:name]
310
+
311
+ # St. Andrew's Day is informal 2006 and earlier. Should only show up when :informal is passed
312
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2006,11,30), :gb_sct, :informal)[0][:name]
313
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2006,11,30), :gb_sct, :informal, :observed)[0][:name]
314
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2002,12,2), :gb_sct, :informal, :observed)[0][:name]
315
+ assert_equal [], Holidays.on(Date.civil(2004,11,30), :gb_sct)
316
+ assert_equal [], Holidays.on(Date.civil(2005,11,30), :gb_sct)
317
+ assert_equal [], Holidays.on(Date.civil(2006,11,30), :gb_sct)
318
+
319
+ # St. Andrew's Day is considered a formal bank holiday 2007 and later. It should show up regardless of whether
320
+ # :informal is specified
321
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2007,11,30), :gb_sct)[0][:name]
322
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2007,11,30), :gb_sct, :informal)[0][:name]
323
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2007,11,30), :gb_sct, :informal, :observed)[0][:name]
324
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2016,11,30), :gb_sct)[0][:name]
325
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2019,11,30), :gb_sct)[0][:name]
326
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2019,12,2), :gb_sct, :observed)[0][:name]
311
327
 
312
328
  assert_equal 'Christmas Day', Holidays.on(Date.civil(2008,12,25), :gb_, :observed)[0][:name]
313
329
  assert_equal 'Christmas Day', Holidays.on(Date.civil(2009,12,25), :gb_, :observed)[0][:name]
@@ -18,7 +18,23 @@ class GbDefinitionTests < Test::Unit::TestCase # :nodoc:
18
18
  end
19
19
 
20
20
  assert_equal 'St. Patrick\'s Day', Holidays.on(Date.civil(2008,3,17), :gb_nir, :informal)[0][:name]
21
- assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2008,11,30), :gb_sct, :informal)[0][:name]
21
+
22
+ # St. Andrew's Day is informal 2006 and earlier. Should only show up when :informal is passed
23
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2006,11,30), :gb_sct, :informal)[0][:name]
24
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2006,11,30), :gb_sct, :informal, :observed)[0][:name]
25
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2002,12,2), :gb_sct, :informal, :observed)[0][:name]
26
+ assert_equal [], Holidays.on(Date.civil(2004,11,30), :gb_sct)
27
+ assert_equal [], Holidays.on(Date.civil(2005,11,30), :gb_sct)
28
+ assert_equal [], Holidays.on(Date.civil(2006,11,30), :gb_sct)
29
+
30
+ # St. Andrew's Day is considered a formal bank holiday 2007 and later. It should show up regardless of whether
31
+ # :informal is specified
32
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2007,11,30), :gb_sct)[0][:name]
33
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2007,11,30), :gb_sct, :informal)[0][:name]
34
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2007,11,30), :gb_sct, :informal, :observed)[0][:name]
35
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2016,11,30), :gb_sct)[0][:name]
36
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2019,11,30), :gb_sct)[0][:name]
37
+ assert_equal 'St. Andrew\'s Day', Holidays.on(Date.civil(2019,12,2), :gb_sct, :observed)[0][:name]
22
38
 
23
39
  assert_equal 'Christmas Day', Holidays.on(Date.civil(2008,12,25), :gb_, :observed)[0][:name]
24
40
  assert_equal 'Christmas Day', Holidays.on(Date.civil(2009,12,25), :gb_, :observed)[0][:name]
@@ -21,16 +21,104 @@ class North_americaDefinitionTests < Test::Unit::TestCase # :nodoc:
21
21
  assert_equal name, (Holidays.on(date, :ca, :informal)[0] || {})[:name]
22
22
  end
23
23
 
24
- # Family Day in BC
25
- [ Date.civil(2013,2,11), Date.civil(2014,2,10) ].each do |date|
26
- assert_equal 'BC Family Day', Holidays.on(date, :ca_bc)[0][:name]
24
+ # Family Day in Alberta - Should only be active on 1990 or later
25
+ [
26
+ Date.civil(1990,2,19),
27
+ Date.civil(2013,2,18),
28
+ Date.civil(2014,2,17),
29
+ Date.civil(2044,2,15),
30
+ ].each do |date|
31
+ assert_equal 'Family Day', Holidays.on(date, :ca_ab)[0][:name]
27
32
  end
28
33
 
29
- # Nova Scotia Heritage Day
30
- [ Date.civil(2015,2,16), Date.civil(2016,2,15) ].each do |date|
34
+ # Family Day in Alberta - should not be active before 1990
35
+ [
36
+ Date.civil(1970,2,16),
37
+ Date.civil(1988,2,15),
38
+ Date.civil(1989,2,20),
39
+ ].each do |date|
40
+ assert_equal [], Holidays.on(date, :ca_ab)
41
+ end
42
+
43
+ # Family Day in Saskatchewan - Should only be active on 2007 or later
44
+ [
45
+ Date.civil(2007,2,19),
46
+ Date.civil(2013,2,18),
47
+ Date.civil(2014,2,17),
48
+ Date.civil(2044,2,15),
49
+ ].each do |date|
50
+ assert_equal 'Family Day', Holidays.on(date, :ca_sk)[0][:name]
51
+ end
52
+
53
+ # Family Day in Saskatchewan - should not be active before 2007
54
+ [
55
+ Date.civil(1970,2,16),
56
+ Date.civil(1988,2,15),
57
+ Date.civil(1989,2,20),
58
+ Date.civil(2006,2,20),
59
+ ].each do |date|
60
+ assert_equal [], Holidays.on(date, :ca_sk)
61
+ end
62
+
63
+ # Family Day in Ontario - Should only be active on 2008 or later
64
+ [
65
+ Date.civil(2008,2,18),
66
+ Date.civil(2013,2,18),
67
+ Date.civil(2014,2,17),
68
+ Date.civil(2044,2,15),
69
+ ].each do |date|
70
+ assert_equal 'Family Day', Holidays.on(date, :ca_on)[0][:name]
71
+ end
72
+
73
+ # Family Day in Ontario - should not be active before 2008
74
+ [
75
+ Date.civil(1970,2,16),
76
+ Date.civil(1988,2,15),
77
+ Date.civil(1989,2,20),
78
+ Date.civil(2006,2,20),
79
+ Date.civil(2007,2,19),
80
+ ].each do |date|
81
+ assert_equal [], Holidays.on(date, :ca_on)
82
+ end
83
+
84
+ # Family Day in BC - Should only be active on 2013 or later
85
+ [
86
+ Date.civil(2013,2,11),
87
+ Date.civil(2014,2,10),
88
+ Date.civil(2044,2,8),
89
+ ].each do |date|
90
+ assert_equal 'Family Day', Holidays.on(date, :ca_bc)[0][:name]
91
+ end
92
+
93
+ # Family Day in BC - should not be active before 2013
94
+ [
95
+ Date.civil(2000,2,14),
96
+ Date.civil(2011,2,14),
97
+ Date.civil(2012,2,13),
98
+ ].each do |date|
99
+ assert_equal [], Holidays.on(date, :ca_bc)
100
+ end
101
+
102
+ # Nova Scotia Heritage Day - should only be active on 2015 and later
103
+ [
104
+ Date.civil(2015,2,16),
105
+ Date.civil(2016,2,15),
106
+ Date.civil(2017,2,20),
107
+ Date.civil(2044,2,15),
108
+ ].each do |date|
31
109
  assert_equal 'Nova Scotia Heritage Day', Holidays.on(date, :ca_ns)[0][:name]
32
110
  end
33
111
 
112
+ # Nova Scotia Heritage Day - should not be active before 2015
113
+ [
114
+ Date.civil(2000,2,21),
115
+ Date.civil(2012,2,20),
116
+ Date.civil(2013,2,18),
117
+ Date.civil(2014,2,17),
118
+ ].each do |date|
119
+ assert_equal [], Holidays.on(date, :ca_ns)
120
+ end
121
+
34
122
  # Islander Day in PE
35
123
  [ Date.civil(2013,2,18), Date.civil(2014,2,17) ].each do |date|
36
124
  assert_equal 'Islander Day', Holidays.on(date, :ca_pe)[0][:name]
@@ -57,6 +57,21 @@ class HolidaysTests < Test::Unit::TestCase
57
57
  end
58
58
  end
59
59
 
60
+ def test_requires_valid_regions_holiday_next
61
+ assert_raises Holidays::UnknownRegionError do
62
+ Holidays.next_holidays(1, [:xx], Date.civil(2008,1,1))
63
+ end
64
+
65
+ assert_raises Holidays::UnknownRegionError do
66
+ Holidays.next_holidays(1, [:ca,:xx], Date.civil(2008,1,1))
67
+ Holidays.on(Date.civil(2008,1,1), [:ca,:xx])
68
+ end
69
+
70
+ assert_raises Holidays::UnknownRegionError do
71
+ Holidays.next_holidays(1, [:ca,:xx])
72
+ end
73
+ end
74
+
60
75
  def test_region_params
61
76
  holidays = Holidays.on(@date, :ca)
62
77
  assert_equal 1, holidays.length
@@ -90,6 +105,33 @@ class HolidaysTests < Test::Unit::TestCase
90
105
  assert holidays.length >= 3
91
106
  end
92
107
 
108
+ def test_any_region_holiday_next
109
+ # Should return Victoria Day.
110
+ holidays = Holidays.next_holidays(1, [:ca], Date.civil(2008,5,1))
111
+ assert_equal 1, holidays.length
112
+ assert_equal ['2008-05-19','Victoria Day'] , [holidays.first[:date].to_s, holidays.first[:name].to_s]
113
+
114
+ # Should return 2 holidays.
115
+ #
116
+ # Should be 2 in the CA region but other regional files are loaded during the
117
+ # unit tests add to the :any count.
118
+ holidays = Holidays.next_holidays(2, [:any], Date.civil(2008,5,1))
119
+ assert_equal 2, holidays.length
120
+
121
+ # Must Region.If there is not region, raise ArgumentError.
122
+ assert_raises ArgumentError do
123
+ Holidays.next_holidays(2, '', Date.civil(2008,5,1))
124
+ end
125
+ # Options should be present.If they are empty, raise ArgumentError.
126
+ assert_raises ArgumentError do
127
+ Holidays.next_holidays(2, [], Date.civil(2008,5,1))
128
+ end
129
+ # Options should be Array.If they are not Array, raise ArgumentError.
130
+ assert_raises ArgumentError do
131
+ Holidays.next_holidays(2, :ca, Date.civil(2008,5,1))
132
+ end
133
+ end
134
+
93
135
  def test_sub_regions
94
136
  # Should return Victoria Day.
95
137
  holidays = Holidays.between(Date.civil(2008,5,1), Date.civil(2008,5,31), :ca)
@@ -104,6 +146,25 @@ class HolidaysTests < Test::Unit::TestCase
104
146
  assert_equal 2, holidays.length
105
147
  end
106
148
 
149
+ def test_sub_regions_holiday_next
150
+ # Should return Victoria Day.
151
+ holidays = Holidays.next_holidays(2, [:ca], Date.civil(2008,5,1))
152
+ assert_equal 1, holidays.length
153
+ assert_equal ['2008-05-19','Victoria Day'] , [holidays.first[:date].to_s, holidays.first[:name].to_s]
154
+
155
+ # Should return Victoria Da and National Patriotes Day.
156
+ holidays = Holidays.next_holidays(2, [:ca_qc], Date.civil(2008,5,1))
157
+ assert_equal 2, holidays.length
158
+ assert_equal ['2008-05-19','Victoria Day'] , [holidays.first[:date].to_s, holidays.first[:name].to_s]
159
+ assert_equal ['2008-05-19','National Patriotes Day'] , [holidays.last[:date].to_s, holidays.last[:name].to_s]
160
+
161
+ # Should return Victoria Day and National Patriotes Day.
162
+ holidays = Holidays.next_holidays(2, [:ca_], Date.civil(2008,5,1))
163
+ assert_equal 2, holidays.length
164
+ assert_equal ['2008-05-19','Victoria Day'] , [holidays.first[:date].to_s, holidays.first[:name].to_s]
165
+ assert_equal ['2008-05-19','National Patriotes Day'] , [holidays.last[:date].to_s, holidays.last[:name].to_s]
166
+ end
167
+
107
168
  def test_easter_lambda
108
169
  [Date.civil(1800,4,11), Date.civil(1899,3,31), Date.civil(1900,4,13),
109
170
  Date.civil(2008,3,21), Date.civil(2035,3,23)].each do |date|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: holidays
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Dunae
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-04-23 00:00:00.000000000 Z
12
+ date: 2016-05-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -104,6 +104,7 @@ extensions: []
104
104
  extra_rdoc_files: []
105
105
  files:
106
106
  - CHANGELOG.md
107
+ - CODE_OF_CONDUCT.md
107
108
  - CONTRIBUTING.md
108
109
  - Gemfile
109
110
  - LICENSE
@@ -250,7 +251,9 @@ files:
250
251
  - lib/holidays/option/context/parse_options.rb
251
252
  - lib/holidays/option_factory.rb
252
253
  - lib/holidays/use_case/context/between.rb
254
+ - lib/holidays/use_case/context/context_common.rb
253
255
  - lib/holidays/use_case/context/dates_driver_builder.rb
256
+ - lib/holidays/use_case/context/next_holiday.rb
254
257
  - lib/holidays/use_case_factory.rb
255
258
  - lib/holidays/version.rb
256
259
  - test/data/test_custom_govt_holiday_defs.yaml