holidays 4.4.0 → 4.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0583fff25d319bc53a85cb10ec309c8ad39496fd
4
- data.tar.gz: 9ee50ee21c0b476609d97d7e0b2c68682741389a
3
+ metadata.gz: cb0c1c87e82d392d31c5281d907e58bbe6573683
4
+ data.tar.gz: 7ffb3aa2717b7727898810687778f0df10ec235f
5
5
  SHA512:
6
- metadata.gz: 3ef3930fca96668d9514dbac18bd907b7e198a81592977dabc30d20b095225cd7e1d7cc9a673d27ddf44bb31b5312332325700c9efbbedd2bb084e5456764140
7
- data.tar.gz: 3d7dee33d38a31f68b11fe0ebd138c16beb2c4c0ea469d3eb7b0586993d1b614f0d822c97adfd3763ded3cb6bd2633363b2373f9d68d182b6bc3885fe5eba79a
6
+ metadata.gz: 7f5373bd6b450b42b4a9bb28338c028faecc3a3aea2c52146cd092fbf5ee6b2a144cf00450a5ddd430532737c46c1da590f387e45ddcfb2ca6584903844b4b53
7
+ data.tar.gz: cbaeda3492a457b84d3f2d0d19a8080539fbdf3068aa722e8593a42597897fddf767ba2bbb2668bc2a5a42c254e2f3ae1ad69a36362e9c2f52f925429bda6d90
@@ -1,5 +1,9 @@
1
1
  # Ruby Holidays Gem CHANGELOG
2
2
 
3
+ ## 4.5.0
4
+
5
+ * Add `Holidays.year_holidays` method to obtain all holidays occuring from date to end of year, inclusively (thanks to https://github.com/jonathanpike)
6
+
3
7
  ## 4.4.0
4
8
 
5
9
  * Add Peruvian holiday definitions (https://github.com/Xosmond)
data/README.md CHANGED
@@ -72,6 +72,22 @@ To find and return the next holidays occurring from date, inclusively:
72
72
 
73
73
  Will default to `Date.today` if no date is provided.
74
74
 
75
+ To find all holidays occuring from date to end of year, inclusively:
76
+
77
+ Holidays.year_holidays([:ca_on], Date.civil(2016, 2, 23))
78
+ => [{:name=>"Good Friday",...},
79
+ {name=>"Easter Sunday",...},
80
+ {:name=>"Victoria Day",...},
81
+ {:name=>"Canada Day",...},
82
+ {:name=>"Civic Holiday",...},
83
+ {:name=>"Labour Day",...},
84
+ {:name=>"Thanksgiving",...},
85
+ {:name=>"Remembrance Day",...},
86
+ {:name=>"Christmas Day",...},
87
+ {:name=>"Boxing Day",...}]
88
+
89
+ Will default to `Date.today` if no date is provided.
90
+
75
91
  ### Loading Custom Definitions on the fly
76
92
 
77
93
  Load custom definitions file on the fly and use them immediately.
@@ -160,6 +160,50 @@ module Holidays
160
160
  UseCaseFactory.next_holiday.call(holidays_count, from_date, date_driver_hash, regions, observed, informal)
161
161
  end
162
162
 
163
+ # Get all holidays occuring from date to end of year, inclusively.
164
+ #
165
+ # Returns an array of hashes or nil.
166
+ #
167
+ # Incoming arguments are below:
168
+ # [<tt>options</tt>] One or more region symbols, <tt>:informal</tt> and/or <tt>:observed</tt>.
169
+ # [<tt>from_date</tt>] Ruby Date object. This is an optional param, defaulted today.
170
+ #
171
+ # ==== Example
172
+ # Date.today
173
+ # => Tue, 23 Feb 2016
174
+ #
175
+ # regions = [:ca_on]
176
+ #
177
+ # Holidays.year_holidays(regions)
178
+ # => [{:name=>"Good Friday",...},
179
+ # {name=>"Easter Sunday",...},
180
+ # {:name=>"Victoria Day",...},
181
+ # {:name=>"Canada Day",...},
182
+ # {:name=>"Civic Holiday",...},
183
+ # {:name=>"Labour Day",...},
184
+ # {:name=>"Thanksgiving",...},
185
+ # {:name=>"Remembrance Day",...},
186
+ # {:name=>"Christmas Day",...},
187
+ # {:name=>"Boxing Day",...}]
188
+ def year_holidays(options, from_date = Date.today)
189
+ raise ArgumentError if options.empty?
190
+ raise ArgumentError unless options.is_a?(Array)
191
+
192
+ # remove the timezone
193
+ from_date = from_date.new_offset(0) + from_date.offset if from_date.respond_to?(:new_offset)
194
+
195
+ 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
+
204
+ UseCaseFactory.year_holiday.call(from_date, to_date, date_driver_hash, regions, observed, informal)
205
+ end
206
+
163
207
  # Allows a developer to explicitly calculate and cache holidays within a given period
164
208
  def cache_between(start_date, end_date, *options)
165
209
  start_date, end_date = get_date(start_date), get_date(end_date)
@@ -29,6 +29,24 @@ module Holidays
29
29
  holidays && !holidays.empty?
30
30
  end
31
31
 
32
+ # Returns a new Date where one or more of the elements have been changed according to the +options+ parameter.
33
+ # The +options+ parameter is a hash with a combination of these keys: <tt>:year</tt>, <tt>:month</tt>, <tt>:day</tt>.
34
+ #
35
+ # Date.new(2007, 5, 12).change(day: 1) # => Date.new(2007, 5, 1)
36
+ # Date.new(2007, 5, 12).change(year: 2005, month: 1) # => Date.new(2005, 1, 12)
37
+ def change(options)
38
+ ::Date.new(
39
+ options.fetch(:year, year),
40
+ options.fetch(:month, month),
41
+ options.fetch(:day, day)
42
+ )
43
+ end
44
+
45
+ def end_of_month
46
+ last_day = ::Time.days_in_month( self.month, self.year )
47
+ change(:day => last_day)
48
+ end
49
+
32
50
  module ClassMethods
33
51
  def calculate_mday(year, month, week, wday)
34
52
  Holidays::DateCalculatorFactory.day_of_month_calculator.call(year, month, week, wday)
@@ -0,0 +1,23 @@
1
+ module Holidays
2
+ module CoreExtensions
3
+ module Time
4
+ def self.included(base)
5
+ base.extend ClassMethods
6
+ end
7
+
8
+ module ClassMethods
9
+ COMMON_YEAR_DAYS_IN_MONTH = [nil, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
10
+
11
+ # Returns the number of days in the given month.
12
+ # If no year is specified, it will use the current year.
13
+ def days_in_month(month, year = current.year)
14
+ if month == 2 && ::Date.gregorian_leap?(year)
15
+ 29
16
+ else
17
+ COMMON_YEAR_DAYS_IN_MONTH[month]
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,51 @@
1
+ module Holidays
2
+ module UseCase
3
+ module Context
4
+ class YearHoliday
5
+ include ContextCommon
6
+
7
+ def initialize(holidays_by_month_repo, day_of_month_calculator, custom_methods_repo, proc_result_cache_repo)
8
+ @holidays_by_month_repo = holidays_by_month_repo
9
+ @day_of_month_calculator = day_of_month_calculator
10
+ @custom_methods_repo = custom_methods_repo
11
+ @proc_result_cache_repo = proc_result_cache_repo
12
+ end
13
+
14
+ def call(from_date, to_date, dates_driver, regions, observed, informal)
15
+ validate!(from_date, to_date, dates_driver, regions)
16
+ holidays = []
17
+ ret_holidays = []
18
+
19
+ ret_holidays = make_date_array(dates_driver, regions, observed, informal)
20
+ ret_holidays.each do |holiday|
21
+ if holiday[:date] >= from_date && holiday[:date] <= to_date
22
+ holidays << holiday
23
+ end
24
+ end
25
+
26
+ holidays.sort{|a, b| a[:date] <=> b[:date] }
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :holidays_by_month_repo,
32
+ :day_of_month_calculator,
33
+ :custom_methods_repo,
34
+ :proc_result_cache_repo
35
+
36
+ def validate!(from_date, to_date, dates_driver, regions)
37
+ raise ArgumentError unless from_date
38
+ raise ArgumentError unless to_date
39
+
40
+ raise ArgumentError if dates_driver.nil? || dates_driver.empty?
41
+
42
+ dates_driver.each do |year, months|
43
+ raise ArgumentError if months.nil? || months.empty?
44
+ end
45
+
46
+ raise ArgumentError if regions.nil? || regions.empty?
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -2,6 +2,7 @@ require 'holidays/use_case/context/context_common'
2
2
  require 'holidays/use_case/context/between'
3
3
  require 'holidays/use_case/context/next_holiday'
4
4
  require 'holidays/use_case/context/dates_driver_builder'
5
+ require 'holidays/use_case/context/year_holiday'
5
6
 
6
7
  module Holidays
7
8
  class UseCaseFactory
@@ -23,6 +24,15 @@ module Holidays
23
24
  )
24
25
  end
25
26
 
27
+ def year_holiday
28
+ UseCase::Context::YearHoliday.new(
29
+ DefinitionFactory.holidays_by_month_repository,
30
+ DateCalculatorFactory.day_of_month_calculator,
31
+ DefinitionFactory.custom_methods_repository,
32
+ DefinitionFactory.proc_result_cache_repository,
33
+ )
34
+ end
35
+
26
36
  def dates_driver_builder
27
37
  UseCase::Context::DatesDriverBuilder.new
28
38
  end
@@ -1,3 +1,3 @@
1
1
  module Holidays
2
- VERSION = '4.4.0'
2
+ VERSION = '4.5.0'
3
3
  end
@@ -0,0 +1,60 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + '/../../test_helper'
2
+
3
+ require 'holidays/core_extensions/date'
4
+ require 'holidays/core_extensions/time'
5
+
6
+ class Date
7
+ include Holidays::CoreExtensions::Date
8
+ end
9
+
10
+ class Time
11
+ include Holidays::CoreExtensions::Time
12
+ end
13
+
14
+ class CoreExtensionDateTimeTests < Test::Unit::TestCase
15
+ def setup
16
+ @date = Date.civil(2008,1,1)
17
+ end
18
+
19
+ def test_change_method
20
+ actual = @date.change(day: 5)
21
+ assert_equal Date.civil(2008,1,5), actual
22
+
23
+ actual = @date.change(year: 2016)
24
+ assert_equal Date.civil(2016,1,1), actual
25
+
26
+ actual = @date.change(month: 5)
27
+ assert_equal Date.civil(2008,5,1), actual
28
+
29
+ actual = @date.change(year: 2015, month: 5, day: 3)
30
+ assert_equal Date.civil(2015,5,3), actual
31
+ end
32
+
33
+ def test_end_of_month_method
34
+ # Works for month with 31 days
35
+ actual = @date.end_of_month
36
+ assert_equal Date.civil(2008,1,31), actual
37
+
38
+ # Works for month with 30 days
39
+ actual = Date.civil(2008,9,5).end_of_month
40
+ assert_equal Date.civil(2008,9,30), actual
41
+
42
+ # Works for leap year
43
+ actual = Date.civil(2016,2,1).end_of_month
44
+ assert_equal = Date.civil(2016,2,29), actual
45
+ end
46
+
47
+ def test_days_in_month_method
48
+ # Works for month with 31 days
49
+ actual = Time.days_in_month(1, 2008)
50
+ assert_equal 31, actual
51
+
52
+ # Works for month with 30 days
53
+ actual = Time.days_in_month(9, 2008)
54
+ assert_equal 30, actual
55
+
56
+ # Works for leap year
57
+ actual = Time.days_in_month(2, 2016)
58
+ assert_equal 29, actual
59
+ end
60
+ end
@@ -11,12 +11,17 @@ require 'mocha/test_unit'
11
11
  require 'date'
12
12
  require 'holidays'
13
13
  require 'holidays/core_extensions/date'
14
+ require 'holidays/core_extensions/time'
14
15
 
15
16
  # Loads core extension for use in various definition tests as necessary
16
17
  class Date
17
18
  include Holidays::CoreExtensions::Date
18
19
  end
19
20
 
21
+ class Time
22
+ include Holidays::CoreExtensions::Time
23
+ end
24
+
20
25
  module Holidays
21
26
  # Test region used for generating a holiday on Date.today
22
27
  module Test # :nodoc:
@@ -139,6 +139,61 @@ class HolidaysTests < Test::Unit::TestCase
139
139
  end
140
140
  end
141
141
 
142
+ def test_year_holidays
143
+ # Should return 10 holidays from February 23 to December 31
144
+ holidays = Holidays.year_holidays([:ca_on], Date.civil(2016, 2, 23))
145
+ assert_equal 10, holidays.length
146
+
147
+ # Must have options (Regions)
148
+ assert_raises ArgumentError do
149
+ Holidays.year_holidays([], Date.civil(2016, 2, 23))
150
+ end
151
+
152
+ # Options must be in the form of an array.
153
+ assert_raises ArgumentError do
154
+ Holidays.year_holidays(:ca_on, Date.civil(2016, 2, 23))
155
+ end
156
+ end
157
+
158
+ def test_year_holidays_with_specified_year
159
+ # Should return all 12 holidays for 2016 in Ontario, Canada
160
+ holidays = Holidays.year_holidays([:ca_on], Date.civil(2016, 1, 1))
161
+ assert_equal 12, holidays.length
162
+
163
+ # Should return all 12 holidays for 2016 in Australia
164
+ holidays = Holidays.year_holidays([:au], Date.civil(2016, 1, 1))
165
+ assert_equal 5, holidays.length
166
+ end
167
+
168
+ def test_year_holidays_without_specified_year
169
+ # Gets holidays for current year from today's date
170
+ holidays = Holidays.year_holidays([:ca_on])
171
+ assert_equal holidays.first[:date].year, Date.today.year
172
+ end
173
+
174
+ def test_year_holidays_feb_29_on_non_leap_year
175
+ # Should throw argument error for invalid date
176
+ assert_raises ArgumentError do
177
+ Holidays.year_holidays([:ca_on], Date.civil(2015, 2, 29))
178
+ end
179
+ end
180
+
181
+ def test_year_holidays_random_years
182
+ # Should be 1 less holiday, as Family day didn't exist in Ontario in 1990
183
+ holidays = Holidays.year_holidays([:ca_on], Date.civil(1990, 1, 1))
184
+ assert_equal 11, holidays.length
185
+
186
+ # Family day still didn't exist in 2000
187
+ holidays = Holidays.year_holidays([:ca_on], Date.civil(2000, 1, 1))
188
+ assert_equal 11, holidays.length
189
+
190
+ holidays = Holidays.year_holidays([:ca_on], Date.civil(2020, 1, 1))
191
+ assert_equal 12, holidays.length
192
+
193
+ holidays = Holidays.year_holidays([:ca_on], Date.civil(2050, 1, 1))
194
+ assert_equal 12, holidays.length
195
+ end
196
+
142
197
  def test_sub_regions
143
198
  # Should return Victoria Day.
144
199
  holidays = Holidays.between(Date.civil(2008,5,1), Date.civil(2008,5,31), :ca)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: holidays
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.4.0
4
+ version: 4.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Dunae
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-06-18 00:00:00.000000000 Z
12
+ date: 2016-06-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
@@ -230,6 +230,7 @@ files:
230
230
  - lib/generated_definitions/za.rb
231
231
  - lib/holidays.rb
232
232
  - lib/holidays/core_extensions/date.rb
233
+ - lib/holidays/core_extensions/time.rb
233
234
  - lib/holidays/date_calculator/day_of_month.rb
234
235
  - lib/holidays/date_calculator/easter.rb
235
236
  - lib/holidays/date_calculator/weekend_modifier.rb
@@ -256,6 +257,7 @@ files:
256
257
  - lib/holidays/use_case/context/context_common.rb
257
258
  - lib/holidays/use_case/context/dates_driver_builder.rb
258
259
  - lib/holidays/use_case/context/next_holiday.rb
260
+ - lib/holidays/use_case/context/year_holiday.rb
259
261
  - lib/holidays/use_case_factory.rb
260
262
  - lib/holidays/version.rb
261
263
  - test/data/test_custom_govt_holiday_defs.yaml
@@ -320,6 +322,7 @@ files:
320
322
  - test/defs/test_defs_vi.rb
321
323
  - test/defs/test_defs_za.rb
322
324
  - test/holidays/core_extensions/test_date.rb
325
+ - test/holidays/core_extensions/test_date_time.rb
323
326
  - test/holidays/date_calculator/test_day_of_month.rb
324
327
  - test/holidays/date_calculator/test_easter_gregorian.rb
325
328
  - test/holidays/date_calculator/test_easter_julian.rb
@@ -437,6 +440,7 @@ test_files:
437
440
  - test/defs/test_defs_vi.rb
438
441
  - test/defs/test_defs_za.rb
439
442
  - test/holidays/core_extensions/test_date.rb
443
+ - test/holidays/core_extensions/test_date_time.rb
440
444
  - test/holidays/date_calculator/test_day_of_month.rb
441
445
  - test/holidays/date_calculator/test_easter_gregorian.rb
442
446
  - test/holidays/date_calculator/test_easter_julian.rb