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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/README.md +11 -8
- data/lib/generated_definitions/REGIONS.rb +3 -3
- data/lib/generated_definitions/ar.rb +1 -1
- data/lib/generated_definitions/at.rb +1 -1
- data/lib/generated_definitions/au.rb +2 -2
- data/lib/generated_definitions/be_fr.rb +1 -1
- data/lib/generated_definitions/be_nl.rb +1 -1
- data/lib/generated_definitions/bg.rb +1 -1
- data/lib/generated_definitions/br.rb +1 -1
- data/lib/generated_definitions/by.rb +1 -1
- data/lib/generated_definitions/ca.rb +1 -1
- data/lib/generated_definitions/ch.rb +1 -1
- data/lib/generated_definitions/cl.rb +3 -2
- data/lib/generated_definitions/cn.rb +1 -1
- data/lib/generated_definitions/co.rb +1 -1
- data/lib/generated_definitions/cr.rb +1 -1
- data/lib/generated_definitions/cy.rb +1 -1
- data/lib/generated_definitions/cz.rb +1 -1
- data/lib/generated_definitions/de.rb +1 -1
- data/lib/generated_definitions/dk.rb +1 -1
- data/lib/generated_definitions/ecbtarget.rb +1 -1
- data/lib/generated_definitions/ee.rb +1 -1
- data/lib/generated_definitions/es.rb +1 -1
- data/lib/generated_definitions/europe.rb +1 -1
- data/lib/generated_definitions/federalreserve.rb +1 -1
- data/lib/generated_definitions/federalreservebanks.rb +1 -1
- data/lib/generated_definitions/fedex.rb +1 -1
- data/lib/generated_definitions/fi.rb +1 -1
- data/lib/generated_definitions/fr.rb +1 -1
- data/lib/generated_definitions/gb.rb +1 -1
- data/lib/generated_definitions/ge.rb +1 -1
- data/lib/generated_definitions/gr.rb +1 -1
- data/lib/generated_definitions/hk.rb +1 -1
- data/lib/generated_definitions/hr.rb +1 -1
- data/lib/generated_definitions/hu.rb +1 -1
- data/lib/generated_definitions/ie.rb +1 -1
- data/lib/generated_definitions/il.rb +1 -1
- data/lib/generated_definitions/in.rb +1 -1
- data/lib/generated_definitions/is.rb +1 -1
- data/lib/generated_definitions/it.rb +1 -1
- data/lib/generated_definitions/jp.rb +1 -1
- data/lib/generated_definitions/ke.rb +1 -1
- data/lib/generated_definitions/kr.rb +1 -1
- data/lib/generated_definitions/kz.rb +1 -1
- data/lib/generated_definitions/li.rb +1 -1
- data/lib/generated_definitions/lt.rb +1 -1
- data/lib/generated_definitions/lu.rb +1 -1
- data/lib/generated_definitions/lv.rb +1 -1
- data/lib/generated_definitions/ma.rb +1 -1
- data/lib/generated_definitions/mc.rb +1 -1
- data/lib/generated_definitions/mt_en.rb +1 -1
- data/lib/generated_definitions/mt_mt.rb +1 -1
- data/lib/generated_definitions/mx.rb +1 -1
- data/lib/generated_definitions/my.rb +1 -1
- data/lib/generated_definitions/nerc.rb +1 -1
- data/lib/generated_definitions/ng.rb +1 -1
- data/lib/generated_definitions/nl.rb +1 -1
- data/lib/generated_definitions/no.rb +1 -1
- data/lib/generated_definitions/northamerica.rb +4 -3
- data/lib/generated_definitions/nyse.rb +1 -1
- data/lib/generated_definitions/nz.rb +1 -1
- data/lib/generated_definitions/pe.rb +1 -1
- data/lib/generated_definitions/ph.rb +1 -1
- data/lib/generated_definitions/pl.rb +1 -1
- data/lib/generated_definitions/pt.rb +1 -1
- data/lib/generated_definitions/ro.rb +1 -1
- data/lib/generated_definitions/rs_cyrl.rb +1 -1
- data/lib/generated_definitions/rs_la.rb +1 -1
- data/lib/generated_definitions/ru.rb +1 -1
- data/lib/generated_definitions/scandinavia.rb +1 -1
- data/lib/generated_definitions/se.rb +1 -1
- data/lib/generated_definitions/sg.rb +1 -1
- data/lib/generated_definitions/si.rb +1 -1
- data/lib/generated_definitions/sk.rb +1 -1
- data/lib/generated_definitions/southamerica.rb +2 -1
- data/lib/generated_definitions/th.rb +1 -1
- data/lib/generated_definitions/tn.rb +1 -1
- data/lib/generated_definitions/tr.rb +4 -1
- data/lib/generated_definitions/tsx.rb +1 -1
- data/lib/generated_definitions/ua.rb +1 -1
- data/lib/generated_definitions/unitednations.rb +1 -1
- data/lib/generated_definitions/ups.rb +1 -1
- data/lib/generated_definitions/us.rb +4 -3
- data/lib/generated_definitions/ve.rb +1 -1
- data/lib/generated_definitions/vn.rb +1 -1
- data/lib/generated_definitions/za.rb +1 -1
- data/lib/holidays/core_extensions/date.rb +11 -3
- data/lib/holidays/date_calculator/hijri_date.rb +10 -7
- data/lib/holidays/date_calculator/lunar_date.rb +269 -83
- data/lib/holidays/definition/context/generator.rb +27 -2
- data/lib/holidays/definition/custom_methods/cl.rb +8 -0
- data/lib/holidays/definition/custom_methods/cn.rb +7 -1
- data/lib/holidays/definition/custom_methods/registry.rb +2 -0
- data/lib/holidays/definition/custom_methods/tr.rb +20 -2
- data/lib/holidays/definition/generator/module.rb +1 -1
- data/lib/holidays/definition/repository/holidays_by_month.rb +2 -1
- data/lib/holidays/errors.rb +5 -0
- data/lib/holidays/finder/context/search.rb +67 -23
- data/lib/holidays/finder/context/year_holiday.rb +6 -8
- data/lib/holidays/finder/rules/in_region.rb +19 -14
- data/lib/holidays/version.rb +1 -1
- metadata +1 -1
|
@@ -12,6 +12,10 @@ module Holidays
|
|
|
12
12
|
# day (2016 Ramazan Bayramı, two days) before the arithmetic result;
|
|
13
13
|
# DIYANET_OVERRIDES pins those years to the proclaimed date. Years with
|
|
14
14
|
# no entry fall back to the calculation. See definitions#377.
|
|
15
|
+
#
|
|
16
|
+
# ramadan_feast only returns the first occurrence of a Gregorian year;
|
|
17
|
+
# ramadan_feast_second_in_year returns the second one in the rare years
|
|
18
|
+
# that have two (2033), and nil otherwise.
|
|
15
19
|
module TR
|
|
16
20
|
SHAWWAL = 10
|
|
17
21
|
DHU_AL_HIJJAH = 12
|
|
@@ -19,7 +23,7 @@ module Holidays
|
|
|
19
23
|
# Proclaimed first days that differ from the arithmetic calendar,
|
|
20
24
|
# keyed by [feast, gregorian_year]. Sourced from the Diyanet dates
|
|
21
25
|
# that the definition file previously carried as a fixed table, plus
|
|
22
|
-
# https://vakithesaplama.diyanet.gov.tr/resmitatiller.php for 2021-
|
|
26
|
+
# https://vakithesaplama.diyanet.gov.tr/resmitatiller.php for 2021-2035.
|
|
23
27
|
DIYANET_OVERRIDES = {
|
|
24
28
|
[:ramadan_feast, 2014] => Date.new(2014, 7, 28),
|
|
25
29
|
[:ramadan_feast, 2015] => Date.new(2015, 7, 17),
|
|
@@ -32,6 +36,9 @@ module Holidays
|
|
|
32
36
|
[:ramadan_feast, 2027] => Date.new(2027, 3, 9),
|
|
33
37
|
[:ramadan_feast, 2028] => Date.new(2028, 2, 26),
|
|
34
38
|
[:ramadan_feast, 2030] => Date.new(2030, 2, 4),
|
|
39
|
+
[:ramadan_feast, 2031] => Date.new(2031, 1, 24),
|
|
40
|
+
[:ramadan_feast, 2033] => Date.new(2033, 1, 2),
|
|
41
|
+
[:ramadan_feast, 2035] => Date.new(2035, 12, 1),
|
|
35
42
|
|
|
36
43
|
[:sacrifice_feast, 2014] => Date.new(2014, 10, 4),
|
|
37
44
|
[:sacrifice_feast, 2016] => Date.new(2016, 9, 12),
|
|
@@ -44,6 +51,8 @@ module Holidays
|
|
|
44
51
|
[:sacrifice_feast, 2025] => Date.new(2025, 6, 6),
|
|
45
52
|
[:sacrifice_feast, 2027] => Date.new(2027, 5, 16),
|
|
46
53
|
[:sacrifice_feast, 2030] => Date.new(2030, 4, 13),
|
|
54
|
+
[:sacrifice_feast, 2031] => Date.new(2031, 4, 2),
|
|
55
|
+
[:sacrifice_feast, 2033] => Date.new(2033, 3, 11),
|
|
47
56
|
}.freeze
|
|
48
57
|
|
|
49
58
|
class << self
|
|
@@ -51,6 +60,11 @@ module Holidays
|
|
|
51
60
|
feast(:ramadan_feast, year, SHAWWAL, 1)
|
|
52
61
|
end
|
|
53
62
|
|
|
63
|
+
def ramadan_feast_second_in_year(year)
|
|
64
|
+
occurrences = hijri.gregorian_year_occurrences(year, SHAWWAL, 1)
|
|
65
|
+
occurrences.last if occurrences.size > 1
|
|
66
|
+
end
|
|
67
|
+
|
|
54
68
|
def sacrifice_feast(year)
|
|
55
69
|
feast(:sacrifice_feast, year, DHU_AL_HIJJAH, 10)
|
|
56
70
|
end
|
|
@@ -59,7 +73,11 @@ module Holidays
|
|
|
59
73
|
|
|
60
74
|
def feast(name, year, hijri_month, hijri_day)
|
|
61
75
|
DIYANET_OVERRIDES[[name, year]] ||
|
|
62
|
-
|
|
76
|
+
hijri.gregorian_year_occurrence(year, hijri_month, hijri_day)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def hijri
|
|
80
|
+
Holidays::Factory::DateCalculator.hijri_date
|
|
63
81
|
end
|
|
64
82
|
end
|
|
65
83
|
end
|
|
@@ -49,7 +49,8 @@ module Holidays
|
|
|
49
49
|
existing_def[:function_modifier] == target_def[:function_modifier] &&
|
|
50
50
|
existing_def[:type] == target_def[:type] &&
|
|
51
51
|
existing_def[:observed] == target_def[:observed] &&
|
|
52
|
-
existing_def[:year_ranges] == target_def[:year_ranges]
|
|
52
|
+
existing_def[:year_ranges] == target_def[:year_ranges] &&
|
|
53
|
+
existing_def[:excluded_regions] == target_def[:excluded_regions]
|
|
53
54
|
end
|
|
54
55
|
end
|
|
55
56
|
end
|
data/lib/holidays/errors.rb
CHANGED
|
@@ -8,4 +8,9 @@ module Holidays
|
|
|
8
8
|
class InvalidRegion < Error; end
|
|
9
9
|
|
|
10
10
|
class DefinitionTestError < Error; end
|
|
11
|
+
|
|
12
|
+
# Raised when a calculation needs data for a year outside the range its
|
|
13
|
+
# tables or formula support, e.g. a lunar date past the end of the lunar
|
|
14
|
+
# calendar tables.
|
|
15
|
+
class UnsupportedYearError < Error; end
|
|
11
16
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require 'holidays/errors'
|
|
2
|
+
|
|
1
3
|
module Holidays
|
|
2
4
|
module Finder
|
|
3
5
|
module Context
|
|
@@ -14,29 +16,11 @@ module Holidays
|
|
|
14
16
|
|
|
15
17
|
holidays = []
|
|
16
18
|
dates_driver.each do |year, months|
|
|
17
|
-
months.each do |month|
|
|
18
|
-
next unless
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
if h[:year_ranges]
|
|
24
|
-
next unless @rules[:year_range].call(year, h[:year_ranges])
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
dates = if h[:function]
|
|
28
|
-
custom_holidays(year, month, h, regions)
|
|
29
|
-
else
|
|
30
|
-
date = build_date(year, month, h, regions)
|
|
31
|
-
date ? [date] : []
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
dates.each do |d|
|
|
35
|
-
if observed_set?(options) && h[:observed]
|
|
36
|
-
d = build_observed_date(d, regions, h)
|
|
37
|
-
end
|
|
38
|
-
holidays << {:date => d, :name => h[:name], :regions => h[:regions]}
|
|
39
|
-
end
|
|
19
|
+
candidates(months).each do |month, h|
|
|
20
|
+
next unless applicable?(year, h, regions, options)
|
|
21
|
+
|
|
22
|
+
year_dates(year, months, month, h, regions, options).each do |d|
|
|
23
|
+
holidays << {:date => d, :name => h[:name], :regions => h[:regions]}
|
|
40
24
|
end
|
|
41
25
|
end
|
|
42
26
|
end
|
|
@@ -61,6 +45,66 @@ module Holidays
|
|
|
61
45
|
end
|
|
62
46
|
end
|
|
63
47
|
|
|
48
|
+
# Returns [month, definition] pairs to evaluate for one year of the dates
|
|
49
|
+
# driver. Fixed-date definitions only matter in the driver's months, but a
|
|
50
|
+
# function (e.g. a lunar date filed under its lunar month) can land several
|
|
51
|
+
# months away from the month it is filed under, so every function definition
|
|
52
|
+
# is evaluated, once, regardless of its month.
|
|
53
|
+
# See https://github.com/holidays/holidays/issues/519
|
|
54
|
+
def candidates(months)
|
|
55
|
+
by_month = @holidays_by_month_repo.all
|
|
56
|
+
|
|
57
|
+
in_driver = months.flat_map do |month|
|
|
58
|
+
(by_month[month] || []).map { |h| [month, h] }
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
outside_driver = (by_month.keys - months).sort.flat_map do |month|
|
|
62
|
+
by_month[month].select { |h| h[:function] }.map { |h| [month, h] }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
in_driver + outside_driver
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# A year that only pads the query with a border month (see
|
|
69
|
+
# DatesDriverBuilder#add_border_months) may lie past the data a
|
|
70
|
+
# calculation supports, e.g. lunar year 2101. Dates of such a year are
|
|
71
|
+
# outside the query anyway, so they are skipped rather than failing
|
|
72
|
+
# the query. A year the query actually covers still raises.
|
|
73
|
+
def year_dates(year, months, month, h, regions, options)
|
|
74
|
+
holiday_dates(year, month, h, regions, options)
|
|
75
|
+
rescue Holidays::UnsupportedYearError
|
|
76
|
+
raise unless border_padding?(months)
|
|
77
|
+
|
|
78
|
+
[]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Every date in the query adds its own month and a neighbouring one to
|
|
82
|
+
# its year, so a year holding a single month (besides the variable
|
|
83
|
+
# month 0) is only there as border padding.
|
|
84
|
+
def border_padding?(months)
|
|
85
|
+
(months - [0]).size == 1
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def applicable?(year, h, regions, options)
|
|
89
|
+
return false if informal_type?(h[:type]) && !informal_set?(options)
|
|
90
|
+
return false unless @rules[:in_region].call(regions, h[:regions], h[:excluded_regions])
|
|
91
|
+
return true unless h[:year_ranges]
|
|
92
|
+
|
|
93
|
+
@rules[:year_range].call(year, h[:year_ranges])
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def holiday_dates(year, month, h, regions, options)
|
|
97
|
+
dates = if h[:function]
|
|
98
|
+
custom_holidays(year, month, h, regions)
|
|
99
|
+
else
|
|
100
|
+
[build_date(year, month, h, regions)].compact
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
return dates unless observed_set?(options) && h[:observed]
|
|
104
|
+
|
|
105
|
+
dates.map { |d| build_observed_date(d, regions, h) }
|
|
106
|
+
end
|
|
107
|
+
|
|
64
108
|
def informal_type?(type)
|
|
65
109
|
type && [:informal, 'informal'].include?(type)
|
|
66
110
|
end
|
|
@@ -13,15 +13,13 @@ module Holidays
|
|
|
13
13
|
|
|
14
14
|
regions, observed, informal = @options_parser.call(options)
|
|
15
15
|
|
|
16
|
-
#
|
|
17
|
-
# the next
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
# This is matching what was in holidays.rb currently so I'm keeping it. -pp
|
|
22
|
-
dates_driver = @dates_driver_builder.call(from_date, from_date >> 12)
|
|
23
|
-
|
|
16
|
+
# The driver stops at to_date; the dates driver still adds January of
|
|
17
|
+
# the next year as a border month. Searching a full 12 months from
|
|
18
|
+
# from_date would make the next year a searched year rather than
|
|
19
|
+
# border padding, so e.g. year_holidays for 2100 would need lunar
|
|
20
|
+
# data for 2101.
|
|
24
21
|
to_date = Date.civil(from_date.year, 12, 31)
|
|
22
|
+
dates_driver = @dates_driver_builder.call(from_date, to_date)
|
|
25
23
|
holidays = []
|
|
26
24
|
ret_holidays = []
|
|
27
25
|
opts = gather_options(observed, informal)
|
|
@@ -3,26 +3,31 @@ module Holidays
|
|
|
3
3
|
module Rules
|
|
4
4
|
class InRegion
|
|
5
5
|
class << self
|
|
6
|
-
|
|
6
|
+
# Each requested region is checked on its own. It qualifies when one
|
|
7
|
+
# of the available regions is the region itself or one of its
|
|
8
|
+
# ancestors (us for us_ca) and none of the excluded regions is. The
|
|
9
|
+
# rule matches when any requested region qualifies. :any always
|
|
10
|
+
# matches, whatever is excluded.
|
|
11
|
+
def call(requested, available, excluded = nil)
|
|
7
12
|
return true if requested.include?(:any)
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
# symbol and check for both.
|
|
11
|
-
requested = requested.collect do |r|
|
|
12
|
-
if r.to_s.include?('_')
|
|
13
|
-
chunks = r.to_s.split('_')
|
|
14
|
+
excluded ||= []
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
r
|
|
20
|
-
end
|
|
16
|
+
requested.any? do |region|
|
|
17
|
+
lineage = lineage(region)
|
|
18
|
+
|
|
19
|
+
(available & lineage).any? && (excluded & lineage).empty?
|
|
21
20
|
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
# The region and all of its parents, e.g. :us_ca_xx gives
|
|
26
|
+
# [:us, :us_ca, :us_ca_xx].
|
|
27
|
+
def lineage(region)
|
|
28
|
+
chunks = region.to_s.split('_')
|
|
24
29
|
|
|
25
|
-
|
|
30
|
+
1.upto(chunks.length).map { |n| chunks.first(n).join('_').to_sym }
|
|
26
31
|
end
|
|
27
32
|
end
|
|
28
33
|
end
|
data/lib/holidays/version.rb
CHANGED