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 +4 -4
- data/LICENSE.txt +21 -0
- data/README.md +95 -0
- data/Rakefile +10 -0
- data/lib/national_holidays/country.rb +30 -0
- data/lib/national_holidays/holiday.rb +17 -0
- data/lib/national_holidays/region.rb +84 -0
- data/test/test_national_holidays.rb +24 -0
- data/test/test_national_holidays_country.rb +19 -0
- data/test/test_national_holidays_holiday.rb +30 -0
- data/test/test_national_holidays_region.rb +48 -0
- metadata +12 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb7291b45904d9a8e6eabe11401ebcc3177e7385
|
4
|
+
data.tar.gz: 5bed83c2b535c5461d6d59f75278cf972e12b54a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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,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.
|
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
|
-
|
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: {}
|