holidays 6.4.0 → 8.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (168) hide show
  1. checksums.yaml +5 -5
  2. data/.gitmodules +1 -1
  3. data/CHANGELOG.md +80 -0
  4. data/Makefile +17 -4
  5. data/README.md +236 -101
  6. data/Rakefile +1 -1
  7. data/bin/console +0 -0
  8. data/bin/setup +1 -0
  9. data/doc/CONTRIBUTING.md +72 -0
  10. data/{MAINTAINERS.md → doc/MAINTAINERS.md} +5 -6
  11. data/{REFERENCES → doc/REFERENCES} +0 -0
  12. data/holidays.gemspec +8 -9
  13. data/lib/generated_definitions/MANIFEST +12 -4
  14. data/lib/generated_definitions/REGIONS.rb +2 -2
  15. data/lib/generated_definitions/ar.rb +30 -11
  16. data/lib/generated_definitions/at.rb +2 -2
  17. data/lib/generated_definitions/au.rb +26 -8
  18. data/lib/generated_definitions/be_fr.rb +2 -2
  19. data/lib/generated_definitions/be_nl.rb +2 -2
  20. data/lib/generated_definitions/bg.rb +2 -2
  21. data/lib/generated_definitions/br.rb +2 -2
  22. data/lib/generated_definitions/ca.rb +24 -17
  23. data/lib/generated_definitions/ch.rb +16 -4
  24. data/lib/generated_definitions/cl.rb +7 -10
  25. data/lib/generated_definitions/co.rb +121 -0
  26. data/lib/generated_definitions/cr.rb +2 -2
  27. data/lib/generated_definitions/cz.rb +2 -2
  28. data/lib/generated_definitions/de.rb +8 -5
  29. data/lib/generated_definitions/dk.rb +2 -2
  30. data/lib/generated_definitions/{ecb_target.rb → ecbtarget.rb} +10 -10
  31. data/lib/generated_definitions/ee.rb +2 -2
  32. data/lib/generated_definitions/el.rb +2 -2
  33. data/lib/generated_definitions/es.rb +8 -5
  34. data/lib/generated_definitions/europe.rb +114 -29
  35. data/lib/generated_definitions/federalreserve.rb +35 -0
  36. data/lib/generated_definitions/{federal_reserve.rb → federalreservebanks.rb} +15 -14
  37. data/lib/generated_definitions/fedex.rb +2 -2
  38. data/lib/generated_definitions/fi.rb +2 -2
  39. data/lib/generated_definitions/fr.rb +2 -2
  40. data/lib/generated_definitions/gb.rb +15 -8
  41. data/lib/generated_definitions/ge.rb +2 -2
  42. data/lib/generated_definitions/hk.rb +2 -2
  43. data/lib/generated_definitions/hr.rb +10 -8
  44. data/lib/generated_definitions/hu.rb +4 -3
  45. data/lib/generated_definitions/ie.rb +2 -2
  46. data/lib/generated_definitions/is.rb +2 -2
  47. data/lib/generated_definitions/it.rb +16 -7
  48. data/lib/generated_definitions/jp.rb +34 -15
  49. data/lib/generated_definitions/kr.rb +2 -2
  50. data/lib/generated_definitions/kz.rb +38 -0
  51. data/lib/generated_definitions/li.rb +2 -2
  52. data/lib/generated_definitions/lt.rb +2 -2
  53. data/lib/generated_definitions/lu.rb +4 -2
  54. data/lib/generated_definitions/lv.rb +55 -0
  55. data/lib/generated_definitions/ma.rb +2 -2
  56. data/lib/generated_definitions/mt_en.rb +2 -2
  57. data/lib/generated_definitions/mt_mt.rb +2 -2
  58. data/lib/generated_definitions/mx.rb +7 -7
  59. data/lib/generated_definitions/my.rb +2 -2
  60. data/lib/generated_definitions/nerc.rb +2 -2
  61. data/lib/generated_definitions/ng.rb +33 -0
  62. data/lib/generated_definitions/nl.rb +2 -2
  63. data/lib/generated_definitions/no.rb +2 -2
  64. data/lib/generated_definitions/{north_america.rb → northamerica.rb} +33 -26
  65. data/lib/generated_definitions/nyse.rb +3 -2
  66. data/lib/generated_definitions/nz.rb +41 -3
  67. data/lib/generated_definitions/pe.rb +2 -2
  68. data/lib/generated_definitions/ph.rb +2 -2
  69. data/lib/generated_definitions/pl.rb +2 -2
  70. data/lib/generated_definitions/pt.rb +2 -2
  71. data/lib/generated_definitions/ro.rb +6 -3
  72. data/lib/generated_definitions/rs_cyrl.rb +3 -3
  73. data/lib/generated_definitions/rs_la.rb +3 -3
  74. data/lib/generated_definitions/ru.rb +2 -2
  75. data/lib/generated_definitions/scandinavia.rb +2 -2
  76. data/lib/generated_definitions/se.rb +2 -2
  77. data/lib/generated_definitions/sg.rb +2 -2
  78. data/lib/generated_definitions/si.rb +4 -3
  79. data/lib/generated_definitions/sk.rb +2 -2
  80. data/lib/generated_definitions/southamerica.rb +247 -0
  81. data/lib/generated_definitions/th.rb +36 -0
  82. data/lib/generated_definitions/tn.rb +2 -2
  83. data/lib/generated_definitions/tr.rb +7 -5
  84. data/lib/generated_definitions/ua.rb +37 -0
  85. data/lib/generated_definitions/{united_nations.rb → unitednations.rb} +61 -61
  86. data/lib/generated_definitions/ups.rb +2 -2
  87. data/lib/generated_definitions/us.rb +9 -9
  88. data/lib/generated_definitions/ve.rb +2 -2
  89. data/lib/generated_definitions/vi.rb +2 -2
  90. data/lib/generated_definitions/za.rb +3 -3
  91. data/lib/holidays/core_extensions/time.rb +3 -3
  92. data/lib/holidays/definition/context/generator.rb +23 -70
  93. data/lib/holidays/definition/context/load.rb +1 -1
  94. data/lib/holidays/definition/generator/module.rb +54 -0
  95. data/lib/holidays/definition/generator/regions.rb +7 -2
  96. data/lib/holidays/definition/parser/custom_method.rb +2 -2
  97. data/lib/holidays/definition/repository/cache.rb +2 -1
  98. data/lib/holidays/definition/repository/holidays_by_month.rb +9 -1
  99. data/lib/holidays/factory/definition.rb +7 -0
  100. data/lib/holidays/finder/context/between.rb +6 -7
  101. data/lib/holidays/finder/context/dates_driver_builder.rb +5 -11
  102. data/lib/holidays/finder/context/next_holiday.rb +12 -12
  103. data/lib/holidays/finder/context/parse_options.rb +0 -6
  104. data/lib/holidays/finder/context/search.rb +39 -32
  105. data/lib/holidays/finder/rules/year_range.rb +30 -54
  106. data/lib/holidays/version.rb +1 -1
  107. data/lib/holidays.rb +14 -7
  108. data/test/coverage_report.rb +23 -7
  109. data/test/data/test_custom_informal_holidays_defs.yaml +11 -0
  110. data/test/data/test_custom_year_range_holiday_defs.yaml +6 -10
  111. data/test/data/test_multiple_regions_with_conflicts_region_1.yaml +38 -0
  112. data/test/data/test_multiple_regions_with_conflicts_region_2.yaml +38 -0
  113. data/test/defs/test_defs_ar.rb +30 -6
  114. data/test/defs/test_defs_at.rb +5 -3
  115. data/test/defs/test_defs_au.rb +29 -0
  116. data/test/defs/test_defs_be_fr.rb +10 -0
  117. data/test/defs/test_defs_be_nl.rb +10 -0
  118. data/test/defs/test_defs_ca.rb +63 -8
  119. data/test/defs/test_defs_ch.rb +6 -0
  120. data/test/defs/test_defs_co.rb +113 -0
  121. data/test/defs/test_defs_de.rb +7 -1
  122. data/test/defs/{test_defs_ecb_target.rb → test_defs_ecbtarget.rb} +11 -11
  123. data/test/defs/test_defs_es.rb +2 -0
  124. data/test/defs/test_defs_europe.rb +250 -15
  125. data/test/defs/test_defs_federalreserve.rb +119 -0
  126. data/test/defs/test_defs_federalreservebanks.rb +251 -0
  127. data/test/defs/test_defs_gb.rb +42 -0
  128. data/test/defs/test_defs_hr.rb +6 -6
  129. data/test/defs/test_defs_hu.rb +12 -4
  130. data/test/defs/test_defs_it.rb +20 -0
  131. data/test/defs/test_defs_jp.rb +30 -2
  132. data/test/defs/test_defs_kz.rb +39 -0
  133. data/test/defs/test_defs_lu.rb +6 -0
  134. data/test/defs/test_defs_lv.rb +96 -0
  135. data/test/defs/test_defs_mx.rb +3 -1
  136. data/test/defs/test_defs_ng.rb +29 -0
  137. data/test/defs/{test_defs_north_america.rb → test_defs_northamerica.rb} +77 -20
  138. data/test/defs/test_defs_nyse.rb +7 -0
  139. data/test/defs/test_defs_nz.rb +4 -0
  140. data/test/defs/test_defs_ro.rb +14 -0
  141. data/test/defs/test_defs_rs_cyrl.rb +1 -1
  142. data/test/defs/test_defs_rs_la.rb +1 -1
  143. data/test/defs/test_defs_southamerica.rb +323 -0
  144. data/test/defs/test_defs_th.rb +33 -0
  145. data/test/defs/test_defs_tr.rb +7 -0
  146. data/test/defs/test_defs_ua.rb +41 -0
  147. data/test/defs/{test_defs_united_nations.rb → test_defs_unitednations.rb} +3 -3
  148. data/test/defs/test_defs_us.rb +11 -11
  149. data/test/holidays/core_extensions/test_date.rb +3 -2
  150. data/test/holidays/definition/context/test_generator.rb +17 -20
  151. data/test/holidays/definition/context/test_load.rb +3 -3
  152. data/test/holidays/definition/generator/test_module.rb +268 -0
  153. data/test/holidays/definition/parser/test_custom_method.rb +4 -4
  154. data/test/holidays/definition/repository/test_holidays_by_month.rb +121 -1
  155. data/test/holidays/finder/context/test_parse_options.rb +0 -10
  156. data/test/holidays/finder/rules/test_year_range.rb +43 -47
  157. data/test/integration/test_any_holidays_during_work_week.rb +90 -0
  158. data/test/integration/test_available_regions.rb +1 -1
  159. data/test/integration/test_custom_informal_holidays.rb +15 -0
  160. data/test/integration/test_custom_year_range_holidays.rb +0 -7
  161. data/test/integration/test_holidays.rb +4 -56
  162. data/test/integration/test_holidays_between.rb +11 -1
  163. data/test/integration/test_multiple_regions.rb +54 -6
  164. data/test/integration/test_multiple_regions_with_conflict.rb +29 -0
  165. data/test/integration/test_nonstandard_regions.rb +25 -0
  166. metadata +79 -53
  167. data/CONTRIBUTING.md +0 -51
  168. data/test/defs/test_defs_federal_reserve.rb +0 -111
@@ -2,17 +2,17 @@
2
2
  module Holidays
3
3
  # This file is generated by the Ruby Holidays gem.
4
4
  #
5
- # Definitions loaded: definitions/us.yaml, definitions/north_america_informal.yaml
5
+ # Definitions loaded: definitions/us.yaml, definitions/northamericainformal.yaml
6
6
  #
7
7
  # All the definitions are available at https://github.com/holidays/holidays
8
8
  module US # :nodoc:
9
9
  def self.defined_regions
10
- [:us_fl, :us_la, :us, :us_ct, :us_de, :us_gu, :us_hi, :us_in, :us_ky, :us_nj, :us_nc, :us_nd, :us_pr, :us_tn, :us_ms, :us_id, :us_ar, :us_tx, :us_dc, :us_md, :us_va, :us_il, :us_vt, :us_ak, :us_ca, :us_me, :us_ma, :us_al, :us_ga, :us_ne, :us_mo, :us_sc, :us_wv, :us_vi, :us_ut, :us_ri, :us_az, :us_co, :us_mt, :us_nm, :us_ny, :us_oh, :us_pa, :us_mi, :us_mn, :us_nv, :us_or, :us_sd, :us_wa, :us_wi, :us_wy, :us_ia, :us_ks, :us_nh, :us_ok, :ca]
10
+ [:us_fl, :us_la, :us, :us_ct, :us_de, :us_gu, :us_hi, :us_in, :us_ky, :us_nj, :us_nc, :us_nd, :us_pr, :us_tn, :us_ms, :us_id, :us_ar, :us_tx, :us_dc, :us_md, :us_va, :us_vt, :us_ak, :us_ca, :us_me, :us_ma, :us_al, :us_ga, :us_ne, :us_mo, :us_sc, :us_wv, :us_vi, :us_ut, :us_ri, :us_az, :us_co, :us_il, :us_mt, :us_nm, :us_ny, :us_oh, :us_pa, :us_mi, :us_mn, :us_nv, :us_or, :us_sd, :us_wa, :us_wi, :us_wy, :us_ia, :us_ks, :us_nh, :us_ok, :ca]
11
11
  end
12
12
 
13
13
  def self.holidays_by_month
14
14
  {
15
- 0 => [{:function => "easter(year)", :function_arguments => [:year], :function_modifier => -47, :name => "Shrove Tuesday", :regions => [:us_fl]},
15
+ 0 => [{:function => "easter(year)", :function_arguments => [:year], :function_modifier => -47, :name => "Shrove Tuesday", :regions => [:us_fl]},
16
16
  {:function => "easter(year)", :function_arguments => [:year], :function_modifier => -47, :name => "Mardi Gras Day", :regions => [:us_la]},
17
17
  {:function => "easter(year)", :function_arguments => [:year], :function_modifier => -2, :type => :informal, :name => "Good Friday", :regions => [:us]},
18
18
  {:function => "easter(year)", :function_arguments => [:year], :function_modifier => -2, :name => "Good Friday", :regions => [:us_ct, :us_de, :us_gu, :us_hi, :us_in, :us_ky, :us_la, :us_nj, :us_nc, :us_nd, :us_pr, :us_tn]},
@@ -28,14 +28,13 @@ module Holidays
28
28
  2 => [{:wday => 1, :week => 3, :name => "Presidents' Day", :regions => [:us]},
29
29
  {:mday => 2, :type => :informal, :name => "Groundhog Day", :regions => [:us, :ca]},
30
30
  {:mday => 14, :type => :informal, :name => "Valentine's Day", :regions => [:us, :ca]}],
31
- 3 => [{:wday => 1, :week => 1, :name => "Casimir Pulaski Day", :regions => [:us_il]},
32
- {:wday => 2, :week => 1, :name => "Town Meeting Day", :regions => [:us_vt]},
31
+ 3 => [{:wday => 2, :week => 1, :name => "Town Meeting Day", :regions => [:us_vt]},
33
32
  {:mday => 2, :name => "Texas Independence Day", :regions => [:us_tx]},
34
33
  {:mday => 26, :observed => "to_weekday_if_weekend(date)", :observed_arguments => [:date], :name => "Prince Jonah Kuhio Kalanianaole Day", :regions => [:us_hi]},
35
34
  {:wday => 1, :week => -1, :name => "Seward's Day", :regions => [:us_ak]},
36
35
  {:mday => 31, :name => "César Chávez Day", :regions => [:us_ca]},
37
36
  {:mday => 17, :type => :informal, :name => "St. Patrick's Day", :regions => [:us, :ca]}],
38
- 4 => [{:mday => 16, :observed => "to_weekday_if_weekend(date)", :observed_arguments => [:date], :name => "Emancipation Day", :regions => [:us_dc, :us_ca]},
37
+ 4 => [{:mday => 16, :observed => "to_weekday_if_weekend(date)", :observed_arguments => [:date], :name => "Emancipation Day", :regions => [:us_dc]},
39
38
  {:wday => 1, :week => 3, :name => "Patriots' Day", :regions => [:us_me, :us_ma]},
40
39
  {:mday => 21, :name => "San Jacinto Day", :regions => [:us_tx]},
41
40
  {:wday => 1, :week => -1, :name => "Confederate Memorial Day", :regions => [:us_al, :us_ms]},
@@ -52,6 +51,7 @@ module Holidays
52
51
  6 => [{:wday => 1, :week => 1, :name => "Jefferson Davis' Birthday", :regions => [:us_al]},
53
52
  {:mday => 3, :name => "Birthday of Jefferson Davis", :regions => [:us_fl]},
54
53
  {:mday => 11, :observed => "to_weekday_if_weekend(date)", :observed_arguments => [:date], :name => "King Kamehameha I Day", :regions => [:us_hi]},
54
+ {:mday => 19, :year_ranges => { :from => 2021 },:observed => "to_weekday_if_weekend(date)", :observed_arguments => [:date], :name => "Juneteenth National Independence Day", :regions => [:us]},
55
55
  {:mday => 19, :name => "Emancipation Day in Texas", :regions => [:us_tx]},
56
56
  {:mday => 20, :observed => "to_weekday_if_weekend(date)", :observed_arguments => [:date], :name => "West Virginia Day", :regions => [:us_wv]},
57
57
  {:wday => 0, :week => 3, :type => :informal, :name => "Father's Day", :regions => [:us, :ca]}],
@@ -71,7 +71,7 @@ module Holidays
71
71
  {:mday => 18, :name => "Alaska Day", :regions => [:us_ak]},
72
72
  {:wday => 5, :week => -1, :name => "Nevada Day", :regions => [:us_nv]},
73
73
  {:mday => 31, :type => :informal, :name => "Halloween", :regions => [:us, :ca]}],
74
- 11 => [{:function => "election_day(year)", :function_arguments => [:year], :name => "Election Day", :regions => [:us_de, :us_hi, :us_il, :us_in, :us_mt, :us_nj, :us_ny, :us_pa, :us_ri]},
74
+ 11 => [{:function => "election_day(year)", :function_arguments => [:year], :name => "Election Day", :regions => [:us_de, :us_hi, :us_in, :us_mt, :us_nj, :us_ny, :us_pa, :us_ri]},
75
75
  {:mday => 11, :observed => "to_weekday_if_weekend(date)", :observed_arguments => [:date], :name => "Veterans Day", :regions => [:us]},
76
76
  {:wday => 4, :week => 4, :name => "Thanksgiving", :regions => [:us]},
77
77
  {:function => "day_after_thanksgiving(year)", :function_arguments => [:year], :name => "Family Day", :regions => [:us_nv]},
@@ -82,7 +82,7 @@ module Holidays
82
82
  {:function => "day_after_thanksgiving(year)", :function_arguments => [:year], :name => "Day after Thanksgiving (Black Friday)", :regions => [:us_ca, :us_de, :us_fl, :us_ia, :us_il, :us_ks, :us_ky, :us_me, :us_mi, :us_mn, :us_ms, :us_ne, :us_nh, :us_nc, :us_pa, :us_sc, :us_ok, :us_tn, :us_tx, :us_va, :us_wa, :us_wv]}],
83
83
  12 => [{:mday => 24, :name => "Christmas Eve", :regions => [:us_ar, :us_mi, :us_nc, :us_sc, :us_tx, :us_wi]},
84
84
  {:mday => 24, :function => "christmas_eve_holiday(date)", :function_arguments => [:date], :name => "Christmas Eve (Holiday)", :regions => [:us_mi, :us_sc, :us_va]},
85
- {:mday => 25, :observed => "to_monday_if_weekend(date)", :observed_arguments => [:date], :name => "Christmas Day", :regions => [:us]},
85
+ {:mday => 25, :observed => "to_weekday_if_weekend(date)", :observed_arguments => [:date], :name => "Christmas Day", :regions => [:us]},
86
86
  {:mday => 26, :name => "Day after Christmas", :regions => [:us_ar, :us_nc, :us_ok, :us_sc, :us_tn, :us_tx]},
87
87
  {:mday => 31, :name => "New Year's Eve", :regions => [:us_mi, :us_wi]}]
88
88
  }
@@ -90,7 +90,7 @@ module Holidays
90
90
 
91
91
  def self.custom_methods
92
92
  {
93
- "christmas_eve_holiday(date)" => Proc.new { |date|
93
+ "christmas_eve_holiday(date)" => Proc.new { |date|
94
94
  beginning_of_month = Date.civil(date.year, date.month, 1)
95
95
  (date.saturday? || date.sunday?) ? date.downto(beginning_of_month).find {|d| d if d.wday == 5} : date
96
96
  },
@@ -12,7 +12,7 @@ module Holidays
12
12
 
13
13
  def self.holidays_by_month
14
14
  {
15
- 0 => [{:function => "easter(year)", :function_arguments => [:year], :function_modifier => -48, :name => "Lunes Carnaval", :regions => [:ve]},
15
+ 0 => [{:function => "easter(year)", :function_arguments => [:year], :function_modifier => -48, :name => "Lunes Carnaval", :regions => [:ve]},
16
16
  {:function => "easter(year)", :function_arguments => [:year], :function_modifier => -47, :name => "Martes Carnaval", :regions => [:ve]},
17
17
  {:function => "easter(year)", :function_arguments => [:year], :function_modifier => -3, :name => "Jueves Santo", :regions => [:ve]},
18
18
  {:function => "easter(year)", :function_arguments => [:year], :function_modifier => -2, :name => "Viernes Santo", :regions => [:ve]}],
@@ -29,7 +29,7 @@ module Holidays
29
29
 
30
30
  def self.custom_methods
31
31
  {
32
-
32
+
33
33
  }
34
34
  end
35
35
  end
@@ -12,7 +12,7 @@ module Holidays
12
12
 
13
13
  def self.holidays_by_month
14
14
  {
15
- 1 => [{:mday => 1, :name => "Tết dương lịch", :regions => [:vi]}],
15
+ 1 => [{:mday => 1, :name => "Tết dương lịch", :regions => [:vi]}],
16
16
  3 => [{:mday => 10, :function => "lunar_to_solar(year, month, day, region)", :function_arguments => [:year, :month, :day, :region], :name => "Giỗ tổ Hùng Vương", :regions => [:vi]}],
17
17
  4 => [{:mday => 30, :name => "Ngày Giải phóng miền Nam, thống nhất đất nước", :regions => [:vi]}],
18
18
  5 => [{:mday => 1, :name => "Ngày Quốc tế Lao động", :regions => [:vi]}],
@@ -22,7 +22,7 @@ module Holidays
22
22
 
23
23
  def self.custom_methods
24
24
  {
25
-
25
+
26
26
  }
27
27
  end
28
28
  end
@@ -12,7 +12,7 @@ module Holidays
12
12
 
13
13
  def self.holidays_by_month
14
14
  {
15
- 0 => [{:function => "easter(year)", :function_arguments => [:year], :function_modifier => -2, :name => "Good Friday", :regions => [:za]},
15
+ 0 => [{:function => "easter(year)", :function_arguments => [:year], :function_modifier => -2, :name => "Good Friday", :regions => [:za]},
16
16
  {:function => "easter(year)", :function_arguments => [:year], :function_modifier => 1, :name => "Family Day", :regions => [:za]}],
17
17
  1 => [{:mday => 1, :observed => "to_monday_if_sunday(date)", :observed_arguments => [:date], :name => "New Year's Day", :regions => [:za]}],
18
18
  3 => [{:mday => 21, :observed => "to_monday_if_sunday(date)", :observed_arguments => [:date], :name => "Human Rights Day", :regions => [:za]}],
@@ -23,13 +23,13 @@ module Holidays
23
23
  9 => [{:mday => 24, :observed => "to_monday_if_sunday(date)", :observed_arguments => [:date], :name => "Heritage Day", :regions => [:za]}],
24
24
  12 => [{:mday => 16, :observed => "to_monday_if_sunday(date)", :observed_arguments => [:date], :name => "Day of Reconciliation", :regions => [:za]},
25
25
  {:mday => 25, :observed => "to_monday_if_sunday(date)", :observed_arguments => [:date], :name => "Christmas Day", :regions => [:za]},
26
- {:mday => 26, :observed => "to_weekday_if_boxing_weekend(date)", :observed_arguments => [:date], :name => "Day of Goodwill", :regions => [:za]}]
26
+ {:mday => 26, :observed => "to_monday_if_sunday(date)", :observed_arguments => [:date], :name => "Day of Goodwill", :regions => [:za]}]
27
27
  }
28
28
  end
29
29
 
30
30
  def self.custom_methods
31
31
  {
32
-
32
+
33
33
  }
34
34
  end
35
35
  end
@@ -4,7 +4,7 @@ module Holidays
4
4
  def self.included(base)
5
5
  base.extend ClassMethods
6
6
  end
7
-
7
+
8
8
  module ClassMethods
9
9
  COMMON_YEAR_DAYS_IN_MONTH = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
10
10
 
@@ -17,7 +17,7 @@ module Holidays
17
17
  COMMON_YEAR_DAYS_IN_MONTH[month]
18
18
  end
19
19
  end
20
- end
20
+ end
21
21
  end
22
22
  end
23
- end
23
+ end
@@ -11,12 +11,13 @@ module Holidays
11
11
  module Definition
12
12
  module Context
13
13
  class Generator
14
- def initialize(custom_method_parser, custom_method_source_decorator, custom_methods_repository, test_parser, test_source_generator)
14
+ def initialize(custom_method_parser, custom_method_source_decorator, custom_methods_repository, test_parser, test_source_generator, module_source_generator)
15
15
  @custom_method_parser = custom_method_parser
16
16
  @custom_method_source_decorator = custom_method_source_decorator
17
17
  @custom_methods_repository = custom_methods_repository
18
18
  @test_parser = test_parser
19
19
  @test_source_generator = test_source_generator
20
+ @module_source_generator = module_source_generator
20
21
  end
21
22
 
22
23
  def parse_definition_files(files)
@@ -66,7 +67,7 @@ module Holidays
66
67
  custom_method_string << @custom_method_source_decorator.call(code) + ",\n\n"
67
68
  end
68
69
 
69
- module_src = generate_module_src(module_name, files, regions, month_strings, custom_method_string)
70
+ module_src = @module_source_generator.call(module_name, files, regions, month_strings, custom_method_string)
70
71
  test_src = @test_source_generator.call(module_name, files, tests)
71
72
 
72
73
  return module_src, test_src || ''
@@ -86,16 +87,27 @@ module Holidays
86
87
  rule = {}
87
88
 
88
89
  definition.each do |key, val|
90
+ # Ruby 2.4 doesn't have the `transform_keys` method. Once we drop 2.4 support we can
91
+ # use `val.transform_keys!(&:to_sym) if val.is_a?(Hash)` instead of this `if` statement.
92
+ if val.is_a?(Hash)
93
+ val = val.keys.each_with_object({}) do |k, result|
94
+ result[k.to_sym] = val[k]
95
+ end
96
+ end
97
+
89
98
  rule[key.to_sym] = val
90
99
  end
91
100
 
92
- rule[:regions] = rule[:regions].collect { |r| r.to_sym }
93
- regions << rule[:regions]
101
+ if rule[:year_ranges] && rule[:year_ranges].key?(:between)
102
+ start_year = rule[:year_ranges][:between]["start"].to_i
103
+ end_year = rule[:year_ranges][:between]["end"].to_i
94
104
 
95
- if rule[:year_ranges]
96
- rule[:year_ranges] = clean_year_ranges(rule[:year_ranges])
105
+ rule[:year_ranges][:between] = Range.new(start_year, end_year)
97
106
  end
98
107
 
108
+ rule[:regions] = rule[:regions].collect { |r| r.to_sym }
109
+ regions << rule[:regions]
110
+
99
111
  exists = false
100
112
  rules_by_month[month].each do |ex|
101
113
  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] and ex[:year_ranges] == rule[:year_ranges]
@@ -120,23 +132,6 @@ module Holidays
120
132
  [regions, rules_by_month]
121
133
  end
122
134
 
123
- # In this case we end up parsing a range as "2006..2008" a string. This is codifying
124
- # what we already do...today we parse as a string but when writing out to our final
125
- # generated files it comes out as a range that Ruby interprets. This just puts it in stone
126
- # what we want to do.
127
- def clean_year_ranges(year_ranges)
128
- year_ranges.collect do |year_range|
129
- if year_range["between"]
130
- range = year_range["between"]
131
- if range.is_a?(String)
132
- year_range["between"] = Range.new(*range.split("..").map(&:to_i))
133
- end
134
- end
135
-
136
- year_range
137
- end
138
- end
139
-
140
135
  #FIXME This should really be split out and tested with its own unit tests.
141
136
  def generate_month_definition_strings(rules_by_month, parsed_custom_methods)
142
137
  month_strings = []
@@ -169,19 +164,11 @@ module Holidays
169
164
  string << ":wday => #{rule[:wday]}, :week => #{rule[:week]}, "
170
165
  end
171
166
 
172
- #FIXME I think this should be split out into its own file.
173
- if rule[:year_ranges] && rule[:year_ranges].kind_of?(Array)
174
- year_string = " :year_ranges => ["
175
- len = rule[:year_ranges].length
176
- rule[:year_ranges].each_with_index do |year,index|
177
- year_string << "{:#{year.keys.first} => #{year.values.first}}"
178
- if len == index + 1
179
- year_string << "],"
180
- else
181
- year_string << ","
182
- end
183
- end
184
- string << year_string
167
+ if rule[:year_ranges] && rule[:year_ranges].is_a?(Hash)
168
+ selector = rule[:year_ranges].keys.first
169
+ value = rule[:year_ranges][selector]
170
+
171
+ string << ":year_ranges => { :#{selector} => #{value} },"
185
172
  end
186
173
 
187
174
  if rule[:observed]
@@ -216,40 +203,6 @@ module Holidays
216
203
  method.arguments.collect { |arg| arg.to_sym }
217
204
  end
218
205
  end
219
-
220
- def generate_module_src(module_name, files, regions, month_strings, custom_methods)
221
- module_src = ""
222
-
223
- module_src =<<-EOM
224
- # encoding: utf-8
225
- module Holidays
226
- # This file is generated by the Ruby Holidays gem.
227
- #
228
- # Definitions loaded: #{files.join(', ')}
229
- #
230
- # All the definitions are available at https://github.com/holidays/holidays
231
- module #{module_name.to_s.upcase} # :nodoc:
232
- def self.defined_regions
233
- [:#{regions.join(', :')}]
234
- end
235
-
236
- def self.holidays_by_month
237
- {
238
- #{month_strings.join(",\n")}
239
- }
240
- end
241
-
242
- def self.custom_methods
243
- {
244
- #{custom_methods}
245
- }
246
- end
247
- end
248
- end
249
- EOM
250
-
251
- return module_src
252
- end
253
206
  end
254
207
  end
255
208
  end
@@ -14,7 +14,7 @@ module Holidays
14
14
  target_region_module = Module.const_get("Holidays").const_get(region.upcase)
15
15
 
16
16
  @definition_merger.call(
17
- target_region_module.defined_regions,
17
+ region,
18
18
  target_region_module.holidays_by_month,
19
19
  target_region_module.custom_methods,
20
20
  )
@@ -0,0 +1,54 @@
1
+ require 'holidays/errors'
2
+
3
+ module Holidays
4
+ module Definition
5
+ module Generator
6
+ class Module
7
+ def call(module_name, files, regions, month_strings, custom_methods)
8
+ raise ArgumentError.new("module name cannot be nil") if module_name.nil?
9
+ raise ArgumentError.new("module name cannot be blank") if module_name.empty?
10
+
11
+ raise ArgumentError.new("files cannot be nil") if files.nil?
12
+ raise ArgumentError.new("files cannot be empty") if files.empty?
13
+ raise ArgumentError.new("files must all be strings") unless files.all? { |f| f.is_a?(String) }
14
+
15
+ raise ArgumentError.new("regions cannot be nil") if regions.nil?
16
+ raise ArgumentError.new("regions cannot be empty") if regions.empty?
17
+
18
+ raise ArgumentError.new("month strings cannot be nil") if month_strings.nil?
19
+ raise ArgumentError.new("month strings cannot be empty") if month_strings.empty?
20
+
21
+ module_src =<<-EOM
22
+ # encoding: utf-8
23
+ module Holidays
24
+ # This file is generated by the Ruby Holidays gem.
25
+ #
26
+ # Definitions loaded: #{files.join(', ')}
27
+ #
28
+ # All the definitions are available at https://github.com/holidays/holidays
29
+ module #{module_name.to_s.upcase} # :nodoc:
30
+ def self.defined_regions
31
+ [:#{regions.join(', :')}]
32
+ end
33
+
34
+ def self.holidays_by_month
35
+ {
36
+ #{month_strings.join(",\n")}
37
+ }
38
+ end
39
+
40
+ def self.custom_methods
41
+ {
42
+ #{custom_methods}
43
+ }
44
+ end
45
+ end
46
+ end
47
+ EOM
48
+
49
+ module_src
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -2,6 +2,10 @@ module Holidays
2
2
  module Definition
3
3
  module Generator
4
4
  class Regions
5
+ # The "ca", "mx", and "us" holiday definitions include the "northamericainformal"
6
+ # holiday definitions, but that does not make these countries subregions of one another.
7
+ NORTH_AMERICA_REGIONS = %i[ca mx us].freeze
8
+
5
9
  def call(regions)
6
10
  validate!(regions)
7
11
 
@@ -37,8 +41,9 @@ EOF
37
41
  lookup = {}
38
42
 
39
43
  regions.each do |region, subregions|
40
- subregions.each do |s|
41
- lookup[s] = region unless lookup.has_key?(s)
44
+ subregions.each do |subregion|
45
+ parent_region = NORTH_AMERICA_REGIONS.include?(subregion) ? subregion : region
46
+ lookup[subregion] = parent_region unless lookup.has_key?(subregion)
42
47
  end
43
48
  end
44
49
 
@@ -21,7 +21,7 @@ module Holidays
21
21
  custom_methods[method_key(name, arguments)] = Entity::CustomMethod.new({
22
22
  name: name,
23
23
  arguments: arguments,
24
- source: pieces["source"],
24
+ source: pieces["ruby"],
25
25
  })
26
26
  end
27
27
 
@@ -36,7 +36,7 @@ module Holidays
36
36
  {
37
37
  :name => name,
38
38
  :arguments => pieces["arguments"],
39
- :source => pieces["source"]
39
+ :source => pieces["ruby"]
40
40
  }
41
41
  )
42
42
  end
@@ -8,6 +8,7 @@ module Holidays
8
8
 
9
9
  def cache_between(start_date, end_date, cache_data, options)
10
10
  raise ArgumentError unless cache_data
11
+ raise ArgumentError unless start_date && end_date
11
12
 
12
13
  @cache_range[options] = start_date..end_date
13
14
  @cache[options] = cache_data.group_by { |holiday| holiday[:date] }
@@ -15,7 +16,7 @@ module Holidays
15
16
 
16
17
  def find(start_date, end_date, options)
17
18
  return nil unless in_cache_range?(start_date, end_date, options)
18
-
19
+
19
20
  if start_date == end_date
20
21
  @cache[options].fetch(start_date, [])
21
22
  else
@@ -41,7 +41,15 @@ module Holidays
41
41
  private
42
42
 
43
43
  def definition_exists?(existing_def, target_def)
44
- existing_def[:name] == target_def[:name] && existing_def[:wday] == target_def[:wday] && existing_def[:mday] == target_def[:mday] && existing_def[:week] == target_def[:week] && existing_def[:function] == target_def[:function] && existing_def[:type] == target_def[:type] && existing_def[:observed] == target_def[:observed] && existing_def[:year_ranges] == target_def[:year_ranges]
44
+ existing_def[:name] == target_def[:name] &&
45
+ existing_def[:wday] == target_def[:wday] &&
46
+ existing_def[:mday] == target_def[:mday] &&
47
+ existing_def[:week] == target_def[:week] &&
48
+ existing_def[:function] == target_def[:function] &&
49
+ existing_def[:function_modifier] == target_def[:function_modifier] &&
50
+ existing_def[:type] == target_def[:type] &&
51
+ existing_def[:observed] == target_def[:observed] &&
52
+ existing_def[:year_ranges] == target_def[:year_ranges]
45
53
  end
46
54
  end
47
55
  end
@@ -5,6 +5,7 @@ require 'holidays/definition/context/load'
5
5
  require 'holidays/definition/decorator/custom_method_proc'
6
6
  require 'holidays/definition/decorator/custom_method_source'
7
7
  require 'holidays/definition/decorator/test'
8
+ require 'holidays/definition/generator/module'
8
9
  require 'holidays/definition/generator/regions'
9
10
  require 'holidays/definition/generator/test'
10
11
  require 'holidays/definition/parser/custom_method'
@@ -29,6 +30,7 @@ module Holidays
29
30
  custom_methods_repository,
30
31
  test_parser,
31
32
  test_generator,
33
+ module_generator,
32
34
  )
33
35
  end
34
36
 
@@ -39,6 +41,7 @@ module Holidays
39
41
  custom_methods_repository,
40
42
  test_parser,
41
43
  test_generator,
44
+ module_generator,
42
45
  )
43
46
  end
44
47
 
@@ -115,6 +118,10 @@ module Holidays
115
118
  )
116
119
  end
117
120
 
121
+ def module_generator
122
+ Holidays::Definition::Generator::Module.new
123
+ end
124
+
118
125
  def test_generator
119
126
  Holidays::Definition::Generator::Test.new(
120
127
  test_decorator,
@@ -14,15 +14,14 @@ module Holidays
14
14
  regions, observed, informal = @options_parser.call(options)
15
15
  dates_driver = @dates_driver_builder.call(start_date, end_date)
16
16
 
17
- holidays = []
18
-
19
17
  #FIXME Why are we calling the options_parser to convert the observed/informal
20
18
  # symbols to bool and then...converting them back? O_o
21
19
  opts = gather_options(observed, informal)
22
20
 
23
- holidays = @definition_search.call(dates_driver, regions, opts)
24
- holidays = holidays.select{|holiday|holiday[:date].between?(start_date, end_date)}
25
- holidays.sort{|a, b| a[:date] <=> b[:date] }
21
+ @definition_search
22
+ .call(dates_driver, regions, opts)
23
+ .select { |holiday| holiday[:date].between?(start_date, end_date) }
24
+ .sort_by { |a| a[:date] }
26
25
  end
27
26
 
28
27
  private
@@ -35,8 +34,8 @@ module Holidays
35
34
  def gather_options(observed, informal)
36
35
  opts = []
37
36
 
38
- opts << :observed if observed == true
39
- opts << :informal if informal == true
37
+ opts << :observed if observed
38
+ opts << :informal if informal
40
39
 
41
40
  opts
42
41
  end
@@ -11,20 +11,14 @@ module Holidays
11
11
  def call(start_date, end_date)
12
12
  dates_driver = {}
13
13
 
14
- (start_date..end_date).map{|current_date|build(dates_driver, current_date)}
14
+ (start_date..end_date).each do |date|
15
+ dates_driver[date.year] = [] unless dates_driver[date.year]
16
+ dates_driver[date.year] << date.month
17
+ dates_driver = add_border_months(date, dates_driver)
18
+ end
15
19
  clean(dates_driver)
16
20
  end
17
21
 
18
- #FIXME Why is the date_driver set to optional as the first param? That's
19
- # just plain wrong...
20
- def build(dates_driver = {}, date)
21
- raise ArgumentError unless dates_driver
22
- raise ArgumentError unless date
23
- dates_driver[date.year] = [] unless dates_driver[date.year]
24
- dates_driver[date.year] << date.month
25
- dates_driver = add_border_months(date, dates_driver)
26
- end
27
-
28
22
  private
29
23
 
30
24
  # As part of https://github.com/holidays/holidays/issues/146 I am returning
@@ -14,7 +14,6 @@ module Holidays
14
14
  regions, observed, informal = @options_parser.call(options)
15
15
 
16
16
  holidays = []
17
- ret_holidays = []
18
17
  opts = gather_options(observed, informal)
19
18
 
20
19
  # This could be smarter but I don't have any evidence that just checking for
@@ -22,17 +21,18 @@ module Holidays
22
21
  # smarter here to check in smaller increments.
23
22
  dates_driver = @dates_driver_builder.call(from_date, from_date >> 12)
24
23
 
25
- ret_holidays = @definition_search.call(dates_driver, regions, opts)
26
-
27
- ret_holidays.sort{|a, b| a[:date] <=> b[:date] }.each do |holiday|
28
- if holiday[:date] >= from_date
29
- holidays << holiday
30
- holidays_count -= 1
31
- break if holidays_count == 0
24
+ @definition_search
25
+ .call(dates_driver, regions, opts)
26
+ .sort_by { |a| a[:date] }
27
+ .each do |holiday|
28
+ if holiday[:date] >= from_date
29
+ holidays << holiday
30
+ holidays_count -= 1
31
+ break if holidays_count == 0
32
+ end
32
33
  end
33
- end
34
34
 
35
- holidays.sort{|a, b| a[:date] <=> b[:date] }
35
+ holidays.sort_by { |a| a[:date] }
36
36
  end
37
37
 
38
38
  private
@@ -46,8 +46,8 @@ module Holidays
46
46
  def gather_options(observed, informal)
47
47
  opts = []
48
48
 
49
- opts << :observed if observed == true
50
- opts << :informal if informal == true
49
+ opts << :observed if observed
50
+ opts << :informal if informal
51
51
 
52
52
  opts
53
53
  end
@@ -42,12 +42,6 @@ module Holidays
42
42
 
43
43
  loaded_regions = []
44
44
 
45
- #FIXME I don't know what this means or why we have it! I'm reluctant to remove it
46
- # at this time without understanding more. -PP 2017/3/29
47
- #
48
- # special case for north_america/US cross-linking
49
- load_region!(:north_america) if regions.include?(:us)
50
-
51
45
  if regions.include?(:any)
52
46
  @regions_repo.all_generated.each do |r|
53
47
  if @regions_repo.loaded?(r)