revised_holidays 9.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (382) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ruby.yml +25 -0
  3. data/CHANGELOG.md +446 -0
  4. data/CODE_OF_CONDUCT.md +74 -0
  5. data/Gemfile +3 -0
  6. data/LICENSE +21 -0
  7. data/Makefile +45 -0
  8. data/README.md +337 -0
  9. data/Rakefile +109 -0
  10. data/bin/console +7 -0
  11. data/bin/setup +6 -0
  12. data/definitions/.github/workflows/ruby.yml +25 -0
  13. data/definitions/.gitignore +5 -0
  14. data/definitions/CHANGELOG.md +352 -0
  15. data/definitions/Gemfile +6 -0
  16. data/definitions/LICENSE +21 -0
  17. data/definitions/METHODS.yml +26 -0
  18. data/definitions/Makefile +9 -0
  19. data/definitions/README.md +22 -0
  20. data/definitions/ar.yaml +268 -0
  21. data/definitions/at.yaml +116 -0
  22. data/definitions/au.yaml +907 -0
  23. data/definitions/be_fr.yaml +153 -0
  24. data/definitions/be_nl.yaml +153 -0
  25. data/definitions/bg.yaml +186 -0
  26. data/definitions/br.yaml +178 -0
  27. data/definitions/ca.yaml +969 -0
  28. data/definitions/ch.yaml +277 -0
  29. data/definitions/cl.yaml +294 -0
  30. data/definitions/co.yaml +437 -0
  31. data/definitions/cr.yaml +100 -0
  32. data/definitions/cz.yaml +137 -0
  33. data/definitions/de.yaml +401 -0
  34. data/definitions/dk.yaml +220 -0
  35. data/definitions/doc/CONTRIBUTING.md +44 -0
  36. data/definitions/doc/MAINTAINERS.md +39 -0
  37. data/definitions/doc/SYNTAX.md +435 -0
  38. data/definitions/doc/architecture/README.md +15 -0
  39. data/definitions/doc/architecture/adr-001.md +86 -0
  40. data/definitions/doc/architecture/adr-002.md +64 -0
  41. data/definitions/ecbtarget.yaml +74 -0
  42. data/definitions/ee.yaml +123 -0
  43. data/definitions/es.yaml +495 -0
  44. data/definitions/federalreserve.yaml +389 -0
  45. data/definitions/federalreservebanks.yaml +821 -0
  46. data/definitions/fedex.yaml +102 -0
  47. data/definitions/fi.yaml +234 -0
  48. data/definitions/fr.yaml +157 -0
  49. data/definitions/gb.yaml +565 -0
  50. data/definitions/ge.yaml +158 -0
  51. data/definitions/gr.yaml +158 -0
  52. data/definitions/hk.yaml +287 -0
  53. data/definitions/hr.yaml +171 -0
  54. data/definitions/hu.yaml +156 -0
  55. data/definitions/ie.yaml +172 -0
  56. data/definitions/index.yaml +80 -0
  57. data/definitions/is.yaml +247 -0
  58. data/definitions/it.yaml +246 -0
  59. data/definitions/jp.yaml +761 -0
  60. data/definitions/ke.yaml +107 -0
  61. data/definitions/kr.yaml +166 -0
  62. data/definitions/kz.yaml +128 -0
  63. data/definitions/li.yaml +154 -0
  64. data/definitions/lib/validation/custom_method_validator.rb +38 -0
  65. data/definitions/lib/validation/definition_validator.rb +35 -0
  66. data/definitions/lib/validation/error.rb +11 -0
  67. data/definitions/lib/validation/month_validator.rb +58 -0
  68. data/definitions/lib/validation/run.rb +66 -0
  69. data/definitions/lib/validation/test_validator.rb +83 -0
  70. data/definitions/lt.yaml +198 -0
  71. data/definitions/lu.yaml +123 -0
  72. data/definitions/lv.yaml +229 -0
  73. data/definitions/ma.yaml +96 -0
  74. data/definitions/mt_en.yaml +131 -0
  75. data/definitions/mt_mt.yaml +131 -0
  76. data/definitions/mx.yaml +160 -0
  77. data/definitions/my.yaml +79 -0
  78. data/definitions/nerc.yaml +94 -0
  79. data/definitions/ng.yaml +97 -0
  80. data/definitions/nl.yaml +127 -0
  81. data/definitions/no.yaml +169 -0
  82. data/definitions/northamericainformal.yaml +105 -0
  83. data/definitions/nyse.yaml +137 -0
  84. data/definitions/nz.yaml +346 -0
  85. data/definitions/pe.yaml +208 -0
  86. data/definitions/ph.yaml +130 -0
  87. data/definitions/pl.yaml +796 -0
  88. data/definitions/pt.yaml +187 -0
  89. data/definitions/ro.yaml +240 -0
  90. data/definitions/rs_cyrl.yaml +129 -0
  91. data/definitions/rs_la.yaml +129 -0
  92. data/definitions/ru.yaml +108 -0
  93. data/definitions/se.yaml +238 -0
  94. data/definitions/sg.yaml +89 -0
  95. data/definitions/si.yaml +162 -0
  96. data/definitions/sk.yaml +154 -0
  97. data/definitions/spec/coverage_report.rb +7 -0
  98. data/definitions/spec/data/invalid/months/malformed/bad.yaml +15 -0
  99. data/definitions/spec/data/invalid/months/missing/no_months.yaml +9 -0
  100. data/definitions/spec/data/valid/simple.yaml +15 -0
  101. data/definitions/spec/spec_helper.rb +7 -0
  102. data/definitions/spec/validation/custom_method_validator_spec.rb +60 -0
  103. data/definitions/spec/validation/definition_validator_spec.rb +43 -0
  104. data/definitions/spec/validation/month_validator_spec.rb +175 -0
  105. data/definitions/spec/validation/test_validator_spec.rb +169 -0
  106. data/definitions/th.yaml +111 -0
  107. data/definitions/tn.yaml +83 -0
  108. data/definitions/tr.yaml +174 -0
  109. data/definitions/ua.yaml +161 -0
  110. data/definitions/unitednations.yaml +189 -0
  111. data/definitions/ups.yaml +102 -0
  112. data/definitions/us.yaml +965 -0
  113. data/definitions/ve.yaml +118 -0
  114. data/definitions/vi.yaml +54 -0
  115. data/definitions/za.yaml +139 -0
  116. data/doc/CONTRIBUTING.md +72 -0
  117. data/doc/MAINTAINERS.md +81 -0
  118. data/doc/REFERENCES +19 -0
  119. data/lib/generated_definitions/MANIFEST +83 -0
  120. data/lib/generated_definitions/REGIONS.rb +6 -0
  121. data/lib/generated_definitions/ar.rb +60 -0
  122. data/lib/generated_definitions/at.rb +37 -0
  123. data/lib/generated_definitions/au.rb +177 -0
  124. data/lib/generated_definitions/be.rb +42 -0
  125. data/lib/generated_definitions/be_fr.rb +36 -0
  126. data/lib/generated_definitions/be_nl.rb +36 -0
  127. data/lib/generated_definitions/bg.rb +53 -0
  128. data/lib/generated_definitions/br.rb +37 -0
  129. data/lib/generated_definitions/ca.rb +88 -0
  130. data/lib/generated_definitions/ch.rb +95 -0
  131. data/lib/generated_definitions/cl.rb +71 -0
  132. data/lib/generated_definitions/co.rb +121 -0
  133. data/lib/generated_definitions/cr.rb +35 -0
  134. data/lib/generated_definitions/cz.rb +37 -0
  135. data/lib/generated_definitions/de.rb +65 -0
  136. data/lib/generated_definitions/dk.rb +48 -0
  137. data/lib/generated_definitions/ecbtarget.rb +30 -0
  138. data/lib/generated_definitions/ee.rb +36 -0
  139. data/lib/generated_definitions/el.rb +38 -0
  140. data/lib/generated_definitions/es.rb +56 -0
  141. data/lib/generated_definitions/europe.rb +638 -0
  142. data/lib/generated_definitions/federalreserve.rb +35 -0
  143. data/lib/generated_definitions/federalreservebanks.rb +35 -0
  144. data/lib/generated_definitions/fedex.rb +36 -0
  145. data/lib/generated_definitions/fi.rb +61 -0
  146. data/lib/generated_definitions/fr.rb +39 -0
  147. data/lib/generated_definitions/gb.rb +51 -0
  148. data/lib/generated_definitions/ge.rb +41 -0
  149. data/lib/generated_definitions/gr.rb +38 -0
  150. data/lib/generated_definitions/hk.rb +106 -0
  151. data/lib/generated_definitions/hr.rb +40 -0
  152. data/lib/generated_definitions/hu.rb +35 -0
  153. data/lib/generated_definitions/ie.rb +33 -0
  154. data/lib/generated_definitions/is.rb +60 -0
  155. data/lib/generated_definitions/it.rb +45 -0
  156. data/lib/generated_definitions/jp.rb +166 -0
  157. data/lib/generated_definitions/ke.rb +34 -0
  158. data/lib/generated_definitions/kr.rb +40 -0
  159. data/lib/generated_definitions/kz.rb +38 -0
  160. data/lib/generated_definitions/li.rb +44 -0
  161. data/lib/generated_definitions/lt.rb +38 -0
  162. data/lib/generated_definitions/lu.rb +35 -0
  163. data/lib/generated_definitions/lv.rb +56 -0
  164. data/lib/generated_definitions/ma.rb +33 -0
  165. data/lib/generated_definitions/mt_en.rb +38 -0
  166. data/lib/generated_definitions/mt_mt.rb +38 -0
  167. data/lib/generated_definitions/mx.rb +54 -0
  168. data/lib/generated_definitions/my.rb +30 -0
  169. data/lib/generated_definitions/nerc.rb +30 -0
  170. data/lib/generated_definitions/ng.rb +33 -0
  171. data/lib/generated_definitions/nl.rb +37 -0
  172. data/lib/generated_definitions/no.rb +40 -0
  173. data/lib/generated_definitions/northamerica.rb +229 -0
  174. data/lib/generated_definitions/nyse.rb +34 -0
  175. data/lib/generated_definitions/nz.rb +105 -0
  176. data/lib/generated_definitions/pe.rb +43 -0
  177. data/lib/generated_definitions/ph.rb +50 -0
  178. data/lib/generated_definitions/pl.rb +73 -0
  179. data/lib/generated_definitions/pt.rb +40 -0
  180. data/lib/generated_definitions/ro.rb +39 -0
  181. data/lib/generated_definitions/rs_cyrl.rb +39 -0
  182. data/lib/generated_definitions/rs_la.rb +39 -0
  183. data/lib/generated_definitions/ru.rb +37 -0
  184. data/lib/generated_definitions/scandinavia.rb +166 -0
  185. data/lib/generated_definitions/se.rb +53 -0
  186. data/lib/generated_definitions/sg.rb +31 -0
  187. data/lib/generated_definitions/si.rb +39 -0
  188. data/lib/generated_definitions/sk.rb +39 -0
  189. data/lib/generated_definitions/southamerica.rb +248 -0
  190. data/lib/generated_definitions/th.rb +36 -0
  191. data/lib/generated_definitions/tn.rb +32 -0
  192. data/lib/generated_definitions/tr.rb +64 -0
  193. data/lib/generated_definitions/ua.rb +37 -0
  194. data/lib/generated_definitions/unitednations.rb +81 -0
  195. data/lib/generated_definitions/ups.rb +36 -0
  196. data/lib/generated_definitions/us.rb +153 -0
  197. data/lib/generated_definitions/ve.rb +36 -0
  198. data/lib/generated_definitions/vi.rb +29 -0
  199. data/lib/generated_definitions/za.rb +36 -0
  200. data/lib/holidays/core_extensions/date.rb +57 -0
  201. data/lib/holidays/core_extensions/time.rb +23 -0
  202. data/lib/holidays/date_calculator/day_of_month.rb +68 -0
  203. data/lib/holidays/date_calculator/easter.rb +91 -0
  204. data/lib/holidays/date_calculator/lunar_date.rb +371 -0
  205. data/lib/holidays/date_calculator/weekend_modifier.rb +80 -0
  206. data/lib/holidays/definition/context/function_processor.rb +91 -0
  207. data/lib/holidays/definition/context/generator.rb +209 -0
  208. data/lib/holidays/definition/context/load.rb +29 -0
  209. data/lib/holidays/definition/context/merger.rb +22 -0
  210. data/lib/holidays/definition/decorator/custom_method_proc.rb +28 -0
  211. data/lib/holidays/definition/decorator/custom_method_source.rb +30 -0
  212. data/lib/holidays/definition/decorator/test.rb +37 -0
  213. data/lib/holidays/definition/entity/custom_method.rb +11 -0
  214. data/lib/holidays/definition/entity/test.rb +11 -0
  215. data/lib/holidays/definition/generator/module.rb +54 -0
  216. data/lib/holidays/definition/generator/regions.rb +55 -0
  217. data/lib/holidays/definition/generator/test.rb +51 -0
  218. data/lib/holidays/definition/parser/custom_method.rb +67 -0
  219. data/lib/holidays/definition/parser/test.rb +86 -0
  220. data/lib/holidays/definition/repository/cache.rb +47 -0
  221. data/lib/holidays/definition/repository/custom_methods.rb +27 -0
  222. data/lib/holidays/definition/repository/holidays_by_month.rb +57 -0
  223. data/lib/holidays/definition/repository/proc_result_cache.rb +51 -0
  224. data/lib/holidays/definition/repository/regions.rb +46 -0
  225. data/lib/holidays/definition/validator/custom_method.rb +31 -0
  226. data/lib/holidays/definition/validator/region.rb +36 -0
  227. data/lib/holidays/definition/validator/test.rb +71 -0
  228. data/lib/holidays/errors.rb +11 -0
  229. data/lib/holidays/factory/date_calculator.rb +42 -0
  230. data/lib/holidays/factory/definition.rb +143 -0
  231. data/lib/holidays/factory/finder.rb +70 -0
  232. data/lib/holidays/finder/context/between.rb +45 -0
  233. data/lib/holidays/finder/context/dates_driver_builder.rb +64 -0
  234. data/lib/holidays/finder/context/next_holiday.rb +57 -0
  235. data/lib/holidays/finder/context/parse_options.rb +104 -0
  236. data/lib/holidays/finder/context/search.rb +111 -0
  237. data/lib/holidays/finder/context/year_holiday.rb +57 -0
  238. data/lib/holidays/finder/rules/in_region.rb +31 -0
  239. data/lib/holidays/finder/rules/year_range.rb +58 -0
  240. data/lib/holidays/load_all_definitions.rb +56 -0
  241. data/lib/holidays/version.rb +3 -0
  242. data/lib/holidays.rb +130 -0
  243. data/lib/revised_holidays.rb +1 -0
  244. data/revised_holidays.gemspec +31 -0
  245. data/test/coverage_report.rb +26 -0
  246. data/test/data/test_custom_govt_holiday_defs.yaml +5 -0
  247. data/test/data/test_custom_informal_holidays_defs.yaml +11 -0
  248. data/test/data/test_custom_year_range_holiday_defs.yaml +31 -0
  249. data/test/data/test_invalid_region.rb +15 -0
  250. data/test/data/test_multiple_custom_holiday_defs.yaml +12 -0
  251. data/test/data/test_multiple_regions_with_conflicts_region_1.yaml +38 -0
  252. data/test/data/test_multiple_regions_with_conflicts_region_2.yaml +38 -0
  253. data/test/data/test_region.rb +15 -0
  254. data/test/data/test_single_custom_holiday_defs.yaml +12 -0
  255. data/test/data/test_single_custom_holiday_with_custom_procs.yaml +28 -0
  256. data/test/defs/test_defs_ar.rb +69 -0
  257. data/test/defs/test_defs_at.rb +31 -0
  258. data/test/defs/test_defs_au.rb +233 -0
  259. data/test/defs/test_defs_be_fr.rb +45 -0
  260. data/test/defs/test_defs_be_nl.rb +45 -0
  261. data/test/defs/test_defs_bg.rb +41 -0
  262. data/test/defs/test_defs_br.rb +49 -0
  263. data/test/defs/test_defs_ca.rb +289 -0
  264. data/test/defs/test_defs_ch.rb +51 -0
  265. data/test/defs/test_defs_cl.rb +69 -0
  266. data/test/defs/test_defs_co.rb +113 -0
  267. data/test/defs/test_defs_cr.rb +29 -0
  268. data/test/defs/test_defs_cz.rb +37 -0
  269. data/test/defs/test_defs_de.rb +89 -0
  270. data/test/defs/test_defs_dk.rb +47 -0
  271. data/test/defs/test_defs_ecbtarget.rb +27 -0
  272. data/test/defs/test_defs_ee.rb +41 -0
  273. data/test/defs/test_defs_es.rb +137 -0
  274. data/test/defs/test_defs_europe.rb +1522 -0
  275. data/test/defs/test_defs_fed_ex.rb +24 -0
  276. data/test/defs/test_defs_federalreserve.rb +119 -0
  277. data/test/defs/test_defs_federalreservebanks.rb +251 -0
  278. data/test/defs/test_defs_fedex.rb +31 -0
  279. data/test/defs/test_defs_fi.rb +59 -0
  280. data/test/defs/test_defs_fr.rb +43 -0
  281. data/test/defs/test_defs_gb.rb +159 -0
  282. data/test/defs/test_defs_ge.rb +53 -0
  283. data/test/defs/test_defs_gr.rb +41 -0
  284. data/test/defs/test_defs_hk.rb +59 -0
  285. data/test/defs/test_defs_hr.rb +45 -0
  286. data/test/defs/test_defs_hu.rb +47 -0
  287. data/test/defs/test_defs_ie.rb +53 -0
  288. data/test/defs/test_defs_is.rb +51 -0
  289. data/test/defs/test_defs_it.rb +55 -0
  290. data/test/defs/test_defs_jp.rb +159 -0
  291. data/test/defs/test_defs_ke.rb +31 -0
  292. data/test/defs/test_defs_kr.rb +37 -0
  293. data/test/defs/test_defs_kz.rb +39 -0
  294. data/test/defs/test_defs_li.rb +35 -0
  295. data/test/defs/test_defs_lt.rb +65 -0
  296. data/test/defs/test_defs_lu.rb +35 -0
  297. data/test/defs/test_defs_lv.rb +98 -0
  298. data/test/defs/test_defs_ma.rb +29 -0
  299. data/test/defs/test_defs_mt_en.rb +41 -0
  300. data/test/defs/test_defs_mt_mt.rb +41 -0
  301. data/test/defs/test_defs_mx.rb +49 -0
  302. data/test/defs/test_defs_my.rb +23 -0
  303. data/test/defs/test_defs_nerc.rb +29 -0
  304. data/test/defs/test_defs_ng.rb +29 -0
  305. data/test/defs/test_defs_nl.rb +33 -0
  306. data/test/defs/test_defs_no.rb +43 -0
  307. data/test/defs/test_defs_northamerica.rb +667 -0
  308. data/test/defs/test_defs_nyse.rb +46 -0
  309. data/test/defs/test_defs_nz.rb +67 -0
  310. data/test/defs/test_defs_pe.rb +47 -0
  311. data/test/defs/test_defs_ph.rb +29 -0
  312. data/test/defs/test_defs_pl.rb +229 -0
  313. data/test/defs/test_defs_pt.rb +47 -0
  314. data/test/defs/test_defs_ro.rb +65 -0
  315. data/test/defs/test_defs_rs_cyrl.rb +46 -0
  316. data/test/defs/test_defs_rs_la.rb +46 -0
  317. data/test/defs/test_defs_ru.rb +34 -0
  318. data/test/defs/test_defs_scandinavia.rb +215 -0
  319. data/test/defs/test_defs_se.rb +59 -0
  320. data/test/defs/test_defs_sg.rb +25 -0
  321. data/test/defs/test_defs_si.rb +105 -0
  322. data/test/defs/test_defs_sk.rb +41 -0
  323. data/test/defs/test_defs_southamerica.rb +327 -0
  324. data/test/defs/test_defs_th.rb +33 -0
  325. data/test/defs/test_defs_tn.rb +27 -0
  326. data/test/defs/test_defs_tr.rb +60 -0
  327. data/test/defs/test_defs_ua.rb +41 -0
  328. data/test/defs/test_defs_unitednations.rb +11 -0
  329. data/test/defs/test_defs_ups.rb +31 -0
  330. data/test/defs/test_defs_us.rb +387 -0
  331. data/test/defs/test_defs_ve.rb +35 -0
  332. data/test/defs/test_defs_vi.rb +22 -0
  333. data/test/defs/test_defs_za.rb +35 -0
  334. data/test/holidays/core_extensions/test_date.rb +122 -0
  335. data/test/holidays/core_extensions/test_date_time.rb +60 -0
  336. data/test/holidays/date_calculator/test_day_of_month.rb +27 -0
  337. data/test/holidays/date_calculator/test_easter_gregorian.rb +30 -0
  338. data/test/holidays/date_calculator/test_easter_julian.rb +36 -0
  339. data/test/holidays/date_calculator/test_lunar_date.rb +89 -0
  340. data/test/holidays/date_calculator/test_weekend_modifier.rb +54 -0
  341. data/test/holidays/definition/context/test_function_processor.rb +199 -0
  342. data/test/holidays/definition/context/test_generator.rb +226 -0
  343. data/test/holidays/definition/context/test_load.rb +37 -0
  344. data/test/holidays/definition/context/test_merger.rb +25 -0
  345. data/test/holidays/definition/decorator/test_custom_method_proc.rb +113 -0
  346. data/test/holidays/definition/decorator/test_custom_method_source.rb +96 -0
  347. data/test/holidays/definition/decorator/test_test.rb +123 -0
  348. data/test/holidays/definition/generator/test_module.rb +268 -0
  349. data/test/holidays/definition/generator/test_regions.rb +97 -0
  350. data/test/holidays/definition/generator/test_test.rb +113 -0
  351. data/test/holidays/definition/parser/test_custom_method.rb +79 -0
  352. data/test/holidays/definition/parser/test_test.rb +142 -0
  353. data/test/holidays/definition/repository/test_cache.rb +123 -0
  354. data/test/holidays/definition/repository/test_custom_methods.rb +43 -0
  355. data/test/holidays/definition/repository/test_holidays_by_month.rb +275 -0
  356. data/test/holidays/definition/repository/test_proc_result_cache.rb +91 -0
  357. data/test/holidays/definition/repository/test_regions.rb +104 -0
  358. data/test/holidays/definition/validator/test_custom_method.rb +94 -0
  359. data/test/holidays/definition/validator/test_region.rb +54 -0
  360. data/test/holidays/definition/validator/test_test.rb +60 -0
  361. data/test/holidays/finder/context/test_between.rb +172 -0
  362. data/test/holidays/finder/context/test_dates_driver_builder.rb +91 -0
  363. data/test/holidays/finder/context/test_next_holiday.rb +156 -0
  364. data/test/holidays/finder/context/test_parse_options.rb +141 -0
  365. data/test/holidays/finder/context/test_search.rb +232 -0
  366. data/test/holidays/finder/context/test_year_holiday.rb +202 -0
  367. data/test/holidays/finder/rules/test_in_region.rb +42 -0
  368. data/test/holidays/finder/rules/test_year_range.rb +166 -0
  369. data/test/integration/README.md +9 -0
  370. data/test/integration/test_all_regions.rb +49 -0
  371. data/test/integration/test_any_holidays_during_work_week.rb +90 -0
  372. data/test/integration/test_available_regions.rb +23 -0
  373. data/test/integration/test_custom_holidays.rb +41 -0
  374. data/test/integration/test_custom_informal_holidays.rb +15 -0
  375. data/test/integration/test_custom_year_range_holidays.rb +35 -0
  376. data/test/integration/test_holidays.rb +243 -0
  377. data/test/integration/test_holidays_between.rb +87 -0
  378. data/test/integration/test_multiple_regions.rb +71 -0
  379. data/test/integration/test_multiple_regions_with_conflict.rb +29 -0
  380. data/test/integration/test_nonstandard_regions.rb +25 -0
  381. data/test/test_helper.rb +37 -0
  382. metadata +649 -0
@@ -0,0 +1,435 @@
1
+ # Holiday Definition Syntax
2
+
3
+ The definition syntax is a custom format developed over the life of this project. All holidays are defined in these YAML files. These definition files have three main top-level properties:
4
+
5
+ * `months` - this is the meat! All definitions for months 1-12 are defined here
6
+ * `methods` - this contains any custom logic that your definitions require
7
+ * `tests` - this contains the tests for your definitions
8
+
9
+ The `months` property is required. The two other properties are not strictly required but are almost always used.
10
+
11
+ In fact, if you leave out `tests` your PR will probably not be accepted unless there is a very, very good reason for leaving it out.
12
+
13
+ ## Key Words
14
+
15
+ There are some terms that you should be familiar with before we dive into each section:
16
+
17
+ #### `region`
18
+
19
+ A region is a symbol that denotes the geographic or cultural region for that holiday. In general these symbols will be the [ISO 3166](https://en.wikipedia.org/wiki/ISO_3166) code for a country or region.
20
+
21
+ ##### Sub-region
22
+
23
+ We also have a concept of a `sub-region`. These regions exist inside of a 'parent' region and inherit the parent's holidays. We use an underscore to specify a subregion.
24
+
25
+ Examples:
26
+
27
+ * `:us_dc` for Washington, D.C in `:us`
28
+ * `:ca_bc` for British Columbia in `:ca`
29
+
30
+ Some sub-regions do not have a matching ISO 3116 entry. In these cases we attempt to choose symbols that are reasonably clear.
31
+
32
+ ##### Non-standard regions
33
+
34
+ Before version v1.1.0 of the original ruby gem the compliance with ISO 3166 was not as strict. There might be cases where an existing region symbol does not match the ISO standard.
35
+
36
+ Non-standard regions (e.g. `ecbtarget`, `federalreserve`, etc) must be all one word, just like a normal region. They must not use underscores or hyphens.
37
+
38
+ #### `formal`/`informal`
39
+
40
+ We consider `formal` dates as government-defined holidays. These could be the kinds of holidays where everyone stays home from work or perhaps are bank holidays but it is *not required* for a holiday to have these features to be considered formal.
41
+
42
+ `Informal` holidays are holidays that everyone knows about but aren't enshrined in law. For example, Valentine's Day in the US is considered an informal holiday.
43
+
44
+ We recognize that these definitions can be highly subjective. If you disagree with the current status of a holiday please open an issue so we can discuss it.
45
+
46
+ #### `observed`
47
+
48
+ There are certain holidays that can be legally observed on different days than they occur. For example, if a holiday falls on a Saturday but it is legally observed on the following Monday then you can define it as `observed` on the Monday. Please see the section below for more details and examples.
49
+
50
+ ## Months
51
+
52
+ Holidays are grouped by month from 1 through 12. Each entry within a month can have several properties depending on the behavior of the holiday. Each section below lays out the various different ways you can define your holiday.
53
+
54
+ The two required properties are:
55
+
56
+ * `name` - The name of the holiday
57
+ * `regions` - One or more region codes (targeted to match [ISO 3166](https://en.wikipedia.org/wiki/ISO_3166))
58
+
59
+ ### Dates defined by a fixed date (e.g. January 1st)
60
+
61
+ * `mday` - A non-negative integer representing day of the month (1 through 31).
62
+
63
+ For example, the following holiday is on the first of January and available in the `:ca`, `:us` and `:au` regions:
64
+
65
+ ```yaml
66
+ 1:
67
+ - name: New Year's Day
68
+ regions: [ca, us, au]
69
+ mday: 1
70
+ ```
71
+
72
+ ### Dates defined by a week number (e.g. first Monday of a month)
73
+
74
+ * `wday` - A non-negative integer representing day of the week (0 = Sunday through 6 = Saturday).
75
+ * `week` - A non-negative integer representing week number (1 = first week, 3 = third week, -1 = last week),
76
+
77
+ For example, the following holiday is on the first Monday of September and available in the `:ca` region:
78
+
79
+ ```yaml
80
+ 9:
81
+ - name: Labour Day
82
+ regions: [ca]
83
+ week: 1
84
+ wday: 1
85
+ ```
86
+
87
+ ### 'Formal' vs 'Informal' types
88
+
89
+ As mentioned above you can specify two different types. By default a holiday is considered 'formal'. By adding a `type: informal` to a definition you will mark it as 'informal' and it will only show up if the user specifically asks for it.
90
+
91
+ Example:
92
+
93
+ ```yaml
94
+ 9:
95
+ - name: Some Holiday
96
+ regions: [fr]
97
+ mday: 1
98
+ type: informal
99
+ ```
100
+
101
+ If a user submits:
102
+
103
+ ```ruby
104
+ Holidays.on(Date.civil(2016, 9, 1), :fr)
105
+ ```
106
+
107
+ Then they will not see the holiday. However, if they submit:
108
+
109
+ ```ruby
110
+ Holidays.on(Date.civil(2016, 9, 1), :fr, :informal)
111
+ ```
112
+
113
+ Then the holiday will be returned. This is especially useful for holidays like "Valentine's Day" in the USA, where it is commonly recognized as a holiday in society but not as a day that is celebrated by taking the day off.
114
+
115
+ ### Year ranges
116
+
117
+ Certain holidays in various countries are only in effect during specific year ranges. A few examples of this are:
118
+
119
+ * A new holiday that starts in 2017 and continues into the future
120
+ * An existing holiday that has been cancelled so that the final year in effect is 2019
121
+ * A historical holiday that was only in effect from 2002 through 2006
122
+
123
+ To address these kinds of scenarios we have the ability to specify 'year ranges' for individual holiday definitions. There are a total of four selectors that can be specified. All must be specified in terms of 'years'. Only one selector can be used at a time.
124
+
125
+ #### `until`
126
+
127
+ The 'until' selector will only return a match if the supplied date takes place in the same year as the holiday or earlier.
128
+
129
+ A single integer representing a year *must* be supplied. An array of values will result in an error.
130
+
131
+ Example:
132
+
133
+ ```yaml
134
+ 7:
135
+ name: 振替休日
136
+ regions: [jp]
137
+ mday: 1
138
+ year_ranges:
139
+ until: 2002
140
+ ```
141
+
142
+ This will return successfully since the date is before 2002:
143
+
144
+ ```ruby
145
+ Holidays.on(Date.civil(2000, 7, 1), :jp)
146
+ ```
147
+
148
+ This will also return successfully since the date takes place on 2002 exactly:
149
+
150
+ ```ruby
151
+ Holidays.on(Date.civil(2002, 7, 1), :jp)
152
+ ```
153
+
154
+ This will not since the date is after 2002:
155
+
156
+ ```ruby
157
+ Holidays.on(Date.civil(2016, 7, 1), :jp)
158
+ ```
159
+
160
+ #### `from`
161
+
162
+ The 'from' selector will only return a match if the supplied date takes place in the same year as the holiday or later.
163
+
164
+ A single integer representing a year *must* be supplied. An array of values will result in an error.
165
+
166
+ Example:
167
+
168
+ ```yaml
169
+ 7:
170
+ name: 振替休日
171
+ regions: [jp]
172
+ mday: 1
173
+ year_ranges:
174
+ from: 2002
175
+ ```
176
+
177
+ This will return successfully since the date is after 2002:
178
+
179
+ ```ruby
180
+ Holidays.on(Date.civil(2016, 7, 1), :jp)
181
+ ```
182
+
183
+ This will also return successfully since the date takes place on 2002 exactly:
184
+
185
+ ```ruby
186
+ Holidays.on(Date.civil(2002, 7, 1), :jp)
187
+ ```
188
+
189
+ This will not since the date is before 2002:
190
+
191
+ ```ruby
192
+ Holidays.on(Date.civil(2000, 7, 1), :jp)
193
+ ```
194
+
195
+ #### `limited`
196
+
197
+ The 'limited' selector will only find a match if the supplied date takes place during
198
+ one of the specified years. Multiple years can be specified.
199
+
200
+ An array of integers representing years *must* be supplied. Providing anything other than an array of integers will result in an error.
201
+
202
+ Please note that this is *not* a range! This is an array of specific years during which the holiday is active. If you need a year range please see the `between` selector below.
203
+
204
+ Example:
205
+
206
+ ```yaml
207
+ 7:
208
+ name: 振替休日
209
+ regions: [jp]
210
+ mday: 1
211
+ year_ranges:
212
+ limited: [2002,2004]
213
+ ```
214
+
215
+ Both of these examples will return successfully since the dates takes place in 2002 and 2004 exactly:
216
+
217
+ ```ruby
218
+ Holidays.on(Date.civil(2002, 7, 1), :jp)
219
+ Holidays.on(Date.civil(2004, 7, 1), :jp)
220
+ ```
221
+
222
+ Neither of these will return since the dates takes place in outside of 2002 and 2004:
223
+
224
+ ```ruby
225
+ Holidays.on(Date.civil(2000, 7, 1), :jp)
226
+ Holidays.on(Date.civil(2003, 7, 1), :jp)
227
+ ```
228
+
229
+ #### `between`
230
+
231
+ The 'between' selector will only find a match if the supplied date takes place during the specified _inclusive_ range of years.
232
+
233
+ To use this selector you *must* provide both a `start` and `end` key. Both values must be integers representing years.
234
+
235
+ Example:
236
+
237
+ ```yaml
238
+ 7:
239
+ name: 振替休日
240
+ regions: [jp]
241
+ mday: 1
242
+ year_ranges:
243
+ between:
244
+ start: 1996
245
+ end: 2002
246
+ ```
247
+
248
+ These examples will return successfully since they take place within the specified range:
249
+
250
+ ```ruby
251
+ Holidays.on(Date.civil(1996, 7, 1), :jp)
252
+ Holidays.on(Date.civil(2000, 7, 1), :jp)
253
+ Holidays.on(Date.civil(2002, 7, 1), :jp)
254
+ ```
255
+
256
+ These will not since both are outside of the specified start/end range:
257
+
258
+ ```ruby
259
+ Holidays.on(Date.civil(2003, 7, 1), :jp)
260
+ Holidays.on(Date.civil(1995, 7, 1), :jp)
261
+ ```
262
+
263
+ ## Methods
264
+
265
+ Sometimes you need to perform a complex calculation to determine a holiday. To facilitate this we allow for users to specify custom methods to calculate a date. These should be placed under the `methods` property. Methods named in this way can then be referenced by entries in the `months` property.
266
+
267
+ #### Important note
268
+
269
+ One thing to note is that these methods are _language specific_ at this time, meaning we would have one for ruby, one for golang, etc. Coming up with a standardized way to represent the logic in the custom-written methods proved to be very difficult. This is a punt until we can come up with a better solution.
270
+
271
+ Please feel free to only add the custom method source in the language that you choose. It will be up to downstream maintainers to ensure that their language has an implementation. So if you only want to add it in ruby please just do that!
272
+
273
+ ### Method Example
274
+
275
+ Canada celebrates Victoria Day, which falls on the Monday on or before May 24. Under the `methods` property we would create a custom method for ruby that returns a Date object:
276
+
277
+ ```yaml
278
+ methods:
279
+ ca_victoria_day:
280
+ arguments: year
281
+ ruby: |
282
+ date = Date.civil(year, 5, 24)
283
+ if date.wday > 1
284
+ date -= (date.wday - 1)
285
+ elsif date.wday == 0
286
+ date -= 6
287
+ end
288
+
289
+ date
290
+ ```
291
+
292
+ This could then be used in a `months` entry:
293
+
294
+ ```yaml
295
+ 5:
296
+ - name: Victoria Day
297
+ regions: [ca]
298
+ function: ca_victoria_day(year)
299
+ ```
300
+
301
+ ### Available arguments
302
+
303
+ You may only specify the following values for arguments into a custom method: `date`, `year`, `month`, `day`, `region`
304
+
305
+ Correct example:
306
+
307
+ ```yaml
308
+ 1:
309
+ - name: Custom Method
310
+ regions: [us]
311
+ function: custom_method(year, month, day)
312
+ ```
313
+
314
+ The following will return an error since `week` is not a recognized argument:
315
+
316
+ ```yaml
317
+ 1:
318
+ - name: Custom Method
319
+ regions: [us]
320
+ function: custom_method(week)
321
+ ```
322
+
323
+ #### Whaa? Why do you restrict what I can pass in?
324
+
325
+ This was done as an attempt to make it easier for the downstream projects to parse and use the custom methods. They have to be able to pass in the required data so we limit it to make that process easier.
326
+
327
+ We can add to this list if your custom logic needs something else! Open an issue with your use case and we can discuss it.
328
+
329
+ ### Methods without a fixed month
330
+
331
+ If a holiday does not have a fixed month (e.g. Easter) it should go in the '0' month:
332
+
333
+ ```yaml
334
+ 0:
335
+ - name: Easter Monday
336
+ regions: [ca]
337
+ function: easter(year)
338
+ ```
339
+
340
+ ### Pre-existing methods
341
+
342
+ There are pre-existing methods for highly-used calculations. You can reference these methods in your definitions as you would a custom method that you have written:
343
+
344
+ * `easter(year)` - calculates Easter via Gregorian calendar for a given year
345
+ * `orthodox_easter(year)` - calculates Easter via Julian calendar for a given year
346
+ * `to_monday_if_sunday(date)` - returns date of the following Monday if the 'date' argument falls on a Sunday
347
+ * `to_monday_if_weekend(date)` - returns date of the following Monday if the 'date' argument falls on a weekend (Saturday or Sunday)
348
+ * `to_weekday_if_boxing_weekend(date)` - returns nearest following weekday if the 'date' argument falls on Boxing Day
349
+ * `to_weekday_if_boxing_weekend_from_year(year)` - calculates nearest weekday following Boxing weekend for given year
350
+ * `to_weekday_if_weekend(date)` - returns nearest weekday (Monday or Friday) if 'date' argument falls on a weekend (Saturday or Sunday)
351
+
352
+ *Protip*: you can use the `easter` methods to calculate all of the dates that are based around Easter. It's especially useful to use since the Easter calculation is complex. For example, 'Good Friday' in the US is 2 days before Easter. Therefore you could do the following:
353
+
354
+ ```
355
+ 0:
356
+ - name: Good Friday
357
+ regions: [us]
358
+ function: easter(year)
359
+ function_modifier: -2
360
+ type: informal
361
+ ```
362
+
363
+ Use the `function_modifier` property, which can be positive or negative, to modify the result of the function.
364
+
365
+ ### Calculating observed dates
366
+
367
+ Users can specify that this gem only return holidays on their 'observed' day. This can be especially useful if they are using this gem for business-related logic. If you wish for your definitions to allow for this then you can add the `observed` property to your entry. This requires a method to help calculate the observed day.
368
+
369
+ Several built-in methods are available for holidays that are observed on varying dates.
370
+
371
+ For example, for a holiday that is observed on Monday if it falls on a weekend you could write:
372
+
373
+ ```
374
+ 7:
375
+ - name: Canada Day
376
+ regions: [ca]
377
+ mday: 1
378
+ observed: to_monday_if_weekend(date)
379
+ ```
380
+
381
+ If a user does not specify `observed` in the options then 7/1 will be the date found for 'Canada Day', regardless of whether it falls on a Saturday or Sunday. If a user specifies 'observed' then it will show as the following Monday if the date falls on a Saturday or Sunday.
382
+
383
+ ## Tests
384
+
385
+ All definition files should have tests included. At this time we do not enforce any rules on coverage or numbers of tests. However, in general, PRs will not be accepted if they are devoid of tests that cover the changes in question.
386
+
387
+ The format is a straightforward 'given/expect'. Here is a simple example:
388
+
389
+ ```yaml
390
+ - given:
391
+ date: '2018-1-1'
392
+ regions: ["ex"]
393
+ expect:
394
+ name: "Example Holiday"
395
+ ```
396
+
397
+ Here are format details:
398
+
399
+ * given (required)
400
+ * date (required) - all dates must be in 'YYYY-MM-DD' format. Either a single day or an array of dates can be used.
401
+ * regions (required) - an array of strings (NOT symbols). Multiple regions can be passed. Even a single region must be in an array.
402
+ * options (optional) - an array of options to use for this test. Can be either 'informal' or 'observed'. Must be an array of strings, e.g. `['informal', 'observed']`
403
+ * expect (required)
404
+ * name (optional) - the name of the holiday you are expecting. Must be a string.
405
+ * holiday (optional) - a boolean indicating whether the given values result in a holiday. Defaults to 'true' if not present. Must be true or false.
406
+
407
+ One or the other of the `expect` keys is required. If you do not specify a `name` then you should set `holiday: false`.
408
+
409
+ #### Test Examples
410
+
411
+ First example shows multiple dates, multiple regions, additional options, and an expectation that the result will be the named holiday:
412
+
413
+ ```yaml
414
+ - given:
415
+ date: ['2018-1-1', '2019-3-5']
416
+ regions: ["ex", "ex2", "ex3"]
417
+ options: ["informal"]
418
+ expect:
419
+ name: "Example Holiday"
420
+ ```
421
+
422
+ Second example shows multiple dates, a single region, multiple options, and an expectation that the given values will *not* result in a found holiday. No name is required because...no holiday is expected to be found.
423
+
424
+ ```yaml
425
+ - given:
426
+ date: ['2022-12-1', '2019-4-1', '2046-8-8]
427
+ regions: ["ex"]
428
+ options: ["informal", "observed"]
429
+ expect:
430
+ holiday: false
431
+ ```
432
+
433
+ These tests will be picked up by the `generate` process in the client repositories and written into actual tests in the given language that are run when a user executes the test suite.
434
+
435
+ Please please please include tests. Your PR won't be accepted if tests are not included with your changes.
@@ -0,0 +1,15 @@
1
+ # Architecture Decision Records
2
+
3
+ Here we document decisions we made regarding high level architecture/design of this repository.
4
+
5
+ For details on what ADR is and why it's important, please reference the following blog posts:
6
+
7
+ - https://product.reverb.com/documenting-architecture-decisions-the-reverb-way-a3563bb24bd0
8
+ - http://thinkrelevance.com/blog/2011/11/15/documenting-architecture-decisions
9
+
10
+ Please note that we only began keeping ADRs for this project in October of 2018. Decisions made before that are not covered.
11
+
12
+ ## Table of contents
13
+
14
+ 1. [Language specific custom methods](adr-001.md)
15
+ 1. [Year ranges syntax update](adr-002.md)
@@ -0,0 +1,86 @@
1
+ # ADR 1: Custom Methods Format Change
2
+
3
+ ## Context
4
+
5
+ We would like these definitions to be usable by any language. The original `holidays` project was written purely in `ruby` but the definitions were generally plain `YAML`.
6
+
7
+ The issue is that `ruby` has been sprinkled into the otherwise plain `YAML` when it made sense with no plan for use outside of `ruby`. This makes sense when you are never planning on using the `YAML` files in other languages.
8
+
9
+ Over time we have [been working](https://github.com/holidays/definitions/issues/7) to make the syntax more generic so that other language implementations could consume them. The last hurdle was custom methods.
10
+
11
+ An example of the original format:
12
+
13
+ ```yaml
14
+ methods:
15
+ ca_victoria_day:
16
+ arguments: year
17
+ source: |
18
+ date = Date.civil(year, 5, 24)
19
+ if date.wday > 1
20
+ date -= (date.wday - 1)
21
+ elsif date.wday == 0
22
+ date -= 6
23
+ end
24
+
25
+ date
26
+ ```
27
+
28
+ As you can see the actual function is just plain `ruby`.
29
+
30
+ After lots of trial and error I have decided that I cannot see a generic format for this logic that would satisfy all use cases for existing custom methods in our definitions. While some custom methods are relatively simple `if/else` statements there are many that are much more complicated.
31
+
32
+ An example of a 'complicated' custom method from the `ch` (Swiss) region:
33
+
34
+ ```yaml
35
+ ch_vd_lundi_du_jeune_federal:
36
+ # Monday after the third Sunday of September
37
+ arguments: year
38
+ ruby: |
39
+ date = Date.civil(year,9,1)
40
+ # Find the first Sunday of September
41
+ until date.wday.eql? 0 do
42
+ date += 1
43
+ end
44
+ # There are 15 days between the first Sunday
45
+ # and the Monday after the third Sunday
46
+ date + 15
47
+ ```
48
+
49
+ The logic itself is not hard to follow but coming up with a generic way to phrase this seems like a complex problem. Every attempt that was made devolved into very complex parsers of nested `YAML` so that we correctly handled each new edge case that appeared. It was very slow going and the complexity was growing and growing.
50
+
51
+ Additionally, having a complex `YAML` syntax for custom methods would require each downstream repository to implement the 'standard'. That seems pretty scary to think about maintaining.
52
+
53
+ The other option is to just make each future language provide their own implementations.
54
+
55
+ ## Decision
56
+
57
+ The decision is to simply require language-specific implementations of custom methods. Since all custom methods are currently in `ruby` we are changing every `source` field to `ruby`. In the future new languages will need to provide their own implementations. For example, we could add a `golang` or `swift` section next to the existing `ruby` section.
58
+
59
+ There are three significant advantages:
60
+
61
+ - It is very easy to understand
62
+ - All holidays using custom methods have tests so each downstream project will have built-in protection in case a bug is introduced in only one language implementation
63
+ - It is very easy to implement for the current `ruby` implementation (which is our only project currently)
64
+
65
+ There are significant downsides:
66
+
67
+ - Possible divergence between languages due to separate implementations, causing confusion and frustration
68
+ - More pressure on maintainers to handle the various implementations, ensuring they can build without issues when new custom methods are added
69
+ - Confusion for new contributors who may only be comfortable in a single language
70
+ - New downstream languages will have a higher hurdle to overcome since they will need to implement the existing logic in their own language
71
+
72
+ In the end I don't want to hold things up because of _possible_ new language implementations that might show up in the future. I personally want to create a new `golang` version of `holidays` but beyond that maybe no one else will consume these definitions!
73
+
74
+ If the `holidays` projects become wildly popular in the future and this becomes a huge problem then I can address it with the (presumably huge) community to find a solution.
75
+
76
+ ## Consequences
77
+
78
+ We might lose contributions due to confusion or fear.
79
+
80
+ We might burn out maintainers if the juggling of languages becomes too much of a burden.
81
+
82
+ This puts more pressure for the completion of an updated [test framework](https://github.com/holidays/definitions/issues/42) for downstream repositories.
83
+
84
+ ## Status
85
+
86
+ Accepted.
@@ -0,0 +1,64 @@
1
+ # ADR 2: Year ranges syntax update
2
+
3
+ ## Context
4
+
5
+ #### Original year range behavior
6
+
7
+ Starting in [v3.2.0](https://github.com/holidays/holidays/releases/tag/v3.2.0) of the ruby gem [\[1\]](#footnote-1) we have had the ability to specify year ranges for specific holidays. This allows for a holiday
8
+ to only be considered 'valid' or 'active' based on specific criteria surrounding years. The available criteria were:
9
+
10
+ * `before` - holiday only valid if it takes place on the target year or before
11
+ * `after` - holiday only valid if it takes place on the target year or after
12
+ * `limited` - holiday only valid if it takes place on at least one of an array of target years (e.g. [2002, 2004])
13
+ * `between` - holiday only valid if it takes place between an inclusive year range (e.g. 2002..2004)
14
+
15
+ This change added useful functionality and its use has since spread to multiple regions.
16
+
17
+ #### Confusion about criteria behavior
18
+
19
+ On January 24th, 2019 [an issue was opened](https://github.com/holidays/definitions/issues/117) expressing that the `before` and `after` criteria were named in a confusing manner since it was not clear whether they operated inclusively or exclusively on the target year.
20
+
21
+ As an example, the value `after: 2018` could be construed by some to mean the holiday is valid starting in 2019 and onward. In reality the current implementation is that the holiday is valid starting in 2018 itself and onward.
22
+
23
+ While this is ultimately up to individual perception it is true that the current names do not provide strong guidance on how the definition will behave.
24
+
25
+ ## Decision
26
+
27
+ The [above issue](https://github.com/holidays/definitions/issues/117) also contained a proposal to make the following changes:
28
+
29
+ * Rename `before` to `until`
30
+ * Rename `after` to `from`
31
+
32
+ These names give a clearer understanding of the desired behavior as `until` and `from` are more generally understood to indicate inclusivity rather than exclusivity.
33
+
34
+ If we take the example from above and make the change then the value `from: 2018` would intend for the holiday to be valid/active starting in 2018 and onward.
35
+
36
+ #### Additional changes
37
+
38
+ While looking into the above issue I noticed two important things that will also be addressed alongside the above changes:
39
+
40
+ * The definition validator does not currently prevent users from specifying multiple selectors at a time for a `year_ranges` entry and we perform no validation that these selectors do not conflict with one another.
41
+ * The `between` key currently accepts a string representation of a Ruby range (e.g. '2008..2012'). While this was not causing any issues today we would like to remove all Ruby-specific values from our definitions so that other languages could more easily parse them.
42
+
43
+ To that end the following changes will also be made:
44
+
45
+ * Update the definition validation to only allow a single selector per `year_ranges` entry and update all definitions to match. This will result no behavior changes but will make clear the expected behavior.
46
+ * `between` will no longer accept a ruby-like range string but instead require explicit `start` and `end` keys with integer values representing a year.
47
+
48
+ ## Consequences
49
+
50
+ This change will require changing multiple files and wll result in a major semantic version bump for the definitions. In addition we will also need to make a similar breaking change in all consuming apps.
51
+
52
+ There are mitigating factors, however. There are only a handful of existing definitions that use the `before`, `after`, or `between` keys and the only consuming app is the [ruby gem](https://github.com/holidays/holidays). This means our affected code is relatively small.
53
+
54
+ Additionally there was already a plan in place to perform an unrelated breaking change in the gem. This means that we can bundle these breaking changes together and minimize the amount of version churn.
55
+
56
+ ## Status
57
+
58
+ Accepted.
59
+
60
+ ## Footnotes
61
+
62
+ ##### footnote-1
63
+
64
+ In the original `holidays` ruby library all definitions were housed in the same directory. The definitions were split into a separate repository starting with [holidays gem v5.0.0](https://github.com/holidays/holidays/blob/master/CHANGELOG.md#500).
@@ -0,0 +1,74 @@
1
+ # ECB TARGET Closing Days
2
+ #
3
+ # Updated: 2014-01-04.
4
+ # Sources:
5
+ # - http://www.ecb.europa.eu/home/html/holidays.en.html
6
+ # - http://www.ecb.europa.eu/press/pr/date/2000/html/pr001214_4.en.html
7
+ ---
8
+ months:
9
+ 0:
10
+ - name: Good Friday
11
+ regions: [ecbtarget]
12
+ function: easter(year)
13
+ function_modifier: -2
14
+ - name: Easter Monday
15
+ regions: [ecbtarget]
16
+ function: easter(year)
17
+ function_modifier: 1
18
+ 1:
19
+ - name: New Year's Day
20
+ regions: [ecbtarget]
21
+ mday: 1
22
+ 5:
23
+ - name: Labour Day
24
+ regions: [ecbtarget]
25
+ mday: 1
26
+ 12:
27
+ - name: Christmas Day
28
+ regions: [ecbtarget]
29
+ mday: 25
30
+ - name: Christmas Holiday
31
+ regions: [ecbtarget]
32
+ mday: 26
33
+
34
+ tests:
35
+ - given:
36
+ date: '2013-01-01'
37
+ regions: ["ecbtarget"]
38
+ expect:
39
+ name: "New Year's Day"
40
+ - given:
41
+ date: '2013-05-01'
42
+ regions: ["ecbtarget"]
43
+ expect:
44
+ name: "Labour Day"
45
+ - given:
46
+ date: '2013-03-29'
47
+ regions: ["ecbtarget"]
48
+ expect:
49
+ name: "Good Friday"
50
+ - given:
51
+ date: '2013-04-01'
52
+ regions: ["ecbtarget"]
53
+ expect:
54
+ name: "Easter Monday"
55
+ - given:
56
+ date: '2013-12-25'
57
+ regions: ["ecbtarget"]
58
+ expect:
59
+ name: "Christmas Day"
60
+ - given:
61
+ date: '2013-12-26'
62
+ regions: ["ecbtarget"]
63
+ expect:
64
+ name: "Christmas Holiday"
65
+ - given:
66
+ date: '2013-03-29'
67
+ regions: ["ecbtarget"]
68
+ expect:
69
+ name: "Good Friday"
70
+ - given:
71
+ date: '2013-04-01'
72
+ regions: ["ecbtarget"]
73
+ expect:
74
+ name: "Easter Monday"