finnish-holidays 0.3.1 → 0.3.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 +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +1 -0
- data/Gemfile +2 -0
- data/README.md +3 -1
- data/Rakefile +1 -1
- data/bin/finnish-holidays +2 -57
- data/finnish-holidays.gemspec +3 -3
- data/lib/finnish-holidays/classes/calendar.rb +92 -0
- data/lib/finnish-holidays/classes/year.rb +78 -0
- data/lib/finnish-holidays/cli.rb +81 -0
- data/lib/finnish-holidays/date_utils.rb +135 -0
- data/lib/finnish-holidays/translate.rb +74 -0
- data/lib/{version.rb → finnish-holidays/version.rb} +1 -1
- data/lib/finnish-holidays.rb +3 -3
- metadata +10 -9
- data/Gemfile.lock +0 -8
- data/lib/classes/calendar.rb +0 -90
- data/lib/classes/year.rb +0 -76
- data/lib/utils/date-utils.rb +0 -133
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6aabc4fbef5921fe6f06313c5f260698233624d9
|
|
4
|
+
data.tar.gz: d873d3fb42023b992f755cd4707fb1de5d73a599
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 38736d90a8034ae0b78120fea660b907f69f2afee340173453c09a8925ee9a41d1e5ab658c22b1866fbc4398e5b3149aff74a571779781c101f8868b740dc9d0
|
|
7
|
+
data.tar.gz: c949beca0e6313f4973ffe523a588139ede7b9a9a333274b7d0c3f5d25c191264ebbad722876c41c6877d4d86500581ea4405cebc86a54585c29acd2cb38b8c5
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
finnish-holidays
|
|
2
2
|
================
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
[](https://travis-ci.org/ericnishio/finnish-holidays)
|
|
5
|
+
|
|
6
|
+
A CLI and utility library for listing Finnish national holidays.
|
|
5
7
|
|
|
6
8
|
## Installation
|
|
7
9
|
|
data/Rakefile
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
require
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/bin/finnish-holidays
CHANGED
|
@@ -1,61 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
# encoding: UTF-8
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
require 'optparse'
|
|
6
|
-
require_relative '../lib/finnish-holidays'
|
|
7
|
-
require_relative '../lib/version'
|
|
8
|
-
require_relative '../lib/utils/date-utils'
|
|
4
|
+
require_relative '../lib/finnish-holidays/cli'
|
|
9
5
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
optparse = OptionParser.new do |opts|
|
|
13
|
-
options[:count] = 3
|
|
14
|
-
opts.on('-cCOUNT', '--count=COUNT', 'Number of holidays to list') do |count|
|
|
15
|
-
options[:count] = count.to_i
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
options[:include_weekends] = false
|
|
19
|
-
opts.on('-a', '--all', 'Include holidays falling on a weekend') do
|
|
20
|
-
options[:include_weekends] = true
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
opts.on('-h', '--help', 'Show this screen') do
|
|
24
|
-
puts opts
|
|
25
|
-
exit
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
opts.on('-v', '--version', 'Show version') do
|
|
29
|
-
puts FinnishHolidays::VERSION
|
|
30
|
-
exit
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
options[:year] = nil
|
|
34
|
-
opts.on('-yYEAR', '--year=YEAR', 'List holidays by year') do |year|
|
|
35
|
-
options[:year] = year.to_i
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
options[:month] = nil
|
|
39
|
-
opts.on('-mMONTH', '--month=MONTH', 'List holidays by month') do |month|
|
|
40
|
-
options[:month] = month.to_i
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
optparse.parse!
|
|
45
|
-
|
|
46
|
-
if (options[:month].is_a? Integer) && (!options[:year].is_a? Integer)
|
|
47
|
-
puts 'You must also specify a year with --year=YEAR'
|
|
48
|
-
exit
|
|
49
|
-
elsif (options[:year].is_a? Integer) && (options[:month].is_a? Integer)
|
|
50
|
-
holidays = FinnishHolidays.month(options[:month], options[:year], options[:include_weekends])
|
|
51
|
-
elsif options[:year].is_a? Integer
|
|
52
|
-
holidays = FinnishHolidays.year(options[:year], options[:include_weekends])
|
|
53
|
-
else
|
|
54
|
-
holidays = FinnishHolidays.next(options[:count], options[:include_weekends])
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
holidays.each do |holiday|
|
|
58
|
-
t = Date.new(holiday['year'], holiday['month'], holiday['day'])
|
|
59
|
-
date = t.strftime('%a, %b %e, %Y')
|
|
60
|
-
puts "#{date} #{holiday['description']}"
|
|
61
|
-
end
|
|
6
|
+
FinnishHolidays::CLI.run()
|
data/finnish-holidays.gemspec
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# coding: utf-8
|
|
2
2
|
lib = File.expand_path('../lib', __FILE__)
|
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
|
-
require 'version'
|
|
4
|
+
require 'finnish-holidays/version'
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |spec|
|
|
7
7
|
spec.name = "finnish-holidays"
|
|
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
|
|
|
9
9
|
spec.authors = ["Eric Nishio"]
|
|
10
10
|
spec.email = ["eric@self-learner.com"]
|
|
11
11
|
|
|
12
|
-
spec.summary = %q{A
|
|
13
|
-
spec.description = %q{
|
|
12
|
+
spec.summary = %q{A CLI and utility library for listing Finnish national holidays.}
|
|
13
|
+
spec.description = %q{Lists Finnish national holidays.}
|
|
14
14
|
spec.homepage = "https://github.com/ericnishio/finnish-holidays"
|
|
15
15
|
spec.license = "MIT"
|
|
16
16
|
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
require 'time'
|
|
2
|
+
require_relative 'year'
|
|
3
|
+
require_relative '../date_utils'
|
|
4
|
+
|
|
5
|
+
module FinnishHolidays
|
|
6
|
+
class Calendar
|
|
7
|
+
MAX_HOLIDAYS = 100
|
|
8
|
+
|
|
9
|
+
def initialize(y = nil, m = nil, d = nil)
|
|
10
|
+
@y = y == nil ? Time.now.year : y
|
|
11
|
+
@m = m == nil ? Time.now.month : m
|
|
12
|
+
@d = d == nil ? Time.now.day : d
|
|
13
|
+
|
|
14
|
+
@year = FinnishHolidays::Year.new(@y)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def next(count = 3, include_weekends = false)
|
|
18
|
+
if count > MAX_HOLIDAYS
|
|
19
|
+
raise "Cannot request more than #{MAX_HOLIDAYS} holidays at once."
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
holidays = []
|
|
23
|
+
|
|
24
|
+
while holidays.length < count
|
|
25
|
+
if !include_weekends
|
|
26
|
+
@year.discard_weekends()
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
if (defined? @year.holidays[@m]) && (@year.holidays[@m].is_a? Array)
|
|
30
|
+
@year.holidays[@m].each do |holiday|
|
|
31
|
+
if (holidays.length < count) && (holiday['day'] >= @d)
|
|
32
|
+
holidays.push(holiday)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
if holidays.length < count
|
|
38
|
+
next_month()
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
holidays
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def year(year, weekends = false)
|
|
46
|
+
if !weekends
|
|
47
|
+
@year.discard_weekends()
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
holidays = []
|
|
51
|
+
|
|
52
|
+
@year.holidays.each do |month, array|
|
|
53
|
+
array.each do |holiday|
|
|
54
|
+
holidays.push(holiday)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
holidays
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def month(month, year, weekends = false)
|
|
62
|
+
if !weekends
|
|
63
|
+
@year.discard_weekends()
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
holidays = []
|
|
67
|
+
|
|
68
|
+
if @year.holidays[month].is_a? Array
|
|
69
|
+
@year.holidays[month].each do |holiday|
|
|
70
|
+
holidays.push(holiday)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
holidays
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
private
|
|
78
|
+
|
|
79
|
+
def next_month
|
|
80
|
+
if @m == 12
|
|
81
|
+
@m = 1
|
|
82
|
+
@y += 1
|
|
83
|
+
@d = 1
|
|
84
|
+
else
|
|
85
|
+
@m += 1
|
|
86
|
+
@d = 1
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
@year = FinnishHolidays::Year.new(@y)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
require 'date'
|
|
2
|
+
require_relative '../date_utils'
|
|
3
|
+
|
|
4
|
+
module FinnishHolidays
|
|
5
|
+
class Year
|
|
6
|
+
def initialize(year)
|
|
7
|
+
if year > 0
|
|
8
|
+
@year = year
|
|
9
|
+
@holidays = {}
|
|
10
|
+
load_holidays()
|
|
11
|
+
else
|
|
12
|
+
raise "Invalid year: #{year}"
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def holidays
|
|
17
|
+
@holidays
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def discard_weekends
|
|
21
|
+
holidays = {}
|
|
22
|
+
|
|
23
|
+
@holidays.each do |month, array|
|
|
24
|
+
array.each do |holiday|
|
|
25
|
+
if !FinnishHolidays::DateUtils.is_weekend(holiday['year'], holiday['month'], holiday['day'])
|
|
26
|
+
if !holidays[month].is_a? Array
|
|
27
|
+
holidays[month] = []
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
holidays[month].push(holiday)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
@holidays = holidays
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def load_holidays
|
|
41
|
+
# Holidays must be added in order
|
|
42
|
+
add_holiday(Date.new(@year, 1, 1), "New Year's Day")
|
|
43
|
+
add_holiday(Date.new(@year, 1, 6), 'Epiphany')
|
|
44
|
+
add_holiday(FinnishHolidays::DateUtils.good_friday(@year), 'Good Friday')
|
|
45
|
+
add_holiday(FinnishHolidays::DateUtils.easter_sunday(@year), 'Easter Sunday')
|
|
46
|
+
add_holiday(FinnishHolidays::DateUtils.easter_monday(@year), 'Easter Monday')
|
|
47
|
+
add_holiday(Date.new(@year, 1, 1), 'May Day')
|
|
48
|
+
add_holiday(FinnishHolidays::DateUtils.ascension_day(@year), 'Ascension Day')
|
|
49
|
+
add_holiday(FinnishHolidays::DateUtils.pentecost(@year), 'Pentecost')
|
|
50
|
+
add_holiday(FinnishHolidays::DateUtils.midsummer_eve(@year), 'Midsummer Eve (unofficial)')
|
|
51
|
+
add_holiday(FinnishHolidays::DateUtils.midsummer_day(@year), 'Midsummer Day')
|
|
52
|
+
add_holiday(FinnishHolidays::DateUtils.all_saints_day(@year), "All Saints' Day")
|
|
53
|
+
add_holiday(Date.new(@year, 12, 6), 'Independence Day')
|
|
54
|
+
add_holiday(Date.new(@year, 12, 24), 'Christmas Eve (unofficial)')
|
|
55
|
+
add_holiday(Date.new(@year, 12, 25), 'Christmas Day')
|
|
56
|
+
add_holiday(Date.new(@year, 12, 26), "St. Stephen's Day")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def add_holiday(date, description)
|
|
60
|
+
year = FinnishHolidays::DateUtils.get_year_from_date(date)
|
|
61
|
+
month = FinnishHolidays::DateUtils.get_month_from_date(date)
|
|
62
|
+
day = FinnishHolidays::DateUtils.get_day_from_date(date)
|
|
63
|
+
|
|
64
|
+
if !@holidays[month].is_a? Array
|
|
65
|
+
@holidays[month] = []
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
holiday = {
|
|
69
|
+
'year' => year,
|
|
70
|
+
'month' => month,
|
|
71
|
+
'day' => day,
|
|
72
|
+
'description' => description
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@holidays[month].push(holiday)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
require 'date'
|
|
2
|
+
require 'optparse'
|
|
3
|
+
require_relative 'date_utils'
|
|
4
|
+
require_relative 'translate'
|
|
5
|
+
require_relative 'version'
|
|
6
|
+
require_relative '../finnish-holidays'
|
|
7
|
+
|
|
8
|
+
module FinnishHolidays
|
|
9
|
+
module CLI
|
|
10
|
+
def self.run()
|
|
11
|
+
options = {}
|
|
12
|
+
|
|
13
|
+
optparse = OptionParser.new do |opts|
|
|
14
|
+
options[:count] = 3
|
|
15
|
+
opts.on('-cCOUNT', '--count=COUNT', 'Number of holidays to list') do |count|
|
|
16
|
+
options[:count] = count.to_i
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
options[:include_weekends] = false
|
|
20
|
+
opts.on('-a', '--all', 'Include holidays falling on a weekend') do
|
|
21
|
+
options[:include_weekends] = true
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
opts.on('-h', '--help', 'Show this screen') do
|
|
25
|
+
puts opts
|
|
26
|
+
exit 0
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
opts.on('-v', '--version', 'Show version') do
|
|
30
|
+
puts FinnishHolidays::VERSION
|
|
31
|
+
exit 0
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
options[:year] = nil
|
|
35
|
+
opts.on('-yYEAR', '--year=YEAR', 'List holidays by year') do |year|
|
|
36
|
+
options[:year] = year.to_i
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
options[:month] = nil
|
|
40
|
+
opts.on('-mMONTH', '--month=MONTH', 'List holidays by month') do |month|
|
|
41
|
+
options[:month] = month.to_i
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
options[:language] = nil
|
|
45
|
+
opts.on('-lLANGUAGE', '--language=LANGUAGE', 'Translate holidays (fi|sv)') do |language|
|
|
46
|
+
if !['fi', 'sv'].include? language
|
|
47
|
+
puts 'Language must be fi (Finnish) or sv (Swedish).'
|
|
48
|
+
exit 1
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
options[:language] = language
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
optparse.parse!
|
|
56
|
+
|
|
57
|
+
if (options[:month].is_a? Integer) && (!options[:year].is_a? Integer)
|
|
58
|
+
puts 'You must also specify a year with --year=YEAR'
|
|
59
|
+
exit 1
|
|
60
|
+
elsif (options[:year].is_a? Integer) && (options[:month].is_a? Integer)
|
|
61
|
+
holidays = FinnishHolidays.month(options[:month], options[:year], options[:include_weekends])
|
|
62
|
+
elsif options[:year].is_a? Integer
|
|
63
|
+
holidays = FinnishHolidays.year(options[:year], options[:include_weekends])
|
|
64
|
+
else
|
|
65
|
+
holidays = FinnishHolidays.next(options[:count], options[:include_weekends])
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
holidays.each do |holiday|
|
|
69
|
+
d = Date.new(holiday['year'], holiday['month'], holiday['day'])
|
|
70
|
+
date = d.strftime('%a, %b %e, %Y')
|
|
71
|
+
description = holiday['description']
|
|
72
|
+
|
|
73
|
+
if ['fi', 'sv'].include? options[:language]
|
|
74
|
+
description = FinnishHolidays::Translate.into(options[:language], holiday['description'])
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
puts "#{date} #{description}"
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
require 'date'
|
|
2
|
+
|
|
3
|
+
module FinnishHolidays
|
|
4
|
+
class DateUtils
|
|
5
|
+
FRIDAY = 5
|
|
6
|
+
SATURDAY = 6
|
|
7
|
+
SUNDAY = 7
|
|
8
|
+
|
|
9
|
+
def self.is_weekend(year, month, day)
|
|
10
|
+
t = Date.new(year, month, day)
|
|
11
|
+
day_of_week = t.strftime('%u').to_i
|
|
12
|
+
[SATURDAY, SUNDAY].include? day_of_week
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.easter_sunday(year)
|
|
16
|
+
a = year % 19
|
|
17
|
+
b = year / 100
|
|
18
|
+
c = year % 100
|
|
19
|
+
d = b / 4
|
|
20
|
+
e = b % 4
|
|
21
|
+
f = (b + 8) / 25
|
|
22
|
+
g = (b - f + 1) / 3
|
|
23
|
+
h = (19 * a + b - d - g + 15) % 30
|
|
24
|
+
i = c / 4
|
|
25
|
+
k = c % 4
|
|
26
|
+
l = (32 + 2 * e + 2 * i - h - k) % 7
|
|
27
|
+
m = (a + 11 * h + 22 * l) / 451
|
|
28
|
+
x = h + l - 7 * m + 114
|
|
29
|
+
month = x / 31
|
|
30
|
+
day = (x % 31) + 1
|
|
31
|
+
Date.new(year, month, day)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Day after Easter Sunday
|
|
35
|
+
def self.easter_monday(year)
|
|
36
|
+
self.easter_sunday(year).next_day
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Friday before Easter Sunday
|
|
40
|
+
def self.good_friday(year)
|
|
41
|
+
date = self.easter_sunday(year)
|
|
42
|
+
day_of_week = nil
|
|
43
|
+
|
|
44
|
+
while day_of_week != FRIDAY
|
|
45
|
+
day_of_week = date.strftime('%u').to_i
|
|
46
|
+
|
|
47
|
+
if (day_of_week != FRIDAY)
|
|
48
|
+
date = date.prev_day
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
date
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# 39 days after Easter Sunday
|
|
56
|
+
def self.ascension_day(year)
|
|
57
|
+
easter_sunday = self.easter_sunday(year)
|
|
58
|
+
easter_sunday.next_day(39)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# 49 days after Easter Sunday
|
|
62
|
+
def self.pentecost(year)
|
|
63
|
+
easter_sunday = self.easter_sunday(year)
|
|
64
|
+
easter_sunday.next_day(49)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Friday between June 19-25
|
|
68
|
+
def self.midsummer_eve(year)
|
|
69
|
+
month = 6
|
|
70
|
+
|
|
71
|
+
(19..25).to_a.each do |day|
|
|
72
|
+
day_of_week = Date.new(year, month, day).strftime('%u').to_i
|
|
73
|
+
|
|
74
|
+
if day_of_week == FRIDAY
|
|
75
|
+
return Date.new(year, month, day)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# Saturday between June 20-26
|
|
81
|
+
def self.midsummer_day(year)
|
|
82
|
+
month = 6
|
|
83
|
+
|
|
84
|
+
(20..26).to_a.each do |day|
|
|
85
|
+
day_of_week = Date.new(year, month, day).strftime('%u').to_i
|
|
86
|
+
|
|
87
|
+
if day_of_week == SATURDAY
|
|
88
|
+
return Date.new(year, month, day)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Saturday between October 31 and November 6
|
|
94
|
+
def self.all_saints_day(year)
|
|
95
|
+
october_31 = Date.new(year, 10, 31)
|
|
96
|
+
second_month = 11
|
|
97
|
+
|
|
98
|
+
if october_31.strftime('%u').to_i == SATURDAY
|
|
99
|
+
return october_31
|
|
100
|
+
else
|
|
101
|
+
(1..6).to_a.each do |day|
|
|
102
|
+
day_of_week = Date.new(year, second_month, day).strftime('%u').to_i
|
|
103
|
+
|
|
104
|
+
if day_of_week == SATURDAY
|
|
105
|
+
return Date.new(year, second_month, day)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def self.get_year_from_date(date)
|
|
112
|
+
date.strftime('%Y').to_i
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def self.get_month_from_date(date)
|
|
116
|
+
date.strftime('%-m').to_i
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def self.get_day_from_date(date)
|
|
120
|
+
date.strftime('%-d').to_i
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def self.zerofy(num)
|
|
124
|
+
num = num.to_i
|
|
125
|
+
|
|
126
|
+
if num < 10
|
|
127
|
+
num = '0' + num.to_s
|
|
128
|
+
else
|
|
129
|
+
num = num.to_s
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
num
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
module FinnishHolidays
|
|
2
|
+
module Translate
|
|
3
|
+
def self.into(language, original)
|
|
4
|
+
translations = {
|
|
5
|
+
"New Year's Day" => {
|
|
6
|
+
'fi' => 'Uudenvuodenpäivä',
|
|
7
|
+
'sv' => 'Nyårsdagen'
|
|
8
|
+
},
|
|
9
|
+
'Epiphany' => {
|
|
10
|
+
'fi' => 'Loppiainen',
|
|
11
|
+
'sv' => 'Trettondedagen'
|
|
12
|
+
},
|
|
13
|
+
'Good Friday' => {
|
|
14
|
+
'fi' => 'Pitkäperjantai',
|
|
15
|
+
'sv' => 'Långfredagen'
|
|
16
|
+
},
|
|
17
|
+
'Easter Sunday' => {
|
|
18
|
+
'fi' => 'Pääsiäispäivä',
|
|
19
|
+
'sv' => 'Påskdagen'
|
|
20
|
+
},
|
|
21
|
+
'Easter Monday' => {
|
|
22
|
+
'fi' => 'Toinen pääsiäispäivä',
|
|
23
|
+
'sv' => 'Andra påskdagen'
|
|
24
|
+
},
|
|
25
|
+
'May Day' => {
|
|
26
|
+
'fi' => 'Vappu',
|
|
27
|
+
'sv' => 'Valborgsmässoafton'
|
|
28
|
+
},
|
|
29
|
+
'Ascension Day' => {
|
|
30
|
+
'fi' => 'Helatorstai',
|
|
31
|
+
'sv' => 'Kristi himmelfärds dag'
|
|
32
|
+
},
|
|
33
|
+
'Pentecost' => {
|
|
34
|
+
'fi' => 'Helluntaipäivä',
|
|
35
|
+
'sv' => 'Pingst'
|
|
36
|
+
},
|
|
37
|
+
'Midsummer Eve (unofficial)' => {
|
|
38
|
+
'fi' => 'Juhannusaatto (unofficial)',
|
|
39
|
+
'sv' => 'Midsommarafton (unofficial)'
|
|
40
|
+
},
|
|
41
|
+
'Midsummer Day' => {
|
|
42
|
+
'fi' => 'Juhannuspäivä',
|
|
43
|
+
'sv' => 'Midsommardagen'
|
|
44
|
+
},
|
|
45
|
+
"All Saints' Day" => {
|
|
46
|
+
'fi' => 'Pyhäinpäivä',
|
|
47
|
+
'sv' => 'Alla helgons dag'
|
|
48
|
+
},
|
|
49
|
+
'Independence Day' => {
|
|
50
|
+
'fi' => 'Itsenäisyyspäivä',
|
|
51
|
+
'sv' => 'Självständighetsdagen'
|
|
52
|
+
},
|
|
53
|
+
'Christmas Eve (unofficial)' => {
|
|
54
|
+
'fi' => 'Jouluaatto (unofficial)',
|
|
55
|
+
'sv' => 'Julafton (unofficial)'
|
|
56
|
+
},
|
|
57
|
+
'Christmas Day' => {
|
|
58
|
+
'fi' => 'Joulupäivä',
|
|
59
|
+
'sv' => 'Juldagen'
|
|
60
|
+
},
|
|
61
|
+
"St. Stephen's Day" => {
|
|
62
|
+
'fi' => 'Tapaninpäivä',
|
|
63
|
+
'sv' => 'Andra juldagen'
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if translations[original] && (translations[original][language].is_a? String)
|
|
68
|
+
return translations[original][language]
|
|
69
|
+
else
|
|
70
|
+
return original
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
data/lib/finnish-holidays.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require_relative 'classes/calendar'
|
|
1
|
+
require_relative 'finnish-holidays/classes/calendar'
|
|
2
2
|
|
|
3
3
|
module FinnishHolidays
|
|
4
4
|
# Lists the next holidays relative to today's date
|
|
@@ -8,11 +8,11 @@ module FinnishHolidays
|
|
|
8
8
|
|
|
9
9
|
# Lists holidays for the given year
|
|
10
10
|
def self.year(year, include_weekends = false)
|
|
11
|
-
Calendar.new(year, 1, 1).year(year, include_weekends)
|
|
11
|
+
FinnishHolidays::Calendar.new(year, 1, 1).year(year, include_weekends)
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
# Lists holidays for the given month (and year)
|
|
15
15
|
def self.month(month, year, include_weekends = false)
|
|
16
|
-
Calendar.new(year, month, 1).month(month, year, include_weekends)
|
|
16
|
+
FinnishHolidays::Calendar.new(year, month, 1).month(month, year, include_weekends)
|
|
17
17
|
end
|
|
18
18
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: finnish-holidays
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.3.
|
|
4
|
+
version: 0.3.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Eric Nishio
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2015-04-
|
|
11
|
+
date: 2015-04-28 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -38,7 +38,7 @@ dependencies:
|
|
|
38
38
|
- - ~>
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '10.0'
|
|
41
|
-
description:
|
|
41
|
+
description: Lists Finnish national holidays.
|
|
42
42
|
email:
|
|
43
43
|
- eric@self-learner.com
|
|
44
44
|
executables:
|
|
@@ -51,17 +51,18 @@ files:
|
|
|
51
51
|
- .rspec
|
|
52
52
|
- .travis.yml
|
|
53
53
|
- Gemfile
|
|
54
|
-
- Gemfile.lock
|
|
55
54
|
- LICENSE.txt
|
|
56
55
|
- README.md
|
|
57
56
|
- Rakefile
|
|
58
57
|
- bin/finnish-holidays
|
|
59
58
|
- finnish-holidays.gemspec
|
|
60
|
-
- lib/classes/calendar.rb
|
|
61
|
-
- lib/classes/year.rb
|
|
62
59
|
- lib/finnish-holidays.rb
|
|
63
|
-
- lib/
|
|
64
|
-
- lib/
|
|
60
|
+
- lib/finnish-holidays/classes/calendar.rb
|
|
61
|
+
- lib/finnish-holidays/classes/year.rb
|
|
62
|
+
- lib/finnish-holidays/cli.rb
|
|
63
|
+
- lib/finnish-holidays/date_utils.rb
|
|
64
|
+
- lib/finnish-holidays/translate.rb
|
|
65
|
+
- lib/finnish-holidays/version.rb
|
|
65
66
|
homepage: https://github.com/ericnishio/finnish-holidays
|
|
66
67
|
licenses:
|
|
67
68
|
- MIT
|
|
@@ -86,5 +87,5 @@ rubyforge_project:
|
|
|
86
87
|
rubygems_version: 2.0.6
|
|
87
88
|
signing_key:
|
|
88
89
|
specification_version: 4
|
|
89
|
-
summary: A
|
|
90
|
+
summary: A CLI and utility library for listing Finnish national holidays.
|
|
90
91
|
test_files: []
|
data/Gemfile.lock
DELETED
data/lib/classes/calendar.rb
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
require 'time'
|
|
2
|
-
require_relative 'year'
|
|
3
|
-
require_relative '../utils/date-utils'
|
|
4
|
-
|
|
5
|
-
class Calendar
|
|
6
|
-
MAX_HOLIDAYS = 100
|
|
7
|
-
|
|
8
|
-
def initialize(y = nil, m = nil, d = nil)
|
|
9
|
-
@y = y == nil ? Time.now.year : y
|
|
10
|
-
@m = m == nil ? Time.now.month : m
|
|
11
|
-
@d = d == nil ? Time.now.day : d
|
|
12
|
-
|
|
13
|
-
@year = Year.new(@y)
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def next(count = 3, include_weekends = false)
|
|
17
|
-
if count > MAX_HOLIDAYS
|
|
18
|
-
raise "Cannot request more than #{MAX_HOLIDAYS} holidays at once."
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
holidays = []
|
|
22
|
-
|
|
23
|
-
while holidays.length < count
|
|
24
|
-
if !include_weekends
|
|
25
|
-
@year.discard_weekends()
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
if (defined? @year.holidays[@m]) && (@year.holidays[@m].is_a? Array)
|
|
29
|
-
@year.holidays[@m].each do |holiday|
|
|
30
|
-
if (holidays.length < count) && (holiday['day'] >= @d)
|
|
31
|
-
holidays.push(holiday)
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
if holidays.length < count
|
|
37
|
-
next_month()
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
holidays
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def year(year, weekends = false)
|
|
45
|
-
if !weekends
|
|
46
|
-
@year.discard_weekends()
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
holidays = []
|
|
50
|
-
|
|
51
|
-
@year.holidays.each do |month, array|
|
|
52
|
-
array.each do |holiday|
|
|
53
|
-
holidays.push(holiday)
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
holidays
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def month(month, year, weekends = false)
|
|
61
|
-
if !weekends
|
|
62
|
-
@year.discard_weekends()
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
holidays = []
|
|
66
|
-
|
|
67
|
-
if @year.holidays[month].is_a? Array
|
|
68
|
-
@year.holidays[month].each do |holiday|
|
|
69
|
-
holidays.push(holiday)
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
holidays
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
private
|
|
77
|
-
|
|
78
|
-
def next_month
|
|
79
|
-
if @m == 12
|
|
80
|
-
@m = 1
|
|
81
|
-
@y += 1
|
|
82
|
-
@d = 1
|
|
83
|
-
else
|
|
84
|
-
@m += 1
|
|
85
|
-
@d = 1
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
@year = Year.new(@y)
|
|
89
|
-
end
|
|
90
|
-
end
|
data/lib/classes/year.rb
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
require 'date'
|
|
2
|
-
require_relative '../utils/date-utils'
|
|
3
|
-
|
|
4
|
-
class Year
|
|
5
|
-
def initialize(year)
|
|
6
|
-
if year > 0
|
|
7
|
-
@year = year
|
|
8
|
-
@holidays = {}
|
|
9
|
-
load_holidays()
|
|
10
|
-
else
|
|
11
|
-
raise "Invalid year: #{year}"
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def holidays
|
|
16
|
-
@holidays
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def discard_weekends
|
|
20
|
-
holidays = {}
|
|
21
|
-
|
|
22
|
-
@holidays.each do |month, array|
|
|
23
|
-
array.each do |holiday|
|
|
24
|
-
if !DateUtils.is_weekend(holiday['year'], holiday['month'], holiday['day'])
|
|
25
|
-
if !holidays[month].is_a? Array
|
|
26
|
-
holidays[month] = []
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
holidays[month].push(holiday)
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
@holidays = holidays
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
private
|
|
38
|
-
|
|
39
|
-
def load_holidays
|
|
40
|
-
# Holidays must be added in order
|
|
41
|
-
add_holiday(Date.new(@year, 1, 1), "New Year's Day")
|
|
42
|
-
add_holiday(Date.new(@year, 1, 6), 'Epiphany')
|
|
43
|
-
add_holiday(DateUtils.good_friday(@year), 'Good Friday')
|
|
44
|
-
add_holiday(DateUtils.easter_sunday(@year), 'Easter Sunday')
|
|
45
|
-
add_holiday(DateUtils.easter_monday(@year), 'Easter Monday')
|
|
46
|
-
add_holiday(Date.new(@year, 1, 1), 'May Day')
|
|
47
|
-
add_holiday(DateUtils.ascension_day(@year), 'Ascension Day')
|
|
48
|
-
add_holiday(DateUtils.pentecost(@year), 'Pentecost')
|
|
49
|
-
add_holiday(DateUtils.midsummer_eve(@year), 'Midsummer Eve (unofficial)')
|
|
50
|
-
add_holiday(DateUtils.midsummer_day(@year), 'Midsummer Day')
|
|
51
|
-
add_holiday(DateUtils.all_saints_day(@year), "All Saints' Day")
|
|
52
|
-
add_holiday(Date.new(@year, 12, 6), 'Independence Day')
|
|
53
|
-
add_holiday(Date.new(@year, 12, 24), 'Christmas Eve (unofficial)')
|
|
54
|
-
add_holiday(Date.new(@year, 12, 25), 'Christmas Day')
|
|
55
|
-
add_holiday(Date.new(@year, 12, 26), "St. Stephen's Day")
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def add_holiday(date, description)
|
|
59
|
-
year = DateUtils.get_year_from_date(date)
|
|
60
|
-
month = DateUtils.get_month_from_date(date)
|
|
61
|
-
day = DateUtils.get_day_from_date(date)
|
|
62
|
-
|
|
63
|
-
if !@holidays[month].is_a? Array
|
|
64
|
-
@holidays[month] = []
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
holiday = {
|
|
68
|
-
'year' => year,
|
|
69
|
-
'month' => month,
|
|
70
|
-
'day' => day,
|
|
71
|
-
'description' => description
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
@holidays[month].push(holiday)
|
|
75
|
-
end
|
|
76
|
-
end
|
data/lib/utils/date-utils.rb
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
require 'date'
|
|
2
|
-
|
|
3
|
-
class DateUtils
|
|
4
|
-
FRIDAY = 5
|
|
5
|
-
SATURDAY = 6
|
|
6
|
-
SUNDAY = 7
|
|
7
|
-
|
|
8
|
-
def self.is_weekend(year, month, day)
|
|
9
|
-
t = Date.new(year, month, day)
|
|
10
|
-
day_of_week = t.strftime('%u').to_i
|
|
11
|
-
[SATURDAY, SUNDAY].include? day_of_week
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def self.easter_sunday(year)
|
|
15
|
-
a = year % 19
|
|
16
|
-
b = year / 100
|
|
17
|
-
c = year % 100
|
|
18
|
-
d = b / 4
|
|
19
|
-
e = b % 4
|
|
20
|
-
f = (b + 8) / 25
|
|
21
|
-
g = (b - f + 1) / 3
|
|
22
|
-
h = (19 * a + b - d - g + 15) % 30
|
|
23
|
-
i = c / 4
|
|
24
|
-
k = c % 4
|
|
25
|
-
l = (32 + 2 * e + 2 * i - h - k) % 7
|
|
26
|
-
m = (a + 11 * h + 22 * l) / 451
|
|
27
|
-
x = h + l - 7 * m + 114
|
|
28
|
-
month = x / 31
|
|
29
|
-
day = (x % 31) + 1
|
|
30
|
-
Date.new(year, month, day)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# Day after Easter Sunday
|
|
34
|
-
def self.easter_monday(year)
|
|
35
|
-
self.easter_sunday(year).next_day
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
# Friday before Easter Sunday
|
|
39
|
-
def self.good_friday(year)
|
|
40
|
-
date = self.easter_sunday(year)
|
|
41
|
-
day_of_week = nil
|
|
42
|
-
|
|
43
|
-
while day_of_week != FRIDAY
|
|
44
|
-
day_of_week = date.strftime('%u').to_i
|
|
45
|
-
|
|
46
|
-
if (day_of_week != FRIDAY)
|
|
47
|
-
date = date.prev_day
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
date
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# 39 days after Easter Sunday
|
|
55
|
-
def self.ascension_day(year)
|
|
56
|
-
easter_sunday = self.easter_sunday(year)
|
|
57
|
-
easter_sunday.next_day(39)
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
# 49 days after Easter Sunday
|
|
61
|
-
def self.pentecost(year)
|
|
62
|
-
easter_sunday = self.easter_sunday(year)
|
|
63
|
-
easter_sunday.next_day(49)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
# Friday between June 19-25
|
|
67
|
-
def self.midsummer_eve(year)
|
|
68
|
-
month = 6
|
|
69
|
-
|
|
70
|
-
(19..25).to_a.each do |day|
|
|
71
|
-
day_of_week = Date.new(year, month, day).strftime('%u').to_i
|
|
72
|
-
|
|
73
|
-
if day_of_week == FRIDAY
|
|
74
|
-
return Date.new(year, month, day)
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
# Saturday between June 20-26
|
|
80
|
-
def self.midsummer_day(year)
|
|
81
|
-
month = 6
|
|
82
|
-
|
|
83
|
-
(20..26).to_a.each do |day|
|
|
84
|
-
day_of_week = Date.new(year, month, day).strftime('%u').to_i
|
|
85
|
-
|
|
86
|
-
if day_of_week == SATURDAY
|
|
87
|
-
return Date.new(year, month, day)
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
# Saturday between October 31 and November 6
|
|
93
|
-
def self.all_saints_day(year)
|
|
94
|
-
october_31 = Date.new(year, 10, 31)
|
|
95
|
-
second_month = 11
|
|
96
|
-
|
|
97
|
-
if october_31.strftime('%u').to_i == SATURDAY
|
|
98
|
-
return october_31
|
|
99
|
-
else
|
|
100
|
-
(1..6).to_a.each do |day|
|
|
101
|
-
day_of_week = Date.new(year, second_month, day).strftime('%u').to_i
|
|
102
|
-
|
|
103
|
-
if day_of_week == SATURDAY
|
|
104
|
-
return Date.new(year, second_month, day)
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
end
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def self.get_year_from_date(date)
|
|
111
|
-
date.strftime('%Y').to_i
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
def self.get_month_from_date(date)
|
|
115
|
-
date.strftime('%-m').to_i
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
def self.get_day_from_date(date)
|
|
119
|
-
date.strftime('%-d').to_i
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
def self.zerofy(num)
|
|
123
|
-
num = num.to_i
|
|
124
|
-
|
|
125
|
-
if num < 10
|
|
126
|
-
num = '0' + num.to_s
|
|
127
|
-
else
|
|
128
|
-
num = num.to_s
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
num
|
|
132
|
-
end
|
|
133
|
-
end
|