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,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
|