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,57 @@
|
|
1
|
+
module Holidays
|
2
|
+
module Finder
|
3
|
+
module Context
|
4
|
+
class YearHoliday
|
5
|
+
def initialize(definition_search, dates_driver_builder, options_parser)
|
6
|
+
@definition_search = definition_search
|
7
|
+
@dates_driver_builder = dates_driver_builder
|
8
|
+
@options_parser = options_parser
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(from_date, options)
|
12
|
+
validate!(from_date)
|
13
|
+
|
14
|
+
regions, observed, informal = @options_parser.call(options)
|
15
|
+
|
16
|
+
# This could be smarter but I don't have any evidence that just checking for
|
17
|
+
# the next 12 months will cause us issues. If it does we can implement something
|
18
|
+
# smarter here to check in smaller increments.
|
19
|
+
#
|
20
|
+
#FIXME Could this be until the to_date instead? Save us some processing?
|
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
|
+
|
24
|
+
to_date = Date.civil(from_date.year, 12, 31)
|
25
|
+
holidays = []
|
26
|
+
ret_holidays = []
|
27
|
+
opts = gather_options(observed, informal)
|
28
|
+
|
29
|
+
ret_holidays = @definition_search.call(dates_driver, regions, opts)
|
30
|
+
|
31
|
+
ret_holidays.each do |holiday|
|
32
|
+
if holiday[:date] >= from_date && holiday[:date] <= to_date
|
33
|
+
holidays << holiday
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
holidays.sort{|a, b| a[:date] <=> b[:date] }
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def validate!(from_date)
|
43
|
+
raise ArgumentError unless from_date && from_date.is_a?(Date)
|
44
|
+
end
|
45
|
+
|
46
|
+
def gather_options(observed, informal)
|
47
|
+
opts = []
|
48
|
+
|
49
|
+
opts << :observed if observed == true
|
50
|
+
opts << :informal if informal == true
|
51
|
+
|
52
|
+
opts
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Holidays
|
2
|
+
module Finder
|
3
|
+
module Rules
|
4
|
+
class InRegion
|
5
|
+
class << self
|
6
|
+
def call(requested, available)
|
7
|
+
return true if requested.include?(:any)
|
8
|
+
|
9
|
+
# When an underscore is encountered, derive the parent regions
|
10
|
+
# symbol and check for both.
|
11
|
+
requested = requested.collect do |r|
|
12
|
+
r.to_s =~ /_/ ? [r, r.to_s.gsub(/_[\w]*$/, '').to_sym] : r
|
13
|
+
end
|
14
|
+
|
15
|
+
requested = requested.flatten.uniq
|
16
|
+
|
17
|
+
available.any? { |avail| requested.include?(avail) }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# Please note that only one condition needs to match in order for `call` to return `true.
|
2
|
+
# See the test file for this class for specific examples.
|
3
|
+
module Holidays
|
4
|
+
module Finder
|
5
|
+
module Rules
|
6
|
+
class YearRange
|
7
|
+
class << self
|
8
|
+
BEFORE = :before
|
9
|
+
AFTER = :after
|
10
|
+
LIMITED = :limited
|
11
|
+
BETWEEN = :between
|
12
|
+
|
13
|
+
#TODO Can we just accept symbols here? Why accept strings?
|
14
|
+
VALID_OPERATORS = [
|
15
|
+
BEFORE, BEFORE.to_s,
|
16
|
+
AFTER, AFTER.to_s,
|
17
|
+
LIMITED, LIMITED.to_s,
|
18
|
+
BETWEEN, BETWEEN.to_s
|
19
|
+
]
|
20
|
+
|
21
|
+
def call(target_year, year_range_definitions)
|
22
|
+
validate!(target_year, year_range_definitions)
|
23
|
+
|
24
|
+
matched = false
|
25
|
+
year_range_definitions.each do |range_defs|
|
26
|
+
next unless range_defs.is_a?(Hash) && range_defs.length == 1
|
27
|
+
|
28
|
+
operator = range_defs.keys.first
|
29
|
+
year_range = range_defs.values.first
|
30
|
+
|
31
|
+
case operator
|
32
|
+
when BEFORE, BEFORE.to_s
|
33
|
+
matched = target_year <= year_range
|
34
|
+
when AFTER, AFTER.to_s
|
35
|
+
matched = target_year >= year_range
|
36
|
+
when LIMITED, LIMITED.to_s
|
37
|
+
if year_range.is_a?(Array)
|
38
|
+
matched = year_range.include?(target_year)
|
39
|
+
else
|
40
|
+
matched = year_range == target_year
|
41
|
+
end
|
42
|
+
when BETWEEN, BETWEEN.to_s
|
43
|
+
matched = year_range.cover?(target_year)
|
44
|
+
end
|
45
|
+
|
46
|
+
break if matched == true
|
47
|
+
end
|
48
|
+
|
49
|
+
matched
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def validate!(target_year, year_ranges)
|
55
|
+
raise ArgumentError.new("target_year must be a number") unless target_year.is_a?(Integer)
|
56
|
+
raise ArgumentError.new("year_ranges cannot be missing") if year_ranges.nil? || year_ranges.empty?
|
57
|
+
|
58
|
+
year_ranges.each do |range|
|
59
|
+
raise ArgumentError.new("year_ranges must include only hashes") unless range.is_a?(Hash)
|
60
|
+
raise ArgumentError.new("year_ranges cannot include empty hashes") if range.empty?
|
61
|
+
raise ArgumentError.new("year_ranges entries can only include one operator") unless range.count == 1
|
62
|
+
|
63
|
+
operator = range.keys.first
|
64
|
+
range = range.values.first
|
65
|
+
|
66
|
+
raise ArgumentError.new("Invalid operator found: '#{operator}'") unless VALID_OPERATORS.include?(operator)
|
67
|
+
|
68
|
+
case operator
|
69
|
+
when BEFORE, BEFORE.to_s, AFTER, AFTER.to_s
|
70
|
+
raise ArgumentError.new(":before and :after operator value must be a number, received: '#{range}'") unless range.is_a?(Integer)
|
71
|
+
when LIMITED, LIMITED.to_s
|
72
|
+
raise ArgumentError.new(":limited operator value must be an array, received: '#{range}'") unless range.is_a?(Array) || range.is_a?(Integer)
|
73
|
+
when BETWEEN, BETWEEN.to_s
|
74
|
+
raise ArgumentError.new(":between operator value must be a range, received: '#{range}'") unless range.is_a?(Range)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -17,6 +17,8 @@ module Holidays
|
|
17
17
|
# into some kind of definition file so it can be loaded automatically but I'm afraid
|
18
18
|
# of making that big of a breaking API change since these are public. For the time
|
19
19
|
# being I'll load them manually like this.
|
20
|
+
#
|
21
|
+
# NOTE: These are no longer public! We can do whatever we want here!
|
20
22
|
global_methods = {
|
21
23
|
"easter(year)" => gregorian_easter.method(:calculate_easter_for).to_proc,
|
22
24
|
"orthodox_easter(year)" => gregorian_easter.method(:calculate_orthodox_easter_for).to_proc,
|
@@ -32,25 +34,25 @@ module Holidays
|
|
32
34
|
"to_tuesday_if_sunday_or_monday_if_saturday(date)" => weekend_modifier.method(:to_tuesday_if_sunday_or_monday_if_saturday).to_proc,
|
33
35
|
}
|
34
36
|
|
35
|
-
|
37
|
+
Factory::Definition.custom_methods_repository.add(global_methods)
|
36
38
|
end
|
37
39
|
|
38
40
|
private
|
39
41
|
|
40
42
|
def gregorian_easter
|
41
|
-
|
43
|
+
Factory::DateCalculator::Easter::Gregorian.easter_calculator
|
42
44
|
end
|
43
45
|
|
44
46
|
def julian_easter
|
45
|
-
|
47
|
+
Factory::DateCalculator::Easter::Julian.easter_calculator
|
46
48
|
end
|
47
49
|
|
48
50
|
def weekend_modifier
|
49
|
-
|
51
|
+
Factory::DateCalculator.weekend_modifier
|
50
52
|
end
|
51
53
|
|
52
54
|
def day_of_month_calculator
|
53
|
-
|
55
|
+
Factory::DateCalculator.day_of_month_calculator
|
54
56
|
end
|
55
57
|
end
|
56
58
|
end
|
data/lib/holidays/version.rb
CHANGED
data/test/defs/test_defs_au.rb
CHANGED
@@ -75,7 +75,7 @@ assert_equal 'Melbourne Cup Day', Holidays.on(Date.civil(2014,11,4), :au_vic_mel
|
|
75
75
|
assert_equal 'Melbourne Cup Day', Holidays.on(Date.civil(2015,11,3), :au_vic_melbourne)[0][:name]
|
76
76
|
|
77
77
|
assert_equal 'Friday before the AFL Grand Final', Date.civil(2015,10,2).holidays(:au_vic)[0][:name]
|
78
|
-
|
78
|
+
assert_equal 'Friday before the AFL Grand Final', Date.civil(2016,9, 30).holidays(:au_vic)[0][:name]
|
79
79
|
|
80
80
|
assert_equal "May Public Holiday", Date.civil(2005, 5, 16).holidays(:au_sa)[0][:name]
|
81
81
|
assert_equal [], Date.civil(2014, 5, 19).holidays(:au_sa)
|
data/test/defs/test_defs_ca.rb
CHANGED
@@ -15,7 +15,6 @@ class CaDefinitionTests < Test::Unit::TestCase # :nodoc:
|
|
15
15
|
Date.civil(2008,7,1) => 'Canada Day',
|
16
16
|
Date.civil(2008,9,1) => 'Labour Day',
|
17
17
|
Date.civil(2008,10,13) => 'Thanksgiving',
|
18
|
-
Date.civil(2008,11,11) => 'Remembrance Day',
|
19
18
|
Date.civil(2008,12,25) => 'Christmas Day',
|
20
19
|
Date.civil(2008,12,26) => 'Boxing Day'}.each do |date, name|
|
21
20
|
assert_equal name, (Holidays.on(date, :ca, :informal)[0] || {})[:name]
|
@@ -145,6 +144,22 @@ end
|
|
145
144
|
end
|
146
145
|
end
|
147
146
|
|
147
|
+
# Remembrance Day in all Canadian provinces
|
148
|
+
# except (Nova Scotia, Manitoba, Ontario, and Quebec)
|
149
|
+
[
|
150
|
+
:ca_ab,
|
151
|
+
:ca_sk,
|
152
|
+
:ca_bc,
|
153
|
+
:ca_pe,
|
154
|
+
:ca_nf,
|
155
|
+
:ca_nt,
|
156
|
+
:ca_nu,
|
157
|
+
:ca_nb,
|
158
|
+
:ca_yk
|
159
|
+
].each do |province|
|
160
|
+
assert_equal "Remembrance Day", Holidays.on(Date.civil(2016,11,11), province)[0][:name]
|
161
|
+
end
|
162
|
+
|
148
163
|
|
149
164
|
{Date.civil(2013,2,2) => 'Groundhog Day',
|
150
165
|
Date.civil(2013,2,14) => 'Valentine\'s Day',
|
data/test/defs/test_defs_jp.rb
CHANGED
@@ -69,5 +69,9 @@ end
|
|
69
69
|
# before 2016, there is no mountain holiday.
|
70
70
|
assert_nil Holidays.on(Date.civil(2015,8,11), :jp)[0]
|
71
71
|
|
72
|
+
# before 2003, there is no citizens holiday.
|
73
|
+
# [note] citizens holiday requires that jp_national_culture_day is wednesday.
|
74
|
+
# Before 2003, the closest past year that mathches above condition is 1998.
|
75
|
+
assert_nil Holidays.on(Date.civil(1998,9,22), :jp)[0]
|
72
76
|
end
|
73
77
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path(File.dirname(__FILE__)) + '/../test_helper'
|
3
|
+
|
4
|
+
# This file is generated by the Ruby Holiday gem.
|
5
|
+
#
|
6
|
+
# Definitions loaded: definitions/kr.yaml
|
7
|
+
class KrDefinitionTests < Test::Unit::TestCase # :nodoc:
|
8
|
+
|
9
|
+
def test_kr
|
10
|
+
{Date.civil(2016,2,8) => "Korean New Year",
|
11
|
+
Date.civil(2016,5,14) => "Buddah\'s Birthday",
|
12
|
+
Date.civil(2016,9,12) => "Korean Thanksgiving",
|
13
|
+
Date.civil(2016,1,1) => "New Year\'s Day",
|
14
|
+
Date.civil(2016,3,1) => "Independence Movement Day",
|
15
|
+
Date.civil(2016,5,5) => "Children\'s Day",
|
16
|
+
Date.civil(2016,6,6) => "Memorial Day",
|
17
|
+
Date.civil(2016,7,17) => "Constitution Day",
|
18
|
+
Date.civil(2016,8,15) => "Liberation Day",
|
19
|
+
Date.civil(2016,10,3) => "National Foundation Day",
|
20
|
+
Date.civil(2016,10,9) => "Hangul Day",
|
21
|
+
Date.civil(2016,12,25) => "Christmas Day"}.each do |date, name|
|
22
|
+
assert_equal name, (Holidays.on(date, :kr, :informal)[0] || {})[:name]
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path(File.dirname(__FILE__)) + '/../test_helper'
|
3
|
+
|
4
|
+
# This file is generated by the Ruby Holiday gem.
|
5
|
+
#
|
6
|
+
# Definitions loaded: definitions/lu.yaml
|
7
|
+
class LuDefinitionTests < Test::Unit::TestCase # :nodoc:
|
8
|
+
|
9
|
+
def test_lu
|
10
|
+
{Date.civil(2008,1,1) => 'Neijoerschdag',
|
11
|
+
Date.civil(2008,3,24) => 'Ouschterméindeg',
|
12
|
+
Date.civil(2008,5,1) => 'Christi Himmelfaart', # Ascension, Easter+39
|
13
|
+
Date.civil(2008,6,23) => 'Nationalfeierdag',
|
14
|
+
Date.civil(2008,8,15) => 'Léiffrawëschdag',
|
15
|
+
Date.civil(2008,11,1) => 'Allerhellgen',
|
16
|
+
Date.civil(2008,12,25) => 'Chrëschtdag',
|
17
|
+
Date.civil(2008,12,26) => 'Stiefesdag',
|
18
|
+
Date.civil(2008,5,11) => 'Péngschtméindeg'
|
19
|
+
}.each do |date, name|
|
20
|
+
assert_equal name, (Holidays.on(date, :lu, :informal)[0] || {})[:name]
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.expand_path(File.dirname(__FILE__)) + '/../test_helper'
|
3
|
+
|
4
|
+
# This file is generated by the Ruby Holiday gem.
|
5
|
+
#
|
6
|
+
# Definitions loaded: definitions/my.yaml
|
7
|
+
class MyDefinitionTests < Test::Unit::TestCase # :nodoc:
|
8
|
+
|
9
|
+
def test_my
|
10
|
+
{Date.civil(2016,1,1) => "New Year's Day",
|
11
|
+
Date.civil(2016,5,1) => 'Labour Day',
|
12
|
+
Date.civil(2016,6,4) => "Agong's Birthday",
|
13
|
+
Date.civil(2016,8,31) => 'Independence Day',
|
14
|
+
Date.civil(2016,9,16) => 'Malaysia Day',
|
15
|
+
Date.civil(2016,12,25) => 'Christmas Day'}.each do |date, name|
|
16
|
+
assert_equal name, (Holidays.on(date, :my, :informal)[0] || {})[:name]
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -15,7 +15,6 @@ class North_americaDefinitionTests < Test::Unit::TestCase # :nodoc:
|
|
15
15
|
Date.civil(2008,7,1) => 'Canada Day',
|
16
16
|
Date.civil(2008,9,1) => 'Labour Day',
|
17
17
|
Date.civil(2008,10,13) => 'Thanksgiving',
|
18
|
-
Date.civil(2008,11,11) => 'Remembrance Day',
|
19
18
|
Date.civil(2008,12,25) => 'Christmas Day',
|
20
19
|
Date.civil(2008,12,26) => 'Boxing Day'}.each do |date, name|
|
21
20
|
assert_equal name, (Holidays.on(date, :ca, :informal)[0] || {})[:name]
|
@@ -145,6 +144,22 @@ end
|
|
145
144
|
end
|
146
145
|
end
|
147
146
|
|
147
|
+
# Remembrance Day in all Canadian provinces
|
148
|
+
# except (Nova Scotia, Manitoba, Ontario, and Quebec)
|
149
|
+
[
|
150
|
+
:ca_ab,
|
151
|
+
:ca_sk,
|
152
|
+
:ca_bc,
|
153
|
+
:ca_pe,
|
154
|
+
:ca_nf,
|
155
|
+
:ca_nt,
|
156
|
+
:ca_nu,
|
157
|
+
:ca_nb,
|
158
|
+
:ca_yk
|
159
|
+
].each do |province|
|
160
|
+
assert_equal "Remembrance Day", Holidays.on(Date.civil(2016,11,11), province)[0][:name]
|
161
|
+
end
|
162
|
+
|
148
163
|
|
149
164
|
{Date.civil(2007,1,1) => 'Año nuevo',
|
150
165
|
Date.civil(2007,2,5) => 'Día de la Constitución',
|
@@ -7,16 +7,16 @@ class Date
|
|
7
7
|
include Holidays::CoreExtensions::Date
|
8
8
|
end
|
9
9
|
|
10
|
-
class Time
|
10
|
+
class Time
|
11
11
|
include Holidays::CoreExtensions::Time
|
12
|
-
end
|
12
|
+
end
|
13
13
|
|
14
14
|
class CoreExtensionDateTimeTests < Test::Unit::TestCase
|
15
15
|
def setup
|
16
16
|
@date = Date.civil(2008,1,1)
|
17
17
|
end
|
18
18
|
|
19
|
-
def test_change_method
|
19
|
+
def test_change_method
|
20
20
|
actual = @date.change(day: 5)
|
21
21
|
assert_equal Date.civil(2008,1,5), actual
|
22
22
|
|
@@ -28,7 +28,7 @@ class CoreExtensionDateTimeTests < Test::Unit::TestCase
|
|
28
28
|
|
29
29
|
actual = @date.change(year: 2015, month: 5, day: 3)
|
30
30
|
assert_equal Date.civil(2015,5,3), actual
|
31
|
-
end
|
31
|
+
end
|
32
32
|
|
33
33
|
def test_end_of_month_method
|
34
34
|
# Works for month with 31 days
|
@@ -41,7 +41,7 @@ class CoreExtensionDateTimeTests < Test::Unit::TestCase
|
|
41
41
|
|
42
42
|
# Works for leap year
|
43
43
|
actual = Date.civil(2016,2,1).end_of_month
|
44
|
-
assert_equal
|
44
|
+
assert_equal Date.civil(2016,2,29), actual
|
45
45
|
end
|
46
46
|
|
47
47
|
def test_days_in_month_method
|
@@ -56,5 +56,5 @@ class CoreExtensionDateTimeTests < Test::Unit::TestCase
|
|
56
56
|
# Works for leap year
|
57
57
|
actual = Time.days_in_month(2, 2016)
|
58
58
|
assert_equal 29, actual
|
59
|
-
end
|
60
|
-
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)) + '/../../../test_helper'
|
2
|
+
|
3
|
+
require 'holidays/definition/context/function_processor'
|
4
|
+
|
5
|
+
class FunctionProcessorTests < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
@year = 2016
|
8
|
+
@month = 1
|
9
|
+
@day = 15
|
10
|
+
@func_id = "custom_function_id"
|
11
|
+
@func_args = [:year]
|
12
|
+
@func_modifier = 1
|
13
|
+
|
14
|
+
@custom_methods_repo = mock()
|
15
|
+
@proc_result_cache_repo = mock()
|
16
|
+
|
17
|
+
@custom_func = mock()
|
18
|
+
|
19
|
+
@custom_methods_repo.expects(:find).at_most_once.with(@func_id).returns(@custom_func)
|
20
|
+
@proc_result_cache_repo.expects(:lookup).at_most_once.with(@custom_func, @year).returns(Date.civil(@year, @month, @day))
|
21
|
+
|
22
|
+
@subject = Holidays::Definition::Context::FunctionProcessor.new(
|
23
|
+
@custom_methods_repo,
|
24
|
+
@proc_result_cache_repo,
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_no_function_arguments_returns_error
|
29
|
+
assert_raises ArgumentError do
|
30
|
+
@subject.call(@year, @month, @day, @func_id, nil, @func_modifier)
|
31
|
+
end
|
32
|
+
|
33
|
+
assert_raises ArgumentError do
|
34
|
+
@subject.call(@year, @month, @day, @func_id, [], @func_modifier)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_unknown_function_argument_returns_error
|
39
|
+
assert_raises ArgumentError do
|
40
|
+
@subject.call(@year, @month, @day, @func_id, [:something], @func_modifier)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_unknown_function_id_returns_error
|
45
|
+
bad_id = "some-bad-id"
|
46
|
+
@custom_methods_repo.expects(:find).at_most_once.with(bad_id).returns(nil)
|
47
|
+
|
48
|
+
assert_raises Holidays::FunctionNotFound do
|
49
|
+
@subject.call(@year, @month, @day, bad_id, @func_args, @func_modifier)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def test_year_arg_passed_to_func_call
|
54
|
+
@func_args = [:year]
|
55
|
+
@proc_result_cache_repo.expects(:lookup).at_most_once.with(@custom_func, @year).returns(Date.civil(2016, 1, 15))
|
56
|
+
|
57
|
+
@subject.call(@year, @month, @day, @func_id, @func_args, @func_modifier)
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_month_arg_passed_to_func_call
|
61
|
+
@func_args = [:month]
|
62
|
+
@proc_result_cache_repo.expects(:lookup).at_most_once.with(@custom_func, @month).returns(Date.civil(2016, 1, 15))
|
63
|
+
|
64
|
+
@subject.call(@year, @month, @day, @func_id, @func_args, @func_modifier)
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_day_arg_passed_to_func_call
|
68
|
+
@func_args = [:day]
|
69
|
+
@proc_result_cache_repo.expects(:lookup).at_most_once.with(@custom_func, @day).returns(Date.civil(2016, 1, 15))
|
70
|
+
|
71
|
+
@subject.call(@year, @month, @day, @func_id, @func_args, @func_modifier)
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_date_arg_passed_to_func_call
|
75
|
+
@func_args = [:date]
|
76
|
+
date = Date.civil(@year, @month, @day)
|
77
|
+
@proc_result_cache_repo.expects(:lookup).at_most_once.with(@custom_func, date).returns(date)
|
78
|
+
|
79
|
+
@subject.call(@year, @month, @day, @func_id, @func_args, @func_modifier)
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_multiple_args_passed_to_func_call
|
83
|
+
@func_args = [:month, :day]
|
84
|
+
@proc_result_cache_repo.expects(:lookup).at_most_once.with(@custom_func, @month, @day).returns(Date.civil(2016, 1, 15))
|
85
|
+
|
86
|
+
@subject.call(@year, @month, @day, @func_id, @func_args, @func_modifier)
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_call_returns_error_if_target_function_returns_unknown_value
|
90
|
+
@proc_result_cache_repo.expects(:lookup).at_most_once.with(@custom_func, @year).returns("bad-response")
|
91
|
+
|
92
|
+
assert_raises Holidays::InvalidFunctionResponse do
|
93
|
+
@subject.call(@year, @month, @day, @func_id, @func_args, @func_modifier)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_call_returns_date_with_modifier
|
98
|
+
@proc_result_cache_repo.expects(:lookup).at_most_once.with(@custom_func, @year).returns(Date.civil(2016, 3, 10))
|
99
|
+
|
100
|
+
result = @subject.call(@year, @month, @day, @func_id, @func_args, @func_modifier)
|
101
|
+
|
102
|
+
assert_equal(Date.civil(2016, 3, 10) + @func_modifier, result)
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_call_returns_date_no_modifier
|
106
|
+
@proc_result_cache_repo.expects(:lookup).at_most_once.with(@custom_func, @year).returns(Date.civil(2016, 3, 10))
|
107
|
+
|
108
|
+
result = @subject.call(@year, @month, @day, @func_id, @func_args, nil)
|
109
|
+
|
110
|
+
assert_equal(Date.civil(2016, 3, 10), result)
|
111
|
+
end
|
112
|
+
|
113
|
+
def test_call_returns_errors_when_custom_function_returns_non_date
|
114
|
+
@proc_result_cache_repo.expects(:lookup).at_most_once.with(@custom_func, @year).returns("bad")
|
115
|
+
|
116
|
+
assert_raises Holidays::InvalidFunctionResponse do
|
117
|
+
@subject.call(@year, @month, @day, @func_id, @func_args, nil)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_call_returns_error_when_custom_function_returns_mday_but_resulting_date_is_invalid
|
122
|
+
@proc_result_cache_repo.expects(:lookup).at_most_once.with(@custom_func, @year).returns(32)
|
123
|
+
|
124
|
+
assert_raises Holidays::InvalidFunctionResponse do
|
125
|
+
@subject.call(@year, @month, @day, @func_id, @func_args, nil)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_call_returns_integer_returns_modified_date
|
130
|
+
@proc_result_cache_repo.expects(:lookup).at_most_once.with(@custom_func, @year).returns(7)
|
131
|
+
|
132
|
+
result = @subject.call(@year, @month, @day, @func_id, @func_args, nil)
|
133
|
+
|
134
|
+
assert_equal(Date.civil(2016, 1, 7), result)
|
135
|
+
end
|
136
|
+
|
137
|
+
def test_func_modifier_not_required
|
138
|
+
result = @subject.call(@year, @month, @day, @func_id, @func_args)
|
139
|
+
assert_equal(Date.civil(2016, 1, 15), result)
|
140
|
+
end
|
141
|
+
|
142
|
+
def test_validate_returns_error_if_year_not_a_number
|
143
|
+
assert_raises ArgumentError do
|
144
|
+
@subject.call("bad-year", @month, @day, @func_id, @func_args)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_validate_returns_error_if_month_not_valid
|
149
|
+
assert_raises ArgumentError do
|
150
|
+
@subject.call(@year, "bad-month", @day, @func_id, [:month])
|
151
|
+
end
|
152
|
+
|
153
|
+
assert_raises ArgumentError do
|
154
|
+
@subject.call(@year, -1, @day, @func_id, [:month])
|
155
|
+
end
|
156
|
+
|
157
|
+
assert_raises ArgumentError do
|
158
|
+
@subject.call(@year, 13, @day, @func_id, [:month])
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def test_validate_returns_error_if_day_is_not_valid
|
163
|
+
assert_raises ArgumentError do
|
164
|
+
@subject.call(@year, @month, 0, @func_id, [:day])
|
165
|
+
end
|
166
|
+
|
167
|
+
assert_raises ArgumentError do
|
168
|
+
@subject.call(@year, @month, 32, @func_id, [:day])
|
169
|
+
end
|
170
|
+
|
171
|
+
assert_raises ArgumentError do
|
172
|
+
@subject.call(@year, @month, "bad-day", @func_id, [:day])
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|