holidays 4.6.0 → 4.7.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 +5 -0
- data/CONTRIBUTING.md +5 -5
- data/Makefile +29 -0
- data/README.md +13 -1
- data/Rakefile +2 -2
- data/definitions/au.yaml +12 -9
- data/definitions/ca.yaml +17 -2
- data/definitions/ch.yaml +1 -1
- data/definitions/index.yaml +3 -0
- data/definitions/is.yaml +1 -1
- data/definitions/jp.yaml +19 -14
- data/definitions/kr.yaml +282 -0
- data/definitions/lu.yaml +56 -0
- data/definitions/my.yaml +51 -0
- data/definitions/ups.yaml +1 -1
- data/definitions/us.yaml +1 -1
- data/lib/generated_definitions/MANIFEST +3 -0
- data/lib/generated_definitions/REGIONS.rb +1 -1
- data/lib/generated_definitions/au.rb +11 -8
- data/lib/generated_definitions/ca.rb +1 -1
- data/lib/generated_definitions/ch.rb +1 -1
- data/lib/generated_definitions/europe.rb +2 -2
- data/lib/generated_definitions/is.rb +1 -1
- data/lib/generated_definitions/jp.rb +13 -15
- data/lib/generated_definitions/kr.rb +248 -0
- data/lib/generated_definitions/lu.rb +39 -0
- data/lib/generated_definitions/my.rb +36 -0
- data/lib/generated_definitions/north_america.rb +2 -2
- data/lib/generated_definitions/scandinavia.rb +1 -1
- data/lib/generated_definitions/ups.rb +1 -1
- data/lib/generated_definitions/us.rb +1 -1
- data/lib/holidays.rb +29 -51
- data/lib/holidays/core_extensions/date.rb +1 -1
- data/lib/holidays/definition/context/function_processor.rb +86 -0
- data/lib/holidays/definition/context/generator.rb +31 -6
- data/lib/holidays/definition/parser/custom_method.rb +1 -3
- data/lib/holidays/definition/repository/holidays_by_month.rb +1 -1
- data/lib/holidays/definition/validator/region.rb +1 -3
- data/lib/holidays/errors.rb +1 -0
- data/lib/holidays/factory/date_calculator.rb +37 -0
- data/lib/holidays/factory/definition.rb +96 -0
- data/lib/holidays/factory/finder.rb +70 -0
- data/lib/holidays/finder/context/between.rb +43 -0
- data/lib/holidays/{use_case → finder}/context/dates_driver_builder.rb +6 -4
- data/lib/holidays/finder/context/next_holiday.rb +57 -0
- data/lib/holidays/{option → finder}/context/parse_options.rb +6 -8
- data/lib/holidays/finder/context/search.rb +86 -0
- data/lib/holidays/finder/context/year_holiday.rb +57 -0
- data/lib/holidays/finder/rules/in_region.rb +23 -0
- data/lib/holidays/finder/rules/year_range.rb +82 -0
- data/lib/holidays/load_all_definitions.rb +7 -5
- data/lib/holidays/version.rb +1 -1
- data/test/coverage_report.rb +7 -0
- data/test/defs/test_defs_au.rb +1 -1
- data/test/defs/test_defs_ca.rb +16 -1
- data/test/defs/test_defs_jp.rb +4 -0
- data/test/defs/test_defs_kr.rb +26 -0
- data/test/defs/test_defs_lu.rb +24 -0
- data/test/defs/test_defs_my.rb +20 -0
- data/test/defs/test_defs_north_america.rb +16 -1
- data/test/holidays/core_extensions/test_date_time.rb +7 -7
- data/test/holidays/definition/context/test_function_processor.rb +175 -0
- data/test/holidays/definition/context/test_generator.rb +18 -11
- data/test/holidays/definition/parser/test_custom_method.rb +2 -2
- data/test/holidays/definition/repository/test_proc_result_cache.rb +1 -1
- data/test/holidays/{test_date_calculator_factory.rb → factory/test_date_calculator.rb} +3 -3
- data/test/holidays/factory/test_definition.rb +53 -0
- data/test/holidays/factory/test_finder.rb +25 -0
- data/test/holidays/finder/context/test_between.rb +172 -0
- data/test/holidays/{use_case → finder}/context/test_dates_driver_builder.rb +2 -2
- data/test/holidays/finder/context/test_next_holiday.rb +156 -0
- data/test/holidays/{option → finder}/context/test_parse_options.rb +9 -9
- data/test/holidays/finder/context/test_search.rb +203 -0
- data/test/holidays/finder/context/test_year_holiday.rb +202 -0
- data/test/holidays/finder/rules/test_in_region.rb +38 -0
- data/test/holidays/finder/rules/test_year_range.rb +170 -0
- data/test/integration/README.md +9 -0
- data/test/{test_all_regions.rb → integration/test_all_regions.rb} +16 -2
- data/test/{test_custom_holidays.rb → integration/test_custom_holidays.rb} +2 -2
- data/test/{test_custom_year_range_holidays.rb → integration/test_custom_year_range_holidays.rb} +1 -1
- data/test/{test_holidays.rb → integration/test_holidays.rb} +43 -32
- data/test/{test_holidays_between.rb → integration/test_holidays_between.rb} +8 -16
- data/test/{test_multiple_regions.rb → integration/test_multiple_regions.rb} +1 -1
- data/test/test_helper.rb +3 -4
- metadata +67 -39
- data/benchmark.rb +0 -8
- data/lib/holidays/date_calculator_factory.rb +0 -35
- data/lib/holidays/definition_factory.rb +0 -86
- data/lib/holidays/option_factory.rb +0 -15
- data/lib/holidays/use_case/context/between.rb +0 -45
- data/lib/holidays/use_case/context/context_common.rb +0 -123
- data/lib/holidays/use_case/context/next_holiday.rb +0 -54
- data/lib/holidays/use_case/context/year_holiday.rb +0 -51
- data/lib/holidays/use_case_factory.rb +0 -41
- data/test/holidays/test_definition_factory.rb +0 -49
- data/test/holidays/test_option_factory.rb +0 -9
- data/test/holidays/test_use_case_factory.rb +0 -13
- data/test/holidays/use_case/context/test_between.rb +0 -77
@@ -0,0 +1,39 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Holidays
|
3
|
+
# This file is generated by the Ruby Holidays gem.
|
4
|
+
#
|
5
|
+
# Definitions loaded: definitions/lu.yaml
|
6
|
+
#
|
7
|
+
# To use the definitions in this file, load it right after you load the
|
8
|
+
# Holiday gem:
|
9
|
+
#
|
10
|
+
# require 'holidays'
|
11
|
+
# require 'generated_definitions/lu'
|
12
|
+
#
|
13
|
+
# All the definitions are available at https://github.com/holidays/holidays
|
14
|
+
module LU # :nodoc:
|
15
|
+
def self.defined_regions
|
16
|
+
[:lu]
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.holidays_by_month
|
20
|
+
{
|
21
|
+
0 => [{:function => "easter(year)", :function_arguments => [:year], :function_modifier => 1, :name => "Ouschterméindeg", :regions => [:lu]},
|
22
|
+
{:function => "easter(year)", :function_arguments => [:year], :function_modifier => 39, :name => "Christi Himmelfaart", :regions => [:lu]},
|
23
|
+
{:function => "easter(year)", :function_arguments => [:year], :function_modifier => 49, :name => "Péngschtméindeg", :regions => [:lu]}],
|
24
|
+
1 => [{:mday => 1, :name => "Neijoerschdag", :regions => [:lu]}],
|
25
|
+
6 => [{:mday => 23, :name => "Nationalfeierdag", :regions => [:lu]}],
|
26
|
+
8 => [{:mday => 15, :name => "Léiffrawëschdag", :regions => [:lu]}],
|
27
|
+
11 => [{:mday => 1, :name => "Allerhellgen", :regions => [:lu]}],
|
28
|
+
12 => [{:mday => 25, :name => "Chrëschtdag", :regions => [:lu]},
|
29
|
+
{:mday => 26, :name => "Stiefesdag", :regions => [:lu]}]
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.custom_methods
|
34
|
+
{
|
35
|
+
|
36
|
+
}
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Holidays
|
3
|
+
# This file is generated by the Ruby Holidays gem.
|
4
|
+
#
|
5
|
+
# Definitions loaded: definitions/my.yaml
|
6
|
+
#
|
7
|
+
# To use the definitions in this file, load it right after you load the
|
8
|
+
# Holiday gem:
|
9
|
+
#
|
10
|
+
# require 'holidays'
|
11
|
+
# require 'generated_definitions/my'
|
12
|
+
#
|
13
|
+
# All the definitions are available at https://github.com/holidays/holidays
|
14
|
+
module MY # :nodoc:
|
15
|
+
def self.defined_regions
|
16
|
+
[:my]
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.holidays_by_month
|
20
|
+
{
|
21
|
+
1 => [{:mday => 1, :observed => "to_weekday_if_weekend(date)", :observed_arguments => [:date], :name => "New Year's Day", :regions => [:my]}],
|
22
|
+
5 => [{:mday => 1, :name => "Labour Day", :regions => [:my]}],
|
23
|
+
6 => [{:mday => 4, :observed => "to_weekday_if_weekend(date)", :observed_arguments => [:date], :name => "Agong's Birthday", :regions => [:my]}],
|
24
|
+
8 => [{:mday => 31, :observed => "to_weekday_if_weekend(date)", :observed_arguments => [:date], :name => "Independence Day", :regions => [:my]}],
|
25
|
+
9 => [{:mday => 16, :observed => "to_weekday_if_weekend(date)", :observed_arguments => [:date], :name => "Malaysia Day", :regions => [:my]}],
|
26
|
+
12 => [{:mday => 25, :observed => "to_weekday_if_weekend(date)", :observed_arguments => [:date], :name => "Christmas Day", :regions => [:my]}]
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.custom_methods
|
31
|
+
{
|
32
|
+
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -79,7 +79,7 @@ module Holidays
|
|
79
79
|
{:mday => 12, :type => :informal, :name => "Día de la Raza", :regions => [:mx]},
|
80
80
|
{:wday => 1, :week => 2, :name => "Columbus Day", :regions => [:us]},
|
81
81
|
{:mday => 31, :type => :informal, :name => "Halloween", :regions => [:us, :ca]}],
|
82
|
-
11 => [{:mday => 11, :name => "Remembrance Day", :regions => [:
|
82
|
+
11 => [{:mday => 11, :name => "Remembrance Day", :regions => [:ca_ab, :ca_sk, :ca_bc, :ca_pe, :ca_nf, :ca_nt, :ca_nu, :ca_nb, :ca_yk]},
|
83
83
|
{:mday => 1, :type => :informal, :name => "Todos los Santos", :regions => [:mx]},
|
84
84
|
{:mday => 2, :type => :informal, :name => "Los Fieles Difuntos", :regions => [:mx]},
|
85
85
|
{:wday => 1, :week => 3, :name => "Día de la Revolución", :regions => [:mx]},
|
@@ -116,7 +116,7 @@ year % 4 == 1 ? 20 : nil
|
|
116
116
|
},
|
117
117
|
|
118
118
|
"day_after_thanksgiving(year)" => Proc.new { |year|
|
119
|
-
Holidays::
|
119
|
+
Holidays::Factory::DateCalculator.day_of_month_calculator.call(year, 11, 4, 4) + 1
|
120
120
|
},
|
121
121
|
|
122
122
|
|
@@ -32,7 +32,7 @@ module Holidays
|
|
32
32
|
def self.custom_methods
|
33
33
|
{
|
34
34
|
"day_after_thanksgiving(year)" => Proc.new { |year|
|
35
|
-
Holidays::
|
35
|
+
Holidays::Factory::DateCalculator.day_of_month_calculator.call(year, 11, 4, 4) + 1
|
36
36
|
},
|
37
37
|
|
38
38
|
|
@@ -52,7 +52,7 @@ year % 4 == 1 ? 20 : nil
|
|
52
52
|
},
|
53
53
|
|
54
54
|
"day_after_thanksgiving(year)" => Proc.new { |year|
|
55
|
-
Holidays::
|
55
|
+
Holidays::Factory::DateCalculator.day_of_month_calculator.call(year, 11, 4, 4) + 1
|
56
56
|
},
|
57
57
|
|
58
58
|
|
data/lib/holidays.rb
CHANGED
@@ -3,10 +3,9 @@ $:.unshift File.dirname(__FILE__)
|
|
3
3
|
|
4
4
|
require 'date'
|
5
5
|
require 'digest/md5'
|
6
|
-
require 'holidays/
|
7
|
-
require 'holidays/
|
8
|
-
require 'holidays/
|
9
|
-
require 'holidays/use_case_factory'
|
6
|
+
require 'holidays/factory/definition'
|
7
|
+
require 'holidays/factory/date_calculator'
|
8
|
+
require 'holidays/factory/finder'
|
10
9
|
require 'holidays/errors'
|
11
10
|
require 'holidays/load_all_definitions'
|
12
11
|
|
@@ -57,19 +56,6 @@ module Holidays
|
|
57
56
|
FULL_DEFINITIONS_PATH = File.expand_path(File.dirname(__FILE__) + "/#{DEFINITIONS_PATH}")
|
58
57
|
|
59
58
|
class << self
|
60
|
-
# Get all holidays on a given date.
|
61
|
-
#
|
62
|
-
# [<tt>date</tt>] A Date object.
|
63
|
-
# [<tt>:options</tt>] One or more region symbols, <tt>:informal</tt> and/or <tt>:observed</tt>.
|
64
|
-
#
|
65
|
-
# Returns an array of hashes or nil. See Holidays#between for the output
|
66
|
-
# format.
|
67
|
-
#
|
68
|
-
# Also available via Date#holidays.
|
69
|
-
def on(date, *options)
|
70
|
-
between(date, date, options)
|
71
|
-
end
|
72
|
-
|
73
59
|
# Does the given work-week have any holidays?
|
74
60
|
#
|
75
61
|
# [<tt>date</tt>] A Date object.
|
@@ -87,6 +73,19 @@ module Holidays
|
|
87
73
|
between(start_date, end_date, options).empty?
|
88
74
|
end
|
89
75
|
|
76
|
+
# Get all holidays on a given date.
|
77
|
+
#
|
78
|
+
# [<tt>date</tt>] A Date object.
|
79
|
+
# [<tt>:options</tt>] One or more region symbols, <tt>:informal</tt> and/or <tt>:observed</tt>.
|
80
|
+
#
|
81
|
+
# Returns an array of hashes or nil. See Holidays#between for the output
|
82
|
+
# format.
|
83
|
+
#
|
84
|
+
# Also available via Date#holidays.
|
85
|
+
def on(date, *options)
|
86
|
+
between(date, date, options)
|
87
|
+
end
|
88
|
+
|
90
89
|
# Get all holidays occuring between two dates, inclusively.
|
91
90
|
#
|
92
91
|
# Returns an array of hashes or nil.
|
@@ -112,14 +111,11 @@ module Holidays
|
|
112
111
|
|
113
112
|
start_date, end_date = get_date(start_date), get_date(end_date)
|
114
113
|
|
115
|
-
if cached_holidays =
|
114
|
+
if cached_holidays = Factory::Definition.cache_repository.find(start_date, end_date, options)
|
116
115
|
return cached_holidays
|
117
116
|
end
|
118
117
|
|
119
|
-
|
120
|
-
date_driver_hash = UseCaseFactory.dates_driver_builder.call(start_date, end_date)
|
121
|
-
|
122
|
-
UseCaseFactory.between.call(start_date, end_date, date_driver_hash, regions, observed, informal)
|
118
|
+
Factory::Finder.between.call(start_date, end_date, options)
|
123
119
|
end
|
124
120
|
|
125
121
|
# Get next holidays occuring from date, inclusively.
|
@@ -150,30 +146,24 @@ module Holidays
|
|
150
146
|
from_date = from_date.new_offset(0) + from_date.offset if from_date.respond_to?(:new_offset)
|
151
147
|
|
152
148
|
from_date = get_date(from_date)
|
153
|
-
regions, observed, informal = OptionFactory.parse_options.call(options)
|
154
149
|
|
155
|
-
|
156
|
-
# the next 12 months will cause us issues. If it does we can implement something
|
157
|
-
# smarter here to check in smaller increments.
|
158
|
-
date_driver_hash = UseCaseFactory.dates_driver_builder.call(from_date, from_date >> 12)
|
159
|
-
|
160
|
-
UseCaseFactory.next_holiday.call(holidays_count, from_date, date_driver_hash, regions, observed, informal)
|
150
|
+
Factory::Finder.next_holiday.call(holidays_count, from_date, options)
|
161
151
|
end
|
162
152
|
|
163
|
-
# Get all holidays occuring from date to end of year, inclusively.
|
153
|
+
# Get all holidays occuring from date to end of year, inclusively.
|
164
154
|
#
|
165
|
-
# Returns an array of hashes or nil.
|
155
|
+
# Returns an array of hashes or nil.
|
166
156
|
#
|
167
|
-
# Incoming arguments are below:
|
157
|
+
# Incoming arguments are below:
|
168
158
|
# [<tt>options</tt>] One or more region symbols, <tt>:informal</tt> and/or <tt>:observed</tt>.
|
169
159
|
# [<tt>from_date</tt>] Ruby Date object. This is an optional param, defaulted today.
|
170
160
|
#
|
171
161
|
# ==== Example
|
172
162
|
# Date.today
|
173
163
|
# => Tue, 23 Feb 2016
|
174
|
-
#
|
164
|
+
#
|
175
165
|
# regions = [:ca_on]
|
176
|
-
#
|
166
|
+
#
|
177
167
|
# Holidays.year_holidays(regions)
|
178
168
|
# => [{:name=>"Good Friday",...},
|
179
169
|
# {name=>"Easter Sunday",...},
|
@@ -191,17 +181,9 @@ module Holidays
|
|
191
181
|
|
192
182
|
# remove the timezone
|
193
183
|
from_date = from_date.new_offset(0) + from_date.offset if from_date.respond_to?(:new_offset)
|
194
|
-
|
195
184
|
from_date = get_date(from_date)
|
196
|
-
to_date = Date.new(from_date.year, 12, 31)
|
197
|
-
regions, observed, informal = OptionFactory.parse_options.call(options)
|
198
|
-
|
199
|
-
# This could be smarter but I don't have any evidence that just checking for
|
200
|
-
# the next 12 months will cause us issues. If it does we can implement something
|
201
|
-
# smarter here to check in smaller increments.
|
202
|
-
date_driver_hash = UseCaseFactory.dates_driver_builder.call(from_date, from_date >> 12)
|
203
185
|
|
204
|
-
|
186
|
+
Factory::Finder.year_holiday.call(from_date, options)
|
205
187
|
end
|
206
188
|
|
207
189
|
# Allows a developer to explicitly calculate and cache holidays within a given period
|
@@ -209,7 +191,7 @@ module Holidays
|
|
209
191
|
start_date, end_date = get_date(start_date), get_date(end_date)
|
210
192
|
cache_data = between(start_date, end_date, *options)
|
211
193
|
|
212
|
-
|
194
|
+
Factory::Definition.cache_repository.cache_between(start_date, end_date, cache_data, options)
|
213
195
|
end
|
214
196
|
|
215
197
|
# Returns an array of symbols of all the available holiday regions.
|
@@ -219,13 +201,13 @@ module Holidays
|
|
219
201
|
|
220
202
|
# Parses provided holiday definition file(s) and loads them so that they are immediately available.
|
221
203
|
def load_custom(*files)
|
222
|
-
regions, rules_by_month, custom_methods,
|
204
|
+
regions, rules_by_month, custom_methods, _ = Factory::Definition.file_parser.parse_definition_files(files)
|
223
205
|
|
224
206
|
custom_methods.each do |method_key, method_entity|
|
225
|
-
custom_methods[method_key] =
|
207
|
+
custom_methods[method_key] = Factory::Definition.custom_method_proc_decorator.call(method_entity)
|
226
208
|
end
|
227
209
|
|
228
|
-
|
210
|
+
Factory::Definition.merger.call(regions, rules_by_month, custom_methods)
|
229
211
|
|
230
212
|
rules_by_month
|
231
213
|
end
|
@@ -239,10 +221,6 @@ module Holidays
|
|
239
221
|
Date.civil(date.year, date.mon, date.mday)
|
240
222
|
end
|
241
223
|
end
|
242
|
-
|
243
|
-
def definition_cache_repository
|
244
|
-
DefinitionFactory.cache_repository
|
245
|
-
end
|
246
224
|
end
|
247
225
|
end
|
248
226
|
|
@@ -49,7 +49,7 @@ module Holidays
|
|
49
49
|
|
50
50
|
module ClassMethods
|
51
51
|
def calculate_mday(year, month, week, wday)
|
52
|
-
Holidays::
|
52
|
+
Holidays::Factory::DateCalculator.day_of_month_calculator.call(year, month, week, wday)
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'holidays/errors'
|
2
|
+
|
3
|
+
module Holidays
|
4
|
+
module Definition
|
5
|
+
module Context
|
6
|
+
class FunctionProcessor
|
7
|
+
def initialize(custom_methods_repo, proc_result_cache_repo)
|
8
|
+
@custom_methods_repo = custom_methods_repo
|
9
|
+
@proc_result_cache_repo = proc_result_cache_repo
|
10
|
+
end
|
11
|
+
|
12
|
+
def call(year, month, day, func_id, desired_func_args, func_modifier = nil)
|
13
|
+
validate!(year, month, day, func_id, desired_func_args)
|
14
|
+
|
15
|
+
function = @custom_methods_repo.find(func_id)
|
16
|
+
raise Holidays::FunctionNotFound.new("Unable to find function with id '#{func_id}'") if function.nil?
|
17
|
+
|
18
|
+
calculate(year, month, function, parse_arguments(year, month, day, desired_func_args), func_modifier)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
VALID_ARGUMENTS = [:year, :month, :day, :date]
|
24
|
+
|
25
|
+
def validate!(year, month, day, func_id, desired_func_args)
|
26
|
+
raise ArgumentError if desired_func_args.nil? || desired_func_args.empty?
|
27
|
+
|
28
|
+
desired_func_args.each do |name|
|
29
|
+
raise ArgumentError unless VALID_ARGUMENTS.include?(name)
|
30
|
+
end
|
31
|
+
|
32
|
+
raise ArgumentError if desired_func_args.include?(:year) && !year.is_a?(Integer)
|
33
|
+
raise ArgumentError if desired_func_args.include?(:month) && (month < 0 || month > 12)
|
34
|
+
raise ArgumentError if desired_func_args.include?(:day) && (day < 1 || day > 31)
|
35
|
+
end
|
36
|
+
|
37
|
+
def parse_arguments(year, month, day, target_args)
|
38
|
+
args = []
|
39
|
+
|
40
|
+
if target_args.include?(:year)
|
41
|
+
args << year
|
42
|
+
end
|
43
|
+
|
44
|
+
if target_args.include?(:month)
|
45
|
+
args << month
|
46
|
+
end
|
47
|
+
|
48
|
+
if target_args.include?(:day)
|
49
|
+
args << day
|
50
|
+
end
|
51
|
+
|
52
|
+
if target_args.include?(:date)
|
53
|
+
args << Date.civil(year, month, day)
|
54
|
+
end
|
55
|
+
|
56
|
+
args
|
57
|
+
end
|
58
|
+
|
59
|
+
def calculate(year, month, id, args, modifier)
|
60
|
+
result = @proc_result_cache_repo.lookup(id, *args)
|
61
|
+
if result.kind_of?(Date)
|
62
|
+
if modifier
|
63
|
+
result = result + modifier # NOTE: This could be a positive OR negative number.
|
64
|
+
end
|
65
|
+
elsif result.is_a?(Integer)
|
66
|
+
begin
|
67
|
+
result = Date.civil(year, month, result)
|
68
|
+
rescue ArgumentError
|
69
|
+
raise Holidays::InvalidFunctionResponse.new("invalid day response from custom method call resulting in invalid date. Result: '#{result}'")
|
70
|
+
end
|
71
|
+
elsif result.nil?
|
72
|
+
# Do nothing. This is because some functions can return 'nil' today.
|
73
|
+
# I want to change this and so rather than come up with a clean
|
74
|
+
# implementation I'll do this so we don't throw an error in this specific
|
75
|
+
# situation. This should be removed once we have changed the existing
|
76
|
+
# custom definition functions. See https://github.com/holidays/holidays/issues/204
|
77
|
+
else
|
78
|
+
raise Holidays::InvalidFunctionResponse.new("invalid response from custom method call, must be a 'date' or 'integer' representing the day. Result: '#{result}'")
|
79
|
+
end
|
80
|
+
|
81
|
+
result
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -1,5 +1,12 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
|
3
|
+
#FIXME This whole file is my next refactor target. We do wayyyyy too much by
|
4
|
+
# convention here. We need hard and fast rules and explicit errors when you
|
5
|
+
# try to parse something that isn't allowed. So if you are a dev recognize
|
6
|
+
# that a lot of the guard statements in here are to codify existing legacy
|
7
|
+
# logic. The fact is that we already require these guards, we just don't
|
8
|
+
# enforce it explicitly. Now we will. And by doing so things will begin
|
9
|
+
# to look very, very messy.
|
3
10
|
module Holidays
|
4
11
|
module Definition
|
5
12
|
module Context
|
@@ -23,7 +30,7 @@ module Holidays
|
|
23
30
|
files.each do |file|
|
24
31
|
definition_file = YAML.load_file(file)
|
25
32
|
|
26
|
-
custom_methods = custom_method_parser.call(definition_file['methods'])
|
33
|
+
custom_methods = @custom_method_parser.call(definition_file['methods'])
|
27
34
|
|
28
35
|
regions, rules_by_month = parse_month_definitions(definition_file['months'], custom_methods)
|
29
36
|
|
@@ -54,7 +61,7 @@ module Holidays
|
|
54
61
|
# Build the custom methods string
|
55
62
|
custom_method_string = ''
|
56
63
|
custom_methods.each do |key, code|
|
57
|
-
custom_method_string << custom_method_source_decorator.call(code) + ",\n\n"
|
64
|
+
custom_method_string << @custom_method_source_decorator.call(code) + ",\n\n"
|
58
65
|
end
|
59
66
|
|
60
67
|
module_src = generate_module_src(module_name, files, regions, month_strings, custom_method_string)
|
@@ -65,8 +72,6 @@ module Holidays
|
|
65
72
|
|
66
73
|
private
|
67
74
|
|
68
|
-
attr_reader :custom_method_parser, :custom_method_source_decorator, :custom_methods_repository
|
69
|
-
|
70
75
|
#FIXME This should be a 'month_definitions_parser' like the above parser
|
71
76
|
def parse_month_definitions(month_definitions, parsed_custom_methods)
|
72
77
|
regions = []
|
@@ -83,9 +88,12 @@ module Holidays
|
|
83
88
|
end
|
84
89
|
|
85
90
|
rule[:regions] = rule[:regions].collect { |r| r.to_sym }
|
86
|
-
|
87
91
|
regions << rule[:regions]
|
88
92
|
|
93
|
+
if rule[:year_ranges]
|
94
|
+
rule[:year_ranges] = clean_year_ranges(rule[:year_ranges])
|
95
|
+
end
|
96
|
+
|
89
97
|
exists = false
|
90
98
|
rules_by_month[month].each do |ex|
|
91
99
|
if ex[:name] == rule[:name] and ex[:wday] == rule[:wday] and ex[:mday] == rule[:mday] and ex[:week] == rule[:week] and ex[:type] == rule[:type] and ex[:function] == rule[:function] and ex[:observed] == rule[:observed] and ex[:year_ranges] == rule[:year_ranges]
|
@@ -110,6 +118,23 @@ module Holidays
|
|
110
118
|
[regions, rules_by_month]
|
111
119
|
end
|
112
120
|
|
121
|
+
# In this case we end up parsing a range as "2006..2008" a string. This is codifying
|
122
|
+
# what we already do...today we parse as a string but when writing out to our final
|
123
|
+
# generated files it comes out as a range that Ruby interprets. This just puts it in stone
|
124
|
+
# what we want to do.
|
125
|
+
def clean_year_ranges(year_ranges)
|
126
|
+
year_ranges.collect do |year_range|
|
127
|
+
if year_range["between"]
|
128
|
+
range = year_range["between"]
|
129
|
+
if range.is_a?(String)
|
130
|
+
year_range["between"] = Range.new(*range.split("..").map(&:to_i))
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
year_range
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
113
138
|
def parse_test_definitions(tests)
|
114
139
|
test_strings = []
|
115
140
|
|
@@ -193,7 +218,7 @@ module Holidays
|
|
193
218
|
# What we should do is ensure that all custom methods are loaded into the repo as soon as they are parsed
|
194
219
|
# so we only have one place to look.
|
195
220
|
def get_function_arguments(function_id, parsed_custom_methods)
|
196
|
-
if method = custom_methods_repository.find(function_id)
|
221
|
+
if method = @custom_methods_repository.find(function_id)
|
197
222
|
method.parameters.collect { |arg| arg[1] }
|
198
223
|
elsif method = parsed_custom_methods[function_id]
|
199
224
|
method.arguments.collect { |arg| arg.to_sym }
|