national_holidays 0.0.1 → 0.0.2

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: 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: {}