holidays 11.7.0 → 11.8.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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/README.md +11 -8
  4. data/lib/generated_definitions/REGIONS.rb +3 -3
  5. data/lib/generated_definitions/ar.rb +1 -1
  6. data/lib/generated_definitions/at.rb +1 -1
  7. data/lib/generated_definitions/au.rb +2 -2
  8. data/lib/generated_definitions/be_fr.rb +1 -1
  9. data/lib/generated_definitions/be_nl.rb +1 -1
  10. data/lib/generated_definitions/bg.rb +1 -1
  11. data/lib/generated_definitions/br.rb +1 -1
  12. data/lib/generated_definitions/by.rb +1 -1
  13. data/lib/generated_definitions/ca.rb +1 -1
  14. data/lib/generated_definitions/ch.rb +1 -1
  15. data/lib/generated_definitions/cl.rb +3 -2
  16. data/lib/generated_definitions/cn.rb +1 -1
  17. data/lib/generated_definitions/co.rb +1 -1
  18. data/lib/generated_definitions/cr.rb +1 -1
  19. data/lib/generated_definitions/cy.rb +1 -1
  20. data/lib/generated_definitions/cz.rb +1 -1
  21. data/lib/generated_definitions/de.rb +1 -1
  22. data/lib/generated_definitions/dk.rb +1 -1
  23. data/lib/generated_definitions/ecbtarget.rb +1 -1
  24. data/lib/generated_definitions/ee.rb +1 -1
  25. data/lib/generated_definitions/es.rb +1 -1
  26. data/lib/generated_definitions/europe.rb +1 -1
  27. data/lib/generated_definitions/federalreserve.rb +1 -1
  28. data/lib/generated_definitions/federalreservebanks.rb +1 -1
  29. data/lib/generated_definitions/fedex.rb +1 -1
  30. data/lib/generated_definitions/fi.rb +1 -1
  31. data/lib/generated_definitions/fr.rb +1 -1
  32. data/lib/generated_definitions/gb.rb +1 -1
  33. data/lib/generated_definitions/ge.rb +1 -1
  34. data/lib/generated_definitions/gr.rb +1 -1
  35. data/lib/generated_definitions/hk.rb +1 -1
  36. data/lib/generated_definitions/hr.rb +1 -1
  37. data/lib/generated_definitions/hu.rb +1 -1
  38. data/lib/generated_definitions/ie.rb +1 -1
  39. data/lib/generated_definitions/il.rb +1 -1
  40. data/lib/generated_definitions/in.rb +1 -1
  41. data/lib/generated_definitions/is.rb +1 -1
  42. data/lib/generated_definitions/it.rb +1 -1
  43. data/lib/generated_definitions/jp.rb +1 -1
  44. data/lib/generated_definitions/ke.rb +1 -1
  45. data/lib/generated_definitions/kr.rb +1 -1
  46. data/lib/generated_definitions/kz.rb +1 -1
  47. data/lib/generated_definitions/li.rb +1 -1
  48. data/lib/generated_definitions/lt.rb +1 -1
  49. data/lib/generated_definitions/lu.rb +1 -1
  50. data/lib/generated_definitions/lv.rb +1 -1
  51. data/lib/generated_definitions/ma.rb +1 -1
  52. data/lib/generated_definitions/mc.rb +1 -1
  53. data/lib/generated_definitions/mt_en.rb +1 -1
  54. data/lib/generated_definitions/mt_mt.rb +1 -1
  55. data/lib/generated_definitions/mx.rb +1 -1
  56. data/lib/generated_definitions/my.rb +1 -1
  57. data/lib/generated_definitions/nerc.rb +1 -1
  58. data/lib/generated_definitions/ng.rb +1 -1
  59. data/lib/generated_definitions/nl.rb +1 -1
  60. data/lib/generated_definitions/no.rb +1 -1
  61. data/lib/generated_definitions/northamerica.rb +4 -3
  62. data/lib/generated_definitions/nyse.rb +1 -1
  63. data/lib/generated_definitions/nz.rb +1 -1
  64. data/lib/generated_definitions/pe.rb +1 -1
  65. data/lib/generated_definitions/ph.rb +1 -1
  66. data/lib/generated_definitions/pl.rb +1 -1
  67. data/lib/generated_definitions/pt.rb +1 -1
  68. data/lib/generated_definitions/ro.rb +1 -1
  69. data/lib/generated_definitions/rs_cyrl.rb +1 -1
  70. data/lib/generated_definitions/rs_la.rb +1 -1
  71. data/lib/generated_definitions/ru.rb +1 -1
  72. data/lib/generated_definitions/scandinavia.rb +1 -1
  73. data/lib/generated_definitions/se.rb +1 -1
  74. data/lib/generated_definitions/sg.rb +1 -1
  75. data/lib/generated_definitions/si.rb +1 -1
  76. data/lib/generated_definitions/sk.rb +1 -1
  77. data/lib/generated_definitions/southamerica.rb +2 -1
  78. data/lib/generated_definitions/th.rb +1 -1
  79. data/lib/generated_definitions/tn.rb +1 -1
  80. data/lib/generated_definitions/tr.rb +4 -1
  81. data/lib/generated_definitions/tsx.rb +1 -1
  82. data/lib/generated_definitions/ua.rb +1 -1
  83. data/lib/generated_definitions/unitednations.rb +1 -1
  84. data/lib/generated_definitions/ups.rb +1 -1
  85. data/lib/generated_definitions/us.rb +4 -3
  86. data/lib/generated_definitions/ve.rb +1 -1
  87. data/lib/generated_definitions/vn.rb +1 -1
  88. data/lib/generated_definitions/za.rb +1 -1
  89. data/lib/holidays/core_extensions/date.rb +11 -3
  90. data/lib/holidays/date_calculator/hijri_date.rb +10 -7
  91. data/lib/holidays/date_calculator/lunar_date.rb +269 -83
  92. data/lib/holidays/definition/context/generator.rb +27 -2
  93. data/lib/holidays/definition/custom_methods/cl.rb +8 -0
  94. data/lib/holidays/definition/custom_methods/cn.rb +7 -1
  95. data/lib/holidays/definition/custom_methods/registry.rb +2 -0
  96. data/lib/holidays/definition/custom_methods/tr.rb +20 -2
  97. data/lib/holidays/definition/generator/module.rb +1 -1
  98. data/lib/holidays/definition/repository/holidays_by_month.rb +2 -1
  99. data/lib/holidays/errors.rb +5 -0
  100. data/lib/holidays/finder/context/search.rb +67 -23
  101. data/lib/holidays/finder/context/year_holiday.rb +6 -8
  102. data/lib/holidays/finder/rules/in_region.rb +19 -14
  103. data/lib/holidays/version.rb +1 -1
  104. metadata +1 -1
@@ -26,16 +26,19 @@ module Holidays
26
26
  # A fixed Hijri date drifts ~11 days earlier each Gregorian year, so
27
27
  # roughly once every 33 years it falls twice in the same Gregorian year
28
28
  # (once in early January, once in late December). Only the earlier
29
- # occurrence is returned.
29
+ # occurrence is returned; see #gregorian_year_occurrences for both.
30
30
  def gregorian_year_occurrence(gregorian_year, hijri_month, hijri_day)
31
- candidate_hijri_year = gregorian_year - 579
31
+ gregorian_year_occurrences(gregorian_year, hijri_month, hijri_day).first
32
+ end
32
33
 
33
- (candidate_hijri_year - 1..candidate_hijri_year + 1).each do |hijri_year|
34
- date = to_gregorian(hijri_year, hijri_month, hijri_day)
35
- return date if date.year == gregorian_year
36
- end
34
+ # Every occurrence of a fixed Hijri month/day within a Gregorian year,
35
+ # earliest first. Empty when none falls in that year.
36
+ def gregorian_year_occurrences(gregorian_year, hijri_month, hijri_day)
37
+ candidate_hijri_year = gregorian_year - 579
37
38
 
38
- nil
39
+ (candidate_hijri_year - 1..candidate_hijri_year + 1)
40
+ .map { |hijri_year| to_gregorian(hijri_year, hijri_month, hijri_day) }
41
+ .select { |date| date.year == gregorian_year }
39
42
  end
40
43
 
41
44
  private
@@ -1,3 +1,6 @@
1
+ require 'date'
2
+ require 'holidays/errors'
3
+
1
4
  module Holidays
2
5
  module DateCalculator
3
6
  # Copied from https://github.com/sunsidew/ruby_lunardate
@@ -6,8 +9,10 @@ module Holidays
6
9
  attr_accessor :year, :month, :day
7
10
 
8
11
  def to_solar(year, month, day, region)
12
+ validate_year!(year, region)
13
+
9
14
  days = 0
10
- year_diff = year - 1900
15
+ year_diff = year - FIRST_YEAR
11
16
  year_info = CALENDAR_YEAR_INFO_MAP[region]
12
17
 
13
18
  year_diff.times do |year_idx|
@@ -34,6 +39,23 @@ module Holidays
34
39
 
35
40
  private
36
41
 
42
+ def validate_year!(year, region)
43
+ return if SUPPORTED_YEARS.cover?(year)
44
+
45
+ raise Holidays::UnsupportedYearError,
46
+ "lunar calendar data for :#{region} covers lunar years #{SUPPORTED_YEARS}, got #{year}"
47
+ end
48
+
49
+ # Each table holds one row per lunar year from FIRST_YEAR to LAST_YEAR,
50
+ # as printed by script/generate_lunar_table.py (see its header for the
51
+ # method and time zones). Rows before 2050 predate that script; it
52
+ # reproduces all of them.
53
+
54
+ # Vietnamese lunar years 1900..2100, computed from the JPL DE440s ephemeris.
55
+ # Vietnam used UTC+8 until North Vietnam switched to UTC+7 on 1967-08-08.
56
+ # The South kept UTC+8 until 1975, so the two calendars differed in
57
+ # between (Tet 1968 was 01-29 in the North and 01-30 in the South). The
58
+ # North's UTC+7 is used from 1967-08-08 on.
37
59
  VIETNAMESE_LUNAR_YEAR_INFO = [
38
60
  [384, 1, 2, 1, 1, 2, 1, 2, 4, 2, 2, 1, 2].freeze,
39
61
  [354, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 2, 1].freeze,
@@ -49,144 +71,198 @@ module Holidays
49
71
  [384, 2, 1, 2, 1, 1, 4, 1, 2, 2, 1, 2, 2].freeze,
50
72
  [354, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1, 2].freeze,
51
73
  [354, 2, 2, 1, 2, 1, 1, 2, 1, 1, 2, 1, 2].freeze,
52
- [384, 2, 2, 1, 2, 4, 1, 2, 1, 2, 1, 1, 2].freeze,
74
+ [384, 2, 2, 1, 2, 5, 1, 2, 1, 2, 1, 1, 2].freeze,
53
75
  [355, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2].freeze,
54
76
  [354, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1].freeze,
55
77
  [384, 2, 3, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1].freeze,
56
- [355, 2, 1, 1, 2, 1, 2, 1, 2, 2, 2, 1, 2].freeze,
57
- [384, 1, 2, 1, 1, 2, 1, 4, 2, 2, 1, 2, 2].freeze,
78
+ [355, 2, 1, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2].freeze,
79
+ [384, 1, 2, 1, 1, 2, 1, 5, 2, 1, 2, 2, 2].freeze,
58
80
  [354, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2].freeze,
59
81
  [354, 2, 1, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2].freeze,
60
82
  [384, 2, 1, 2, 2, 3, 2, 1, 1, 2, 1, 2, 2].freeze,
61
- [354, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2].freeze,
62
- [354, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 1].freeze,
63
- [385, 2, 1, 2, 4, 2, 1, 2, 2, 1, 2, 1, 2].freeze,
83
+ [354, 1, 2, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2].freeze,
84
+ [354, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 1].freeze,
85
+ [385, 2, 1, 2, 5, 2, 1, 2, 2, 1, 2, 1, 2].freeze,
64
86
  [354, 1, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1].freeze,
65
- [355, 2, 1, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2].freeze,
66
- [384, 1, 4, 1, 2, 1, 1, 2, 2, 1, 2, 2, 2].freeze,
87
+ [355, 2, 1, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2].freeze,
88
+ [384, 1, 4, 1, 2, 1, 1, 2, 1, 2, 2, 2, 2].freeze,
67
89
  [354, 1, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2, 2].freeze,
68
90
  [383, 1, 2, 2, 1, 1, 4, 1, 2, 1, 2, 2, 1].freeze,
69
- [354, 2, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2, 1].freeze,
91
+ [354, 2, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1].freeze,
70
92
  [355, 2, 2, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2].freeze,
71
93
  [384, 1, 2, 2, 1, 6, 1, 2, 1, 2, 1, 1, 2].freeze,
72
- [355, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2].freeze,
94
+ [355, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2].freeze,
73
95
  [354, 1, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1].freeze,
74
- [384, 2, 1, 5, 1, 2, 1, 2, 1, 2, 2, 2, 1].freeze,
96
+ [384, 2, 1, 5, 1, 1, 2, 2, 1, 2, 2, 2, 1].freeze,
75
97
  [354, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2, 2, 1].freeze,
76
98
  [384, 2, 2, 1, 1, 2, 1, 5, 1, 2, 2, 1, 2].freeze,
77
99
  [354, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2, 1, 2].freeze,
78
100
  [354, 2, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1].freeze,
79
101
  [384, 2, 2, 1, 2, 2, 5, 1, 1, 2, 1, 2, 1].freeze,
80
- [355, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 1, 2].freeze,
81
- [355, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2].freeze,
82
- [384, 1, 1, 2, 5, 1, 2, 1, 2, 2, 1, 2, 2].freeze,
102
+ [355, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2].freeze,
103
+ [354, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1].freeze,
104
+ [385, 2, 1, 2, 5, 1, 2, 1, 2, 2, 1, 2, 2].freeze,
83
105
  [354, 1, 1, 2, 1, 1, 2, 1, 2, 2, 2, 1, 2].freeze,
84
106
  [354, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2].freeze,
85
107
  [384, 2, 4, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2].freeze,
86
108
  [354, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2].freeze,
87
- [384, 2, 2, 1, 2, 1, 2, 3, 2, 1, 2, 1, 2].freeze,
88
- [354, 2, 1, 2, 2, 1, 2, 1, 1, 2, 1, 2, 1].freeze,
109
+ [384, 2, 1, 2, 2, 1, 2, 3, 2, 1, 2, 1, 2].freeze,
110
+ [354, 1, 2, 2, 1, 2, 2, 1, 1, 2, 1, 2, 1].freeze,
89
111
  [355, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2].freeze,
90
- [384, 1, 2, 1, 2, 5, 2, 1, 2, 1, 2, 1, 2].freeze,
91
- [355, 1, 2, 1, 1, 2, 2, 1, 2, 2, 1, 2, 2].freeze,
92
- [354, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 2].freeze,
93
- [384, 2, 1, 5, 1, 1, 2, 1, 2, 1, 2, 2, 2].freeze,
112
+ [384, 1, 2, 1, 2, 5, 1, 2, 2, 1, 2, 1, 2].freeze,
113
+ [354, 1, 2, 1, 1, 2, 2, 1, 2, 2, 1, 2, 1].freeze,
114
+ [355, 2, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 2].freeze,
115
+ [384, 1, 2, 5, 1, 1, 2, 1, 2, 1, 2, 2, 2].freeze,
94
116
  [354, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2].freeze,
95
- [384, 2, 1, 2, 1, 2, 1, 1, 4, 2, 1, 2, 2].freeze,
96
- [354, 1, 2, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2].freeze,
117
+ [383, 2, 1, 2, 1, 2, 1, 1, 4, 2, 1, 2, 1].freeze,
118
+ [355, 2, 2, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2].freeze,
97
119
  [354, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1].freeze,
98
120
  [384, 2, 1, 2, 1, 2, 4, 2, 1, 2, 1, 2, 1].freeze,
99
121
  [355, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2].freeze,
100
122
  [354, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 2, 1].freeze,
101
123
  [384, 2, 1, 2, 3, 2, 1, 2, 1, 2, 2, 2, 1].freeze,
102
124
  [355, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 2].freeze,
103
- [354, 1, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2, 2].freeze,
104
- [383, 1, 2, 4, 2, 1, 1, 2, 1, 1, 2, 2, 1].freeze,
105
- [355, 2, 2, 1, 2, 2, 1, 1, 2, 1, 2, 1, 2].freeze,
106
- [384, 1, 2, 2, 1, 2, 1, 4, 2, 1, 2, 1, 2].freeze,
107
- [354, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1].freeze,
108
- [355, 2, 1, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2].freeze,
125
+ [353, 1, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1].freeze,
126
+ [384, 2, 2, 4, 2, 1, 1, 2, 1, 1, 2, 2, 1].freeze,
127
+ [354, 2, 2, 1, 2, 2, 1, 1, 2, 1, 1, 2, 1].freeze,
128
+ [384, 2, 2, 1, 2, 2, 1, 4, 2, 1, 2, 1, 1].freeze,
129
+ [355, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1].freeze,
130
+ [355, 2, 1, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2].freeze,
109
131
  [384, 1, 2, 1, 1, 4, 2, 1, 2, 2, 2, 1, 2].freeze,
110
- [354, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 2, 1].freeze,
111
- [354, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2, 2, 1].freeze,
112
- [384, 2, 2, 1, 4, 1, 2, 1, 1, 2, 2, 1, 2].freeze,
113
- [354, 2, 2, 1, 2, 1, 1, 2, 1, 1, 2, 1, 2].freeze,
114
- [384, 2, 2, 1, 2, 1, 2, 1, 4, 2, 1, 1, 2].freeze,
132
+ [354, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 1, 2].freeze,
133
+ [354, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1, 2].freeze,
134
+ [384, 2, 2, 1, 4, 1, 2, 1, 1, 2, 1, 2, 2].freeze,
135
+ [354, 2, 1, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2].freeze,
136
+ [384, 2, 2, 1, 2, 1, 2, 1, 4, 1, 2, 1, 2].freeze,
115
137
  [354, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 1].freeze,
116
- [355, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1].freeze,
117
- [384, 2, 1, 1, 2, 1, 6, 1, 2, 2, 1, 2, 1].freeze,
138
+ [355, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1].freeze,
139
+ [384, 1, 2, 1, 2, 1, 6, 1, 2, 2, 1, 2, 1].freeze,
118
140
  [355, 2, 1, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2].freeze,
119
141
  [354, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2].freeze,
120
- [384, 2, 1, 2, 3, 2, 1, 1, 2, 2, 1, 2, 2].freeze,
142
+ [384, 2, 1, 2, 3, 2, 1, 1, 2, 1, 2, 2, 2].freeze,
121
143
  [354, 2, 1, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2].freeze,
122
- [384, 2, 1, 2, 2, 1, 1, 2, 1, 1, 4, 2, 2].freeze,
123
- [354, 1, 2, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2].freeze,
124
- [354, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 1].freeze,
125
- [385, 2, 1, 2, 2, 1, 4, 2, 2, 1, 2, 1, 2].freeze,
126
- [354, 1, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1].freeze,
127
- [355, 2, 1, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2].freeze,
128
- [384, 1, 2, 1, 1, 4, 1, 2, 2, 1, 2, 2, 2].freeze,
144
+ [354, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2].freeze,
145
+ [384, 2, 5, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2].freeze,
146
+ [354, 1, 2, 2, 1, 2, 2, 1, 2, 1, 1, 2, 1].freeze,
147
+ [384, 2, 1, 2, 1, 2, 2, 5, 2, 1, 2, 1, 1].freeze,
148
+ [355, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1].freeze,
149
+ [355, 2, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2, 2].freeze,
150
+ [384, 1, 2, 1, 1, 4, 1, 2, 1, 2, 2, 2, 2].freeze,
129
151
  [354, 1, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2, 2].freeze,
130
152
  [354, 1, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2].freeze,
131
153
  [383, 1, 2, 4, 2, 1, 2, 1, 1, 2, 1, 2, 1].freeze,
132
154
  [355, 2, 2, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2].freeze,
133
- [384, 1, 2, 2, 1, 2, 2, 1, 4, 2, 1, 1, 2].freeze,
134
- [355, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2].freeze,
135
- [354, 1, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1].freeze,
136
- [384, 2, 1, 1, 2, 3, 2, 2, 1, 2, 2, 2, 1].freeze,
155
+ [384, 1, 2, 2, 1, 2, 1, 2, 5, 1, 2, 1, 2].freeze,
156
+ [354, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1].freeze,
157
+ [355, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2].freeze,
158
+ [384, 2, 1, 1, 2, 3, 2, 2, 1, 2, 2, 1, 2].freeze,
137
159
  [354, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2, 2, 1].freeze,
138
160
  [354, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1].freeze,
139
- [384, 2, 2, 2, 3, 2, 1, 1, 2, 1, 2, 1, 2].freeze,
161
+ [384, 2, 2, 1, 4, 2, 1, 1, 2, 1, 2, 1, 2].freeze,
140
162
  [354, 2, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1].freeze,
141
163
  [355, 2, 2, 1, 2, 2, 1, 2, 1, 1, 2, 1, 2].freeze,
142
164
  [384, 1, 4, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2].freeze,
143
- [354, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 1].freeze,
144
- [385, 2, 1, 2, 1, 2, 1, 4, 2, 2, 1, 2, 2].freeze,
145
- [354, 1, 1, 2, 1, 1, 2, 1, 2, 2, 2, 1, 2].freeze,
146
- [354, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2].freeze,
147
- [384, 2, 2, 1, 1, 4, 1, 2, 1, 2, 1, 2, 2].freeze,
165
+ [354, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1].freeze,
166
+ [384, 2, 1, 2, 1, 1, 2, 4, 2, 2, 1, 2, 1].freeze,
167
+ [355, 2, 1, 2, 1, 1, 2, 1, 2, 2, 2, 1, 2].freeze,
168
+ [354, 2, 1, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2].freeze,
169
+ [384, 2, 1, 2, 1, 4, 1, 2, 1, 2, 1, 2, 2].freeze,
148
170
  [354, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2].freeze,
149
171
  [354, 2, 1, 2, 2, 1, 2, 1, 1, 2, 1, 2, 1].freeze,
150
- [384, 2, 1, 6, 2, 1, 2, 1, 1, 2, 1, 2, 1].freeze,
151
- [355, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2].freeze,
172
+ [384, 2, 1, 2, 4, 2, 1, 2, 1, 2, 1, 2, 1].freeze,
173
+ [355, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2].freeze,
152
174
  [384, 1, 2, 1, 2, 1, 2, 1, 2, 4, 2, 1, 2].freeze,
153
175
  [354, 1, 2, 1, 1, 2, 1, 2, 2, 2, 1, 2, 1].freeze,
154
176
  [355, 2, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 2].freeze,
155
- [384, 1, 2, 1, 2, 1, 5, 1, 2, 1, 2, 2, 2].freeze, # 2017 has a leap 6th month; previous entry omitted it, shifting every later date
156
- [354, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2].freeze,
157
- [354, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2].freeze,
158
- [384, 2, 1, 2, 4, 2, 1, 1, 2, 1, 2, 1, 2].freeze,
177
+ [384, 1, 2, 1, 2, 1, 5, 1, 2, 1, 2, 2, 2].freeze,
178
+ [354, 1, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2, 2].freeze,
179
+ [354, 1, 2, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2].freeze,
180
+ [384, 1, 2, 2, 4, 2, 1, 1, 2, 1, 1, 2, 2].freeze,
159
181
  [354, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1].freeze,
160
182
  [355, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2].freeze,
161
- [384, 1, 4, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2].freeze,
183
+ [384, 1, 4, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2].freeze,
162
184
  [354, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 2, 1].freeze,
163
185
  [384, 2, 1, 2, 1, 1, 4, 2, 1, 2, 2, 2, 1].freeze,
164
- [355, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 2].freeze,
165
- [354, 1, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2, 2].freeze,
166
- [383, 1, 2, 2, 1, 4, 1, 2, 1, 1, 2, 2, 1].freeze,
167
- [355, 2, 2, 1, 2, 2, 1, 1, 2, 1, 1, 2, 2].freeze,
168
- [354, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1].freeze,
169
- [384, 2, 1, 4, 2, 1, 2, 2, 1, 2, 1, 2, 1].freeze,
170
- [355, 2, 1, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2].freeze,
186
+ [354, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2, 2, 1].freeze,
187
+ [354, 2, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1].freeze,
188
+ [384, 2, 2, 2, 1, 4, 1, 2, 1, 1, 2, 2, 1].freeze,
189
+ [354, 2, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1].freeze,
190
+ [355, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1].freeze,
191
+ [384, 1, 2, 5, 2, 1, 2, 2, 1, 2, 1, 2, 1].freeze,
192
+ [355, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2].freeze,
171
193
  [384, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 4, 2].freeze,
172
- [354, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 2, 1].freeze,
194
+ [354, 1, 2, 1, 1, 2, 1, 1, 2, 2, 2, 1, 2].freeze,
173
195
  [354, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1, 2].freeze,
174
- [384, 2, 2, 1, 2, 1, 5, 1, 1, 2, 2, 1, 2].freeze,
175
- [354, 2, 2, 1, 2, 1, 1, 2, 1, 1, 2, 1, 2].freeze,
176
- [354, 2, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1].freeze,
177
- [384, 2, 2, 1, 2, 4, 2, 1, 2, 1, 2, 1, 1].freeze,
178
- [355, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1].freeze,
179
- [355, 2, 1, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2].freeze,
180
- [384, 1, 4, 1, 2, 1, 2, 1, 2, 2, 2, 1, 2].freeze,
196
+ [384, 2, 2, 1, 2, 1, 5, 1, 1, 2, 1, 2, 2].freeze,
197
+ [354, 2, 1, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2].freeze,
198
+ [354, 2, 1, 2, 2, 1, 2, 1, 2, 1, 1, 2, 1].freeze,
199
+ [384, 2, 2, 1, 2, 4, 2, 1, 2, 1, 1, 2, 1].freeze,
200
+ [355, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1, 2, 1].freeze,
201
+ [355, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 1, 2].freeze,
202
+ [384, 1, 4, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2].freeze,
181
203
  [354, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2].freeze,
182
204
  [384, 2, 1, 2, 1, 1, 2, 3, 2, 1, 2, 2, 2].freeze,
183
205
  [354, 2, 1, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2].freeze,
184
- [354, 2, 1, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2].freeze,
206
+ [354, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2].freeze,
185
207
  [384, 2, 1, 2, 2, 5, 1, 2, 1, 1, 2, 1, 2].freeze,
186
- [354, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 1].freeze,
187
- [355, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1].freeze
208
+ [354, 1, 2, 2, 1, 2, 2, 1, 2, 1, 1, 2, 1].freeze,
209
+ [355, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 2, 1].freeze,
210
+ [384, 1, 2, 5, 1, 2, 1, 2, 2, 1, 2, 2, 1].freeze,
211
+ [355, 1, 2, 1, 2, 1, 1, 2, 2, 1, 2, 2, 2].freeze,
212
+ [383, 1, 2, 1, 1, 2, 1, 1, 4, 2, 2, 2, 1].freeze,
213
+ [355, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2, 2].freeze,
214
+ [354, 1, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2].freeze,
215
+ [383, 1, 2, 2, 1, 2, 5, 1, 1, 2, 1, 2, 1].freeze,
216
+ [355, 2, 2, 1, 2, 2, 1, 2, 1, 1, 2, 1, 2].freeze,
217
+ [354, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1].freeze,
218
+ [384, 2, 1, 2, 5, 1, 2, 2, 1, 2, 1, 2, 1].freeze,
219
+ [355, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2].freeze,
220
+ [354, 1, 2, 1, 2, 1, 1, 2, 1, 2, 2, 2, 1].freeze,
221
+ [384, 2, 2, 3, 2, 1, 1, 2, 1, 2, 2, 2, 1].freeze,
222
+ [354, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2, 1, 2].freeze,
223
+ [384, 2, 2, 1, 2, 1, 2, 3, 2, 1, 2, 1, 2].freeze,
224
+ [354, 2, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1].freeze,
225
+ [355, 2, 2, 1, 2, 2, 1, 1, 2, 1, 2, 1, 2].freeze,
226
+ [384, 1, 2, 1, 2, 4, 2, 1, 2, 1, 2, 1, 2].freeze,
227
+ [354, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1].freeze,
228
+ [355, 2, 1, 2, 1, 1, 2, 2, 1, 2, 2, 1, 2].freeze,
229
+ [384, 1, 2, 1, 4, 1, 2, 1, 2, 2, 2, 1, 2].freeze,
230
+ [354, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2].freeze,
231
+ [384, 2, 1, 2, 1, 2, 1, 1, 4, 2, 1, 2, 2].freeze,
232
+ [354, 2, 1, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2].freeze,
233
+ [354, 2, 1, 2, 2, 1, 2, 1, 1, 2, 1, 1, 2].freeze,
234
+ [384, 2, 1, 2, 2, 1, 4, 2, 1, 2, 1, 2, 1].freeze,
235
+ [355, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2].freeze,
236
+ [354, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1].freeze,
237
+ [384, 2, 1, 2, 3, 2, 1, 2, 2, 2, 1, 2, 1].freeze,
238
+ [355, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 2].freeze,
239
+ [354, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2].freeze,
240
+ [384, 2, 1, 4, 2, 1, 1, 1, 2, 1, 2, 2, 2].freeze,
241
+ [354, 1, 2, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2].freeze,
242
+ [384, 1, 2, 2, 1, 2, 1, 4, 2, 1, 1, 2, 2].freeze,
243
+ [354, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1].freeze,
244
+ [355, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2].freeze,
245
+ [384, 1, 1, 2, 1, 6, 1, 2, 2, 1, 2, 1, 2].freeze,
246
+ [354, 1, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1].freeze,
247
+ [355, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 2].freeze,
248
+ [383, 1, 2, 1, 4, 1, 1, 2, 1, 2, 2, 2, 1].freeze,
249
+ [354, 2, 2, 1, 2, 1, 1, 1, 2, 1, 2, 2, 1].freeze,
250
+ [384, 2, 2, 2, 1, 2, 1, 1, 4, 1, 2, 1, 2].freeze,
251
+ [354, 2, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1].freeze,
252
+ [355, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 1, 2].freeze,
253
+ [384, 1, 2, 1, 2, 2, 5, 2, 1, 2, 1, 2, 1].freeze,
254
+ [355, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2].freeze,
255
+ [354, 1, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 1].freeze,
256
+ [384, 2, 1, 2, 3, 2, 1, 1, 2, 2, 2, 1, 2].freeze,
257
+ [354, 2, 1, 2, 1, 1, 1, 2, 1, 2, 2, 1, 2].freeze,
258
+ [354, 2, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2].freeze,
259
+ [384, 2, 4, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2].freeze,
260
+ [354, 2, 1, 2, 2, 1, 2, 1, 2, 1, 1, 2, 1].freeze
188
261
  ].freeze
189
262
 
263
+ # Korean lunar years 1900..2100. 2050..2100 are computed from the JPL
264
+ # DE440s ephemeris at UTC+9 (KASI's published tables end in 2050).
265
+ # Before 1912 the rows follow the Chinese reckoning at UTC+8.
190
266
  KOREAN_LUNAR_YEAR_INFO = [
191
267
  [384, 1, 2, 1, 1, 2, 1, 2, 4, 2, 2, 1, 2].freeze,
192
268
  [354, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 2, 1].freeze,
@@ -330,17 +406,74 @@ module Holidays
330
406
  [384, 2, 2, 1, 2, 4, 2, 1, 2, 1, 2, 1, 1].freeze,
331
407
  [355, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1].freeze,
332
408
  [355, 2, 1, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2].freeze,
333
- [384, 1, 4, 1, 2, 1, 2, 1, 2, 2, 2, 1, 2].freeze,
409
+ [384, 1, 4, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2].freeze,
334
410
  [354, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2].freeze,
335
411
  [384, 2, 1, 2, 1, 1, 2, 3, 2, 1, 2, 2, 2].freeze,
336
412
  [354, 2, 1, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2].freeze,
337
413
  [354, 2, 1, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2].freeze,
338
414
  [384, 2, 1, 2, 2, 5, 1, 2, 1, 1, 2, 1, 2].freeze,
339
415
  [354, 1, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 1].freeze,
340
- [355, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1].freeze
416
+ [355, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1].freeze,
417
+ [384, 2, 1, 5, 1, 2, 1, 2, 2, 1, 2, 2, 1].freeze,
418
+ [355, 2, 1, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2].freeze,
419
+ [384, 1, 2, 1, 1, 2, 1, 1, 6, 1, 2, 2, 2].freeze,
420
+ [354, 1, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2, 2].freeze,
421
+ [354, 1, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2].freeze,
422
+ [383, 1, 2, 2, 1, 2, 5, 1, 1, 2, 1, 2, 1].freeze,
423
+ [355, 2, 2, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2].freeze,
424
+ [354, 1, 2, 2, 1, 2, 1, 2, 2, 1, 1, 2, 1].freeze,
425
+ [384, 2, 1, 2, 5, 2, 1, 2, 1, 2, 2, 1, 1].freeze,
426
+ [355, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1].freeze,
427
+ [355, 2, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2, 2].freeze,
428
+ [383, 1, 2, 3, 2, 1, 1, 2, 1, 2, 2, 2, 1].freeze,
429
+ [354, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1].freeze,
430
+ [384, 2, 2, 1, 2, 1, 2, 3, 2, 1, 2, 1, 2].freeze,
431
+ [354, 2, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1].freeze,
432
+ [355, 2, 2, 1, 2, 2, 1, 2, 1, 1, 2, 1, 2].freeze,
433
+ [384, 1, 2, 1, 2, 4, 2, 1, 2, 1, 2, 1, 2].freeze,
434
+ [354, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1].freeze,
435
+ [355, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2].freeze,
436
+ [384, 2, 1, 1, 4, 1, 2, 1, 2, 2, 2, 1, 2].freeze,
437
+ [354, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2].freeze,
438
+ [384, 2, 2, 1, 1, 2, 1, 1, 4, 2, 1, 2, 2].freeze,
439
+ [354, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2].freeze,
440
+ [354, 2, 1, 2, 2, 1, 2, 1, 1, 2, 1, 2, 1].freeze,
441
+ [384, 2, 1, 2, 2, 1, 6, 1, 1, 2, 1, 2, 1].freeze,
442
+ [355, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2].freeze,
443
+ [354, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1].freeze,
444
+ [384, 2, 1, 2, 3, 2, 1, 2, 2, 2, 1, 2, 1].freeze,
445
+ [355, 2, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 2].freeze,
446
+ [354, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2].freeze,
447
+ [384, 2, 1, 4, 2, 1, 1, 2, 1, 2, 1, 2, 2].freeze,
448
+ [354, 2, 1, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2].freeze,
449
+ [384, 1, 2, 2, 2, 1, 2, 3, 2, 1, 2, 1, 2].freeze,
450
+ [354, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1].freeze,
451
+ [355, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2].freeze,
452
+ [384, 1, 2, 1, 1, 6, 1, 2, 2, 1, 2, 1, 2].freeze,
453
+ [354, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 2, 1].freeze,
454
+ [355, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 2].freeze,
455
+ [384, 1, 2, 1, 4, 1, 2, 1, 1, 2, 2, 2, 2].freeze,
456
+ [353, 1, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1].freeze,
457
+ [384, 2, 2, 2, 1, 2, 1, 1, 4, 1, 2, 2, 1].freeze,
458
+ [355, 2, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 2].freeze,
459
+ [354, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1].freeze,
460
+ [384, 2, 1, 2, 1, 2, 5, 2, 1, 2, 1, 2, 1].freeze,
461
+ [355, 2, 1, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2].freeze,
462
+ [354, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 2, 1].freeze,
463
+ [384, 2, 1, 2, 3, 2, 1, 2, 1, 2, 2, 2, 1].freeze,
464
+ [354, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1, 2].freeze,
465
+ [354, 2, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2, 1].freeze,
466
+ [384, 2, 2, 4, 2, 1, 1, 2, 1, 1, 2, 1, 2].freeze,
467
+ [354, 2, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1].freeze
341
468
  ].freeze
342
469
 
343
- # Source: https://github.com/hungtcs/traditional-chinese-calendar-database/blob/master/database/all.json
470
+ # Chinese lunar years 1900..2100, used for cn, hk and sg.
471
+ # 1901..2099 agree with the Hong Kong Observatory's Gregorian-Lunar
472
+ # calendar conversion tables (https://www.hko.gov.hk/en/gts/time/conversion.htm).
473
+ # 1900 and 2100, which those tables do not cover in full, are computed
474
+ # from the JPL DE440s ephemeris at UTC+8.
475
+ # 1901..2049 were originally taken from
476
+ # https://github.com/hungtcs/traditional-chinese-calendar-database/blob/master/database/all.json
344
477
  CHINESE_LUNAR_YEAR_INFO = [
345
478
  [384, 1, 2, 1, 1, 2, 1, 2, 4, 2, 2, 1, 2].freeze, # 1900 unavailable, filled with data from Vietnamese calendar
346
479
  [354, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 2, 1].freeze,
@@ -492,9 +625,62 @@ module Holidays
492
625
  [384, 2, 1, 2, 2, 5, 1, 2, 1, 1, 2, 1, 2].freeze,
493
626
  [354, 1, 2, 2, 1, 2, 2, 1, 2, 1, 1, 2, 1].freeze,
494
627
  [355, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2, 1].freeze, # 2049
628
+ [384, 1, 2, 5, 1, 2, 1, 2, 2, 1, 2, 2, 1].freeze,
629
+ [355, 2, 1, 1, 2, 1, 1, 2, 2, 1, 2, 2, 2].freeze,
630
+ [384, 1, 2, 1, 1, 2, 1, 1, 4, 2, 2, 2, 2].freeze,
631
+ [354, 1, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2, 2].freeze,
632
+ [354, 1, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2].freeze,
633
+ [383, 1, 2, 2, 1, 2, 5, 1, 1, 2, 1, 2, 1].freeze,
634
+ [355, 2, 2, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2].freeze,
635
+ [354, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1].freeze,
636
+ [384, 2, 1, 2, 5, 1, 2, 2, 1, 2, 2, 1, 1].freeze,
637
+ [355, 2, 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 1].freeze,
638
+ [354, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2, 2, 1].freeze,
639
+ [384, 2, 2, 3, 2, 1, 1, 2, 1, 2, 2, 2, 1].freeze,
640
+ [354, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2, 2, 1].freeze,
641
+ [384, 2, 2, 1, 2, 1, 2, 3, 2, 1, 2, 1, 2].freeze,
642
+ [354, 2, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1].freeze,
643
+ [355, 2, 2, 1, 2, 2, 1, 2, 1, 1, 2, 1, 2].freeze,
644
+ [384, 1, 2, 1, 2, 4, 2, 1, 2, 1, 2, 1, 2].freeze,
645
+ [354, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1].freeze,
646
+ [355, 2, 1, 2, 1, 1, 2, 2, 1, 2, 2, 1, 2].freeze,
647
+ [384, 1, 2, 1, 4, 1, 2, 1, 2, 2, 2, 1, 2].freeze,
648
+ [354, 1, 2, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2].freeze,
649
+ [384, 2, 1, 2, 1, 2, 1, 1, 4, 2, 1, 2, 2].freeze,
650
+ [354, 2, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2].freeze,
651
+ [354, 2, 1, 2, 2, 1, 2, 1, 1, 2, 1, 2, 1].freeze,
652
+ [384, 2, 1, 2, 2, 1, 4, 2, 1, 2, 1, 2, 1].freeze,
653
+ [355, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2].freeze,
654
+ [354, 1, 2, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1].freeze,
655
+ [384, 2, 1, 2, 3, 2, 1, 2, 2, 2, 1, 2, 1].freeze,
656
+ [355, 2, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 2].freeze,
657
+ [354, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2].freeze,
658
+ [384, 2, 1, 4, 2, 1, 1, 2, 1, 1, 2, 2, 2].freeze,
659
+ [354, 1, 2, 2, 1, 2, 1, 1, 2, 1, 1, 2, 2].freeze,
660
+ [384, 1, 2, 2, 2, 1, 1, 4, 2, 1, 1, 2, 2].freeze,
661
+ [354, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1].freeze,
662
+ [355, 2, 1, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2].freeze,
663
+ [384, 1, 2, 1, 1, 6, 1, 2, 2, 1, 2, 1, 2].freeze,
664
+ [354, 1, 2, 1, 1, 2, 1, 2, 2, 1, 2, 2, 1].freeze,
665
+ [355, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 2].freeze,
666
+ [383, 1, 2, 1, 4, 1, 2, 1, 1, 2, 2, 2, 1].freeze,
667
+ [354, 2, 2, 1, 2, 1, 1, 1, 2, 1, 2, 2, 1].freeze,
668
+ [384, 2, 2, 2, 1, 2, 1, 1, 4, 1, 2, 2, 1].freeze,
669
+ [354, 2, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1].freeze,
670
+ [355, 2, 2, 1, 2, 2, 1, 2, 1, 2, 1, 2, 1].freeze,
671
+ [384, 1, 2, 2, 1, 2, 5, 2, 1, 2, 1, 2, 1].freeze,
672
+ [355, 1, 2, 1, 2, 1, 2, 2, 1, 2, 2, 1, 2].freeze,
673
+ [354, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 2, 1].freeze,
674
+ [384, 2, 1, 2, 3, 2, 1, 1, 2, 2, 2, 1, 2].freeze,
675
+ [354, 2, 1, 2, 1, 1, 1, 2, 1, 2, 2, 1, 2].freeze,
676
+ [354, 2, 2, 1, 2, 1, 1, 1, 2, 1, 2, 1, 2].freeze,
677
+ [384, 2, 4, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2].freeze,
678
+ [354, 2, 2, 1, 2, 1, 2, 1, 2, 1, 1, 2, 1].freeze, # 2100
495
679
  ].freeze
496
680
 
497
- MAX_YEAR_NUMBER = 150
681
+ FIRST_YEAR = 1900
682
+ LAST_YEAR = 2100
683
+ SUPPORTED_YEARS = (FIRST_YEAR..LAST_YEAR).freeze
498
684
 
499
685
  # Given the region, CALENDAR_YEAR_INFO_MAP looks up the date
500
686
  # table and uses it in the calculation
@@ -117,9 +117,11 @@ module Holidays
117
117
  rule[:regions] = rule[:regions].collect(&:to_sym)
118
118
  regions << rule[:regions]
119
119
 
120
+ parse_excluded_regions!(rule)
121
+
120
122
  exists = false
121
123
  rules_by_month[month].each do |ex|
122
- 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[:function_modifier] == rule[:function_modifier] and ex[:observed] == rule[:observed] and ex[:year_ranges] == rule[:year_ranges]
124
+ 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[:function_modifier] == rule[:function_modifier] and ex[:observed] == rule[:observed] and ex[:year_ranges] == rule[:year_ranges] and ex[:excluded_regions] == rule[:excluded_regions]
123
125
  ex[:regions] << rule[:regions].flatten
124
126
  exists = true
125
127
  end
@@ -145,6 +147,23 @@ module Holidays
145
147
  [regions, rules_by_month]
146
148
  end
147
149
 
150
+ # Symbolizes a rule's optional excluded_regions, dropping the key when
151
+ # it is empty so such a rule is identical to one without it. Every
152
+ # excluded region must be a strict descendant of one of the rule's own
153
+ # regions (us_hi under us), otherwise it could never take effect.
154
+ def parse_excluded_regions!(rule)
155
+ excluded = Array(rule.delete(:excluded_regions)).collect(&:to_sym)
156
+ return if excluded.empty?
157
+
158
+ excluded.each do |e|
159
+ next if rule[:regions].any? { |r| e.to_s.start_with?("#{r}_") }
160
+
161
+ raise ArgumentError, "Excluded region '#{e}' in '#{rule[:name]}' must be a subregion of one of its regions #{rule[:regions]}"
162
+ end
163
+
164
+ rule[:excluded_regions] = excluded
165
+ end
166
+
148
167
  #FIXME This should really be split out and tested with its own unit tests.
149
168
  def generate_month_definition_strings(rules_by_month, parsed_custom_methods)
150
169
  month_strings = []
@@ -194,7 +213,13 @@ module Holidays
194
213
  end
195
214
 
196
215
  # shouldn't allow the same region twice
197
- string << ":name => \"#{rule[:name]}\", :regions => [:" + rule[:regions].uniq.join(', :') + "]}"
216
+ string << ":name => \"#{rule[:name]}\", :regions => [:" + rule[:regions].uniq.join(', :') + "]"
217
+
218
+ if rule[:excluded_regions]
219
+ string << ", :excluded_regions => [:" + rule[:excluded_regions].uniq.join(', :') + "]"
220
+ end
221
+
222
+ string << "}"
198
223
  rule_strings << string
199
224
  end
200
225
  month_string << rule_strings.join(",\n ") + "]"
@@ -7,6 +7,14 @@ module Holidays
7
7
  # +methods:+ block in definitions/cl.yaml.
8
8
  module CL
9
9
  class << self
10
+ def indigenous_peoples_day_cl(year)
11
+ return Date.civil(2021, 6, 21) if year == 2021
12
+ raise IndexError, 'Out of range' unless (2022..2099).cover?(year)
13
+
14
+ day = 21.019 + 0.242194 * (year - 1980) - ((year - 1980) / 4).floor
15
+ Date.civil(year, 6, day.floor)
16
+ end
17
+
10
18
  def st_peter_st_paul_cl(year)
11
19
  date = Date.civil(year, 6, 29)
12
20
  if [2,3,4].include?(date.wday)
@@ -1,4 +1,5 @@
1
1
  require 'date'
2
+ require 'holidays/errors'
2
3
 
3
4
  module Holidays
4
5
  module Definition
@@ -11,7 +12,12 @@ module Holidays
11
12
  # which lands on 4 or 5 April. This is the standard solar-term
12
13
  # approximation; the century constant shifts between the 20th and
13
14
  # 21st centuries.
15
+ #
16
+ # The formula is off by one day in 2100 only: the sun reaches 15
17
+ # degrees at 00:45 on 5 April 2100, Beijing time (JPL DE440s).
14
18
  def cn_qingming(year)
19
+ return Date.civil(2100, 4, 5) if year == 2100
20
+
15
21
  constant =
16
22
  case year
17
23
  when 1900..1999
@@ -19,7 +25,7 @@ module Holidays
19
25
  when 2000..2099
20
26
  4.81
21
27
  else
22
- raise IndexError.new("Out of range")
28
+ raise Holidays::UnsupportedYearError, "cn_qingming covers 1900..2100, got #{year}"
23
29
  end
24
30
  y = year % 100
25
31
  Date.civil(year, 4, (y * 0.2422 + constant).floor - (y / 4))
@@ -60,6 +60,7 @@ module Holidays
60
60
  "hari_raya_puasa(year)" => MY.method(:hari_raya_puasa).to_proc,
61
61
  "hobart_show_day(year)" => AU.method(:hobart_show_day).to_proc,
62
62
  "ie_st_brigids_day(year)" => IE.method(:ie_st_brigids_day).to_proc,
63
+ "indigenous_peoples_day_cl(year)" => CL.method(:indigenous_peoples_day_cl).to_proc,
63
64
  "independence_day(region, date)" => US.method(:independence_day).to_proc,
64
65
  "is_sumardagurinn_fyrsti(year)" => IS.method(:is_sumardagurinn_fyrsti).to_proc,
65
66
  "jp_citizens_holiday(year)" => JP.method(:jp_citizens_holiday).to_proc,
@@ -93,6 +94,7 @@ module Holidays
93
94
  "qld_queens_bday_october(year)" => AU.method(:qld_queens_bday_october).to_proc,
94
95
  "qld_queens_birthday_june(year)" => AU.method(:qld_queens_birthday_june).to_proc,
95
96
  "ramadan_feast(year)" => TR.method(:ramadan_feast).to_proc,
97
+ "ramadan_feast_second_in_year(year)" => TR.method(:ramadan_feast_second_in_year).to_proc,
96
98
  "rosh_hashanah(year)" => US.method(:rosh_hashanah).to_proc,
97
99
  "sacrifice_feast(year)" => TR.method(:sacrifice_feast).to_proc,
98
100
  "se_alla_helgons_dag(year)" => SE.method(:se_alla_helgons_dag).to_proc,