national_holidays 0.0.1 → 0.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d49e1a4f16f57faae9173300299c13e8addcffd1
4
- data.tar.gz: ac17ebe82b0523e4eb01e1066cf3ce9c4e2ae579
3
+ metadata.gz: cb7291b45904d9a8e6eabe11401ebcc3177e7385
4
+ data.tar.gz: 5bed83c2b535c5461d6d59f75278cf972e12b54a
5
5
  SHA512:
6
- metadata.gz: 38e9259b565a312419117fb4d92fde792407743ddec6049519b4a8015ba902b962e181977dce1cb30f180f6d302db95f34b6fa66de1828bbe5bd246dfbaf9c91
7
- data.tar.gz: bc3eaa23e914bdf06925f5e5501a75fb9daa8bc5348e206a59e6e553957b959deb71486c38946363e3a810a288aedf49a383ab071df2448214d6b8dff259546d
6
+ metadata.gz: b36421e48049f73133c21313a9177f9dccbf019ecc767c4671fc8adfd4de2100536cb3b9b411a2bc4fe4a82657b3a63c41c18d0bee8b73793140d44dfc090b80
7
+ data.tar.gz: 00e0e05e3b837d264e8f7b48ff8ff6c2f006dcf103fdedf73e1a78c0bf29df559b4e422a5ebcb7db8313b680d6ee1c95ce5692aed6e1d893c67b58cf5136828a
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) [2018] [CharlieHR]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,95 @@
1
+ # National Holidays for Ruby
2
+
3
+ ## Where does this data come from?
4
+
5
+ The national holidays data used in this gem comes from the [national-holidays-config](https://github.com/kaoru/national-holidays-config) project.
6
+
7
+ ## Installation
8
+
9
+ gem install national_holidays
10
+
11
+ ## Usage
12
+
13
+ require 'national_holidays'
14
+
15
+ NationalHolidays.load! # optionally pre-load all data
16
+
17
+ NationalHolidays.countries.each do |country|
18
+ country.regions.each do |region|
19
+ holidays = region.all_holidays.select { |h| h.date.day == 18 && h.date.month == 11 }
20
+
21
+ if holidays.any?
22
+ puts "My birthday is a public holiday in #{country.name}: #{holidays.first.names.except(:en).first.last}!"
23
+ end
24
+ end
25
+ end
26
+
27
+ # My birthday is a public holiday in Haiti: Vertières Day!
28
+ # My birthday is a public holiday in Iran (Islamic Republic of): Martyrdom of Imam Reza!
29
+ # My birthday is a public holiday in Latvia: Latvijas Republikas proklamēšanas diena!
30
+ # My birthday is a public holiday in Mexico: Revolución Mexicana!
31
+
32
+ ## Country
33
+
34
+ country = NationalHolidays::Country.new(:gb)
35
+
36
+ puts country.code
37
+ # gb
38
+
39
+ puts country.name
40
+ # United Kingdom of Great Britain and Northern Ireland
41
+
42
+ puts country.regions.map(&:name)
43
+ # ["England", "Wales", "Scotland", "Northern Ireland"]
44
+
45
+ Country names come from https://github.com/hexorx/countries
46
+
47
+ Region names come from https://github.com/kaoru/national-holidays-config
48
+
49
+ ## Region
50
+
51
+ region = NationalHolidays::Region.new(:united_states14)
52
+
53
+ puts region.code
54
+ # :united_states14
55
+
56
+ puts region.name
57
+ # Illinois
58
+
59
+ date = Date.new(2018, 1, 1)
60
+
61
+ puts region.all_holidays.count
62
+ # 374
63
+
64
+ puts region.holidays_on_or_before(date).count
65
+ # 87
66
+ puts region.holidays_before(date).count
67
+ # 86
68
+
69
+ puts region.holidays_on_or_after(date).count
70
+ # 288
71
+ puts region.holidays_after(date).count
72
+ # 287
73
+
74
+ puts region.holidays_between(date, date).count
75
+ # 1
76
+
77
+ ## Holiday
78
+
79
+ holiday.names
80
+ # {
81
+ # en: "New Year's Day",
82
+ # es: "Año Nuevo"
83
+ # }
84
+
85
+ holiday.date
86
+ # Date.new(2018, 1, 1)
87
+
88
+ holiday.public_holiday?
89
+ # true
90
+
91
+ In the future we hope to also support non-public holidays, ie. days which are notable but do not mean that people get the day of work.
92
+
93
+ ## Who are we?
94
+
95
+ We run [CharlieHR](https://www.charliehr.com) where knowing about public and national holidays helps us calculate time off for 1000s of companies.
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs << 'test'
7
+ end
8
+
9
+ desc 'Run tests'
10
+ task default: :test
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'countries'
4
+
5
+ class NationalHolidays
6
+ class Country
7
+ attr_reader :code, :name
8
+
9
+ def self.all
10
+ Dir.glob("#{NationalHolidays.config_directory}/*").sort.map do |country_directory|
11
+ new(File.basename(country_directory))
12
+ end
13
+ end
14
+
15
+ def initialize(code)
16
+ @code = code.to_sym
17
+ @name = ISO3166::Country.new(code).name
18
+ end
19
+
20
+ def regions
21
+ dir = "#{NationalHolidays.config_directory}/#{code}"
22
+
23
+ raise NationalHolidays::UnknownCountryError, "Unknown country: #{code}" unless Dir.exist?(dir)
24
+
25
+ Dir.glob("#{dir}/*.yml").sort.map do |filename|
26
+ Region.new(File.basename(filename).sub(/\.yml/, ''))
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ class NationalHolidays
4
+ class Holiday
5
+ attr_reader :names, :date
6
+
7
+ def initialize(names, date, public_holiday)
8
+ @names = names.map { |k, v| [k.to_sym, v] }.to_h
9
+ @date = Date.parse(date.to_s)
10
+ @public_holiday = public_holiday
11
+ end
12
+
13
+ def public_holiday?
14
+ @public_holiday
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'national_holidays/holiday'
4
+
5
+ require 'yaml'
6
+
7
+ class NationalHolidays
8
+ class Region
9
+ attr_reader :code
10
+
11
+ def self.all
12
+ Dir.glob("#{NationalHolidays.config_directory}/*/*.yml").map do |region_filename|
13
+ new(File.basename(region_filename).sub(/\.yml/, ''))
14
+ end.sort_by(&:code)
15
+ end
16
+
17
+ def initialize(code)
18
+ @code = code.to_sym
19
+ end
20
+
21
+ def name
22
+ config.fetch('name')
23
+ end
24
+
25
+ def all_holidays
26
+ holidays
27
+ end
28
+
29
+ def holidays_on_or_before(date)
30
+ holidays(nil, date)
31
+ end
32
+
33
+ def holidays_before(date)
34
+ holidays(nil, date.prev_day)
35
+ end
36
+
37
+ def holidays_on_or_after(date)
38
+ holidays(date, nil)
39
+ end
40
+
41
+ def holidays_after(date)
42
+ holidays(date.next_day, nil)
43
+ end
44
+
45
+ def holidays_between(start_date, end_date)
46
+ holidays(start_date, end_date)
47
+ end
48
+
49
+ private
50
+
51
+ def holidays(start_date = nil, end_date = nil)
52
+ start_date = Date.parse(start_date.to_s).to_s if start_date
53
+ end_date = Date.parse(end_date.to_s).to_s if end_date
54
+
55
+ config.fetch('years').flat_map do |_, holidays|
56
+ holidays.map do |holiday_config|
57
+ holiday_config_date = holiday_config.fetch('date')
58
+
59
+ next if start_date && start_date > holiday_config_date
60
+ next if end_date && end_date < holiday_config_date
61
+
62
+ Holiday.new(*holiday_config.values_at('names', 'date', 'public_holiday'))
63
+ end
64
+ end.compact
65
+ end
66
+
67
+ @cache = {}
68
+ class << self
69
+ attr_reader :cache
70
+ end
71
+
72
+ def config
73
+ return self.class.cache[code] if self.class.cache.key?(code)
74
+
75
+ filename = Dir.glob("#{NationalHolidays.config_directory}/*/*.yml").sort.find do |f|
76
+ File.basename(f) == "#{code}.yml"
77
+ end
78
+
79
+ raise NationalHolidays::UnknownRegionError, "Unknown region: #{code}" unless filename
80
+
81
+ self.class.cache[code] = YAML.safe_load(File.read(filename))
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest/autorun'
4
+ require 'national_holidays'
5
+
6
+ class NationalHolidaysTest < Minitest::Test
7
+ def test_load
8
+ assert_equal true, NationalHolidays.load!
9
+ end
10
+
11
+ def test_countries
12
+ assert_equal :ae, NationalHolidays.countries.first.code
13
+ assert_equal 'South Africa', NationalHolidays.countries.last.name
14
+ end
15
+
16
+ def test_regions
17
+ assert_equal :angola01, NationalHolidays.regions.first.code
18
+ assert_equal 'Vietnam', NationalHolidays.regions.last.name
19
+ end
20
+
21
+ def test_regions_to_public_holiday_count_for_year
22
+ assert_equal 8, NationalHolidays.regions_to_public_holiday_count_for_year(2017).fetch(:united_kingdom01)
23
+ end
24
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest/autorun'
4
+ require 'national_holidays'
5
+
6
+ class NationalHolidaysCountryTest < Minitest::Test
7
+ def test_code
8
+ assert_equal :gb, NationalHolidays::Country.new(:gb).code
9
+ assert_equal :gb, NationalHolidays::Country.new('gb').code
10
+ end
11
+
12
+ def test_name
13
+ assert_equal 'United Kingdom of Great Britain and Northern Ireland', NationalHolidays::Country.new(:gb).name
14
+ end
15
+
16
+ def test_regions
17
+ assert_equal %i[united_kingdom01 united_kingdom02 united_kingdom03 united_kingdom04], NationalHolidays::Country.new(:gb).regions.map(&:code)
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest/autorun'
4
+ require 'national_holidays'
5
+
6
+ class NationalHolidaysHolidayTest < Minitest::Test
7
+ def holiday
8
+ NationalHolidays::Holiday.new(
9
+ {
10
+ 'en' => "New Year's Day",
11
+ 'es' => 'Año Nuevo'
12
+ },
13
+ '2018-01-01',
14
+ true
15
+ )
16
+ end
17
+
18
+ def test_names
19
+ assert_equal "New Year's Day", holiday.names.fetch(:en)
20
+ assert_equal 'Año Nuevo', holiday.names.fetch(:es)
21
+ end
22
+
23
+ def test_date
24
+ assert_equal Date.new(2018, 1, 1), holiday.date
25
+ end
26
+
27
+ def test_public_holiday
28
+ assert holiday.public_holiday?
29
+ end
30
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest/autorun'
4
+ require 'national_holidays'
5
+
6
+ class NationalHolidaysRegionTest < Minitest::Test
7
+ def test_code
8
+ assert_equal :united_kingdom01, NationalHolidays::Region.new(:united_kingdom01).code
9
+ assert_equal :united_kingdom01, NationalHolidays::Region.new('united_kingdom01').code
10
+ end
11
+
12
+ def test_name
13
+ assert_equal 'England', NationalHolidays::Region.new(:united_kingdom01).name
14
+ end
15
+
16
+ def test_all_holidays
17
+ refute_empty(NationalHolidays::Region.new(:united_kingdom01).all_holidays.select { |holiday| holiday.date == Date.new(2011, 1, 3) })
18
+ refute_empty(NationalHolidays::Region.new(:united_kingdom01).all_holidays.select { |holiday| holiday.date == Date.new(2040, 1, 2) })
19
+ end
20
+
21
+ def test_holidays_on_or_before
22
+ refute_empty NationalHolidays::Region.new(:united_kingdom01).holidays_on_or_before(Date.new(2018, 1, 1))
23
+ assert_empty(NationalHolidays::Region.new(:united_kingdom01).holidays_on_or_before(Date.new(2018, 1, 1)).select { |holiday| holiday.date > Date.new(2018, 1, 1) })
24
+ assert_equal Date.new(2018, 1, 1), NationalHolidays::Region.new(:united_kingdom01).holidays_on_or_before(Date.new(2018, 1, 1)).last.date
25
+ end
26
+
27
+ def test_holidays_before
28
+ refute_empty NationalHolidays::Region.new(:united_kingdom01).holidays_before(Date.new(2018, 1, 1))
29
+ assert_empty(NationalHolidays::Region.new(:united_kingdom01).holidays_before(Date.new(2018, 1, 1)).select { |holiday| holiday.date >= Date.new(2018, 1, 1) })
30
+ assert_equal Date.new(2017, 12, 26), NationalHolidays::Region.new(:united_kingdom01).holidays_before(Date.new(2018, 1, 1)).last.date
31
+ end
32
+
33
+ def test_holidays_on_or_after
34
+ refute_empty NationalHolidays::Region.new(:united_kingdom01).holidays_on_or_after(Date.new(2018, 1, 1))
35
+ assert_empty(NationalHolidays::Region.new(:united_kingdom01).holidays_on_or_after(Date.new(2018, 1, 1)).select { |holiday| holiday.date < Date.new(2018, 1, 1) })
36
+ assert_equal Date.new(2018, 1, 1), NationalHolidays::Region.new(:united_kingdom01).holidays_on_or_after(Date.new(2018, 1, 1)).first.date
37
+ end
38
+
39
+ def test_holidays_after
40
+ refute_empty NationalHolidays::Region.new(:united_kingdom01).holidays_after(Date.new(2018, 1, 1))
41
+ assert_empty(NationalHolidays::Region.new(:united_kingdom01).holidays_after(Date.new(2018, 1, 1)).select { |holiday| holiday.date <= Date.new(2018, 1, 1) })
42
+ assert_equal Date.new(2018, 3, 30), NationalHolidays::Region.new(:united_kingdom01).holidays_after(Date.new(2018, 1, 1)).first.date
43
+ end
44
+
45
+ def test_holidays_between
46
+ assert_equal(['Good Friday', 'Easter Monday', 'Royal Wedding Day'], NationalHolidays::Region.new(:united_kingdom01).holidays_between(Date.new(2011, 4, 1), Date.new(2011, 4, 30)).map { |holiday| holiday.names.fetch(:en) })
47
+ end
48
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: national_holidays
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Balhatchet
@@ -73,8 +73,18 @@ executables: []
73
73
  extensions: []
74
74
  extra_rdoc_files: []
75
75
  files:
76
+ - LICENSE.txt
77
+ - README.md
78
+ - Rakefile
76
79
  - lib/national_holidays.rb
77
- homepage:
80
+ - lib/national_holidays/country.rb
81
+ - lib/national_holidays/holiday.rb
82
+ - lib/national_holidays/region.rb
83
+ - test/test_national_holidays.rb
84
+ - test/test_national_holidays_country.rb
85
+ - test/test_national_holidays_holiday.rb
86
+ - test/test_national_holidays_region.rb
87
+ homepage: https://github.com/kaoru/national-holidays-ruby
78
88
  licenses:
79
89
  - MIT
80
90
  metadata: {}