holidays 4.6.0 → 4.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 }
|