holidays 3.3.0 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +44 -0
- data/CONTRIBUTING.md +37 -0
- data/README.md +16 -25
- data/REFERENCES +4 -1
- data/Rakefile +38 -8
- data/benchmark.rb +8 -0
- data/definitions/README.md +187 -8
- data/definitions/ar.yaml +2 -1
- data/definitions/at.yaml +17 -13
- data/definitions/au.yaml +65 -60
- data/definitions/be_fr.yaml +14 -10
- data/definitions/be_nl.yaml +8 -4
- data/definitions/bg.yaml +12 -6
- data/definitions/br.yaml +6 -3
- data/definitions/ca.yaml +8 -6
- data/definitions/ch.yaml +21 -15
- data/definitions/cl.yaml +4 -2
- data/definitions/cr.yaml +5 -3
- data/definitions/cz.yaml +4 -2
- data/definitions/de.yaml +25 -14
- data/definitions/dk.yaml +26 -17
- data/definitions/ecb_target.yaml +4 -2
- data/definitions/el.yaml +23 -18
- data/definitions/es.yaml +31 -28
- data/definitions/federal_reserve.yaml +12 -12
- data/definitions/fedex.yaml +6 -6
- data/definitions/fi.yaml +26 -25
- data/definitions/fr.yaml +8 -4
- data/definitions/gb.yaml +9 -7
- data/definitions/hr.yaml +8 -6
- data/definitions/hu.yaml +8 -6
- data/definitions/ie.yaml +17 -16
- data/definitions/index.yaml +1 -1
- data/definitions/is.yaml +29 -19
- data/definitions/it.yaml +10 -9
- data/definitions/jp.yaml +92 -44
- data/definitions/li.yaml +25 -20
- data/definitions/lt.yaml +2 -1
- data/definitions/ma.yaml +7 -7
- data/definitions/mx.yaml +11 -11
- data/definitions/nerc.yaml +6 -6
- data/definitions/nl.yaml +22 -18
- data/definitions/no.yaml +19 -11
- data/definitions/north_america_informal.yaml +6 -6
- data/definitions/nyse.yaml +9 -8
- data/definitions/nz.yaml +33 -29
- data/definitions/ph.yaml +15 -8
- data/definitions/pl.yaml +27 -17
- data/definitions/pt.yaml +4 -2
- data/definitions/ro.yaml +21 -18
- data/definitions/se.yaml +24 -18
- data/definitions/sg.yaml +10 -9
- data/definitions/si.yaml +4 -2
- data/definitions/sk.yaml +4 -2
- data/definitions/united_nations.yaml +12 -12
- data/definitions/ups.yaml +6 -6
- data/definitions/us.yaml +12 -11
- data/definitions/ve.yaml +8 -4
- data/definitions/vi.yaml +6 -6
- data/definitions/za.yaml +26 -24
- data/holidays.gemspec +3 -1
- data/lib/generated_definitions/MANIFEST +1 -1
- data/lib/generated_definitions/ar.rb +8 -6
- data/lib/generated_definitions/at.rb +11 -9
- data/lib/generated_definitions/au.rb +75 -99
- data/lib/generated_definitions/be.rb +12 -10
- data/lib/generated_definitions/be_fr.rb +12 -10
- data/lib/generated_definitions/be_nl.rb +12 -10
- data/lib/generated_definitions/bg.rb +14 -13
- data/lib/generated_definitions/br.rb +11 -9
- data/lib/generated_definitions/ca.rb +20 -20
- data/lib/generated_definitions/ch.rb +41 -44
- data/lib/generated_definitions/cl.rb +9 -7
- data/lib/generated_definitions/cr.rb +9 -7
- data/lib/generated_definitions/cz.rb +9 -6
- data/lib/generated_definitions/de.rb +25 -25
- data/lib/generated_definitions/dk.rb +17 -15
- data/lib/generated_definitions/ecb_target.rb +9 -7
- data/lib/generated_definitions/el.rb +13 -11
- data/lib/generated_definitions/es.rb +35 -33
- data/lib/generated_definitions/europe.rb +234 -247
- data/lib/generated_definitions/federal_reserve.rb +11 -9
- data/lib/generated_definitions/fedex.rb +42 -0
- data/lib/generated_definitions/fi.rb +32 -36
- data/lib/generated_definitions/fr.rb +12 -10
- data/lib/generated_definitions/gb.rb +15 -13
- data/lib/generated_definitions/hr.rb +10 -8
- data/lib/generated_definitions/hu.rb +9 -7
- data/lib/generated_definitions/ie.rb +17 -17
- data/lib/generated_definitions/is.rb +26 -26
- data/lib/generated_definitions/it.rb +9 -7
- data/lib/generated_definitions/jp.rb +112 -89
- data/lib/generated_definitions/li.rb +14 -12
- data/lib/generated_definitions/lt.rb +9 -7
- data/lib/generated_definitions/ma.rb +7 -5
- data/lib/generated_definitions/mx.rb +7 -5
- data/lib/generated_definitions/nerc.rb +10 -8
- data/lib/generated_definitions/nl.rb +15 -13
- data/lib/generated_definitions/no.rb +16 -14
- data/lib/generated_definitions/north_america.rb +34 -37
- data/lib/generated_definitions/nyse.rb +10 -8
- data/lib/generated_definitions/nz.rb +40 -40
- data/lib/generated_definitions/ph.rb +17 -13
- data/lib/generated_definitions/pl.rb +25 -27
- data/lib/generated_definitions/pt.rb +10 -8
- data/lib/generated_definitions/ro.rb +11 -9
- data/lib/generated_definitions/scandinavia.rb +92 -102
- data/lib/generated_definitions/se.rb +25 -27
- data/lib/generated_definitions/sg.rb +11 -9
- data/lib/generated_definitions/si.rb +10 -8
- data/lib/generated_definitions/sk.rb +9 -7
- data/lib/generated_definitions/united_nations.rb +7 -5
- data/lib/generated_definitions/ups.rb +13 -12
- data/lib/generated_definitions/us.rb +20 -21
- data/lib/generated_definitions/ve.rb +11 -9
- data/lib/generated_definitions/vi.rb +7 -5
- data/lib/generated_definitions/za.rb +19 -17
- data/lib/holidays.rb +20 -83
- data/lib/holidays/date_calculator/weekend_modifier.rb +22 -5
- data/lib/holidays/definition/context/generator.rb +67 -29
- data/lib/holidays/definition/context/merger.rb +8 -8
- data/lib/holidays/definition/decorator/custom_method_proc.rb +28 -0
- data/lib/holidays/definition/decorator/custom_method_source.rb +30 -0
- data/lib/holidays/definition/entity/custom_method.rb +11 -0
- data/lib/holidays/definition/parser/custom_method.rb +69 -0
- data/lib/holidays/definition/repository/custom_methods.rb +27 -0
- data/lib/holidays/definition/repository/holidays_by_month.rb +1 -1
- data/lib/holidays/definition/repository/{proc_cache.rb → proc_result_cache.rb} +19 -4
- data/lib/holidays/definition/validator/custom_method.rb +31 -0
- data/lib/holidays/definition_factory.rb +42 -6
- data/lib/holidays/errors.rb +6 -0
- data/lib/holidays/load_all_definitions.rb +57 -0
- data/lib/holidays/option/context/parse_options.rb +26 -16
- data/lib/holidays/option_factory.rb +1 -0
- data/lib/holidays/use_case/context/between.rb +41 -14
- data/lib/holidays/use_case_factory.rb +2 -1
- data/lib/holidays/version.rb +1 -1
- data/test/data/test_single_custom_holiday_with_custom_procs.yaml +24 -0
- data/test/defs/test_defs_at.rb +1 -1
- data/test/defs/test_defs_au.rb +3 -2
- data/test/defs/test_defs_cr.rb +1 -0
- data/test/defs/test_defs_cz.rb +1 -0
- data/test/defs/test_defs_dk.rb +2 -2
- data/test/defs/test_defs_el.rb +7 -6
- data/test/defs/test_defs_europe.rb +40 -33
- data/test/defs/test_defs_fedex.rb +24 -0
- data/test/defs/test_defs_fi.rb +4 -3
- data/test/defs/test_defs_hr.rb +2 -2
- data/test/defs/test_defs_hu.rb +2 -2
- data/test/defs/test_defs_is.rb +2 -1
- data/test/defs/test_defs_it.rb +2 -1
- data/test/defs/test_defs_jp.rb +1 -1
- data/test/defs/test_defs_li.rb +1 -1
- data/test/defs/test_defs_ma.rb +2 -1
- data/test/defs/test_defs_mx.rb +4 -3
- data/test/defs/test_defs_nl.rb +7 -6
- data/test/defs/test_defs_no.rb +1 -0
- data/test/defs/test_defs_north_america.rb +4 -3
- data/test/defs/test_defs_nyse.rb +2 -1
- data/test/defs/test_defs_pl.rb +1 -0
- data/test/defs/test_defs_ro.rb +11 -11
- data/test/defs/test_defs_scandinavia.rb +12 -8
- data/test/defs/test_defs_se.rb +3 -2
- data/test/defs/test_defs_sg.rb +2 -1
- data/test/defs/test_defs_vi.rb +1 -1
- data/test/defs/test_defs_za.rb +3 -2
- data/test/holidays/date_calculator/test_weekend_modifier.rb +11 -0
- data/test/holidays/definition/context/test_generator.rb +64 -5
- data/test/holidays/definition/context/test_merger.rb +5 -2
- data/test/holidays/definition/decorator/test_custom_method_proc.rb +113 -0
- data/test/holidays/definition/decorator/test_custom_method_source.rb +96 -0
- data/test/holidays/definition/parser/test_custom_method.rb +79 -0
- data/test/holidays/definition/repository/test_custom_methods.rb +43 -0
- data/test/holidays/definition/repository/test_holidays_by_month.rb +0 -32
- data/test/holidays/definition/repository/test_proc_result_cache.rb +84 -0
- data/test/holidays/definition/validator/test_custom_method.rb +89 -0
- data/test/holidays/option/context/test_parse_options.rb +5 -0
- data/test/holidays/test_definition_factory.rb +17 -2
- data/test/holidays/use_case/context/test_between.rb +2 -0
- data/test/test_all_regions.rb +7 -49
- data/test/test_custom_holidays.rb +8 -2
- data/test/test_helper.rb +9 -2
- data/test/test_holidays.rb +9 -29
- metadata +46 -11
- data/lib/generated_definitions/fed_ex.rb +0 -41
- data/test/holidays/definition/repository/test_proc_cache.rb +0 -29
- data/test/test_parse_definitions.rb +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a3ae038d2ecc81231efdb1dfb62b8aa5f8a9a08b
|
4
|
+
data.tar.gz: 0ee05da812d8db5409bad033938d44d127c5a9a7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d89718606e9235afedb475611e069cc5cfeae83951f28881418df6299287cd947bff46df32ee6fbec68eb3794f42622c90ca8d69b4fc764bc9a0464542a1e36f
|
7
|
+
data.tar.gz: 1005849766e633f5fad96e4cdc37f8d5ab021c63b5a50c921bd066239eedd69d07d22f0b83474af958fc32db75cfee83ff7216f6d8a146b4788466e05702fc1b
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,49 @@
|
|
1
1
|
# Ruby Holidays Gem CHANGELOG
|
2
2
|
|
3
|
+
## 4.0.0
|
4
|
+
|
5
|
+
Major refactor with breaking changes! Sorry for the wall of text but there is a lot of info here.
|
6
|
+
|
7
|
+
* Fixes issue 144 (loading custom defs with methods). This was the refactor catalyst. Changes highlights include:
|
8
|
+
- Allow for custom methods added via the `load_custom` method to be used immediately as expected
|
9
|
+
- Consolidate and clarify custom method parsing and validation
|
10
|
+
- Change nearly every definition to use new 'custom method' YAML format. See `definitions/README.md` for more info.
|
11
|
+
- Remove `require` functionality when loading new definitions, instead using in-memory repositories. See below for info.
|
12
|
+
- Now loads all generated definitions when `require 'holidays'` is called. See below for performance info.
|
13
|
+
* Add `rake console` command for easier local testing
|
14
|
+
* Remove or rename many public methods that were never intended for public use:
|
15
|
+
- Remove following date calculation helper methods (definitions must now directly call factory):
|
16
|
+
- `easter`
|
17
|
+
- `orthodox_easter`
|
18
|
+
- `orthodox_easter_julian`
|
19
|
+
- `to_monday_if_sunday`
|
20
|
+
- `to_monday_if_weekend`
|
21
|
+
- `to_weekday_if_boxing_weekend`
|
22
|
+
- `to_weekday_if_boxing_weekend_from_year`
|
23
|
+
- `to_weekday_if_weekend`
|
24
|
+
- `calculate_day_of_month`
|
25
|
+
- Remove `available` method. This was only intended for internal use
|
26
|
+
- Remove `parse_definition_files_and_return_source`. This was only intended for internal use
|
27
|
+
- Remove `load_all` method. This was only intended for internal use
|
28
|
+
- Rename `regions` to `available_regions` for clarity
|
29
|
+
- Rename `full_week?` to `any_holidays_during_work_week?` for clarity
|
30
|
+
* Following methods now constitute the 'public API' of this gem:
|
31
|
+
- `on`
|
32
|
+
- `any_holidays_during_work_week?` (renamed method, was originally `full_week?`, same behavior as before)
|
33
|
+
- `between`
|
34
|
+
- `cache_between`
|
35
|
+
- `available_regions` (renamed method, was originally `regions`, same behavior as before)
|
36
|
+
- `load_custom`
|
37
|
+
* All generated definitions are now loaded when `require 'holidays'` is called
|
38
|
+
- Previously files were required 'on the fly' when a specific region was specified. By requiring all definitions upon
|
39
|
+
startup we greatly simplify the handling of regions, definitions, and custom methods internally
|
40
|
+
- This results in a performance hit when calling `require 'holidays'`. Here is an example based on my benchmarking:
|
41
|
+
- old: `0.045537`
|
42
|
+
- new: `0.145125`
|
43
|
+
|
44
|
+
I decided that this performance hit on startup is acceptable. All other performance should remain the same. If performance is
|
45
|
+
a major concern please open an issue so we can discuss your use case.
|
46
|
+
|
3
47
|
## 3.3.0
|
4
48
|
|
5
49
|
This is the final minor point release in v3.X.X. I am releasing it so that all of the latest definitions can be
|
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# How to contribute
|
2
|
+
|
3
|
+
There are multiple ways to help! We rely on users around the world to help keep our definitions accurate and up to date. In addition, pull requests to address bugs or implement new features are always welcome.
|
4
|
+
|
5
|
+
## For definition updates
|
6
|
+
|
7
|
+
Our definitions are written in YAML. You can find a complete guide to our format in the [definitions README](definitions/README.md). We take the YAML definitions and generate final ruby classes that are loaded at runtime for fast calculations.
|
8
|
+
|
9
|
+
Here are the steps to take once you have a good idea on what you want to change:
|
10
|
+
|
11
|
+
* Fork the repository
|
12
|
+
* Edit desired definition YAML file(s) located under `definitions/`. If you are adding a new region be sure to update `definitions/index.yaml` as well
|
13
|
+
* Run `bundle exec rake generate` to generate updated final definitions (they will be located under `lib/generated_definitions/` and `test/defs/`)
|
14
|
+
* Run `bundle exec rake test` to ensure your changes did not introduce errors
|
15
|
+
* Open a PR with *all* of these changes. You *MUST* include the generated definition files and tests in your PR. There is no automatic process to generate definitions at this time
|
16
|
+
|
17
|
+
Including documentation with your updates is very much appreciated. A simple Wikipedia entry or government link in the comments alongside your changes would be perfect.
|
18
|
+
|
19
|
+
Lastly, note that there are many 'meta' regions. For example, there are regions for Europe, Scandinavia, and North America. If your new region(s) falls into these areas consider adding them. You can find these 'meta' regions in `definitions/index.yaml`.
|
20
|
+
|
21
|
+
## For non-definition functionality
|
22
|
+
|
23
|
+
* Fork the repository
|
24
|
+
* Make your changes
|
25
|
+
* Create a PR pointing back to `master`
|
26
|
+
|
27
|
+
Don't worry about versioning, we'll handle it on our end.
|
28
|
+
|
29
|
+
*Tests are required*. If your PR results in lower test coverage then it will not be accepted.
|
30
|
+
|
31
|
+
## Local development helpers
|
32
|
+
|
33
|
+
We have included a few handy tasks to help you troubleshoot and test:
|
34
|
+
|
35
|
+
* `rake test` - runs the entire suite
|
36
|
+
* `rake test_region <region>` - runs the tests for just that region. Make sure to run `rake generate` after updating your YAML before running this!
|
37
|
+
* `rake console` - launches an IRB session with the 'holidays' gem loaded for quick testing
|
data/README.md
CHANGED
@@ -14,7 +14,9 @@ To install the gem from RubyGems:
|
|
14
14
|
|
15
15
|
The Holidays gem is tested on Ruby 2.0.0, 2.1.0, 2.2.0, 2.3.0 and JRuby.
|
16
16
|
|
17
|
-
|
17
|
+
This gem follows [semantic versioning](http://semver.org/). The only methods covered by this guarantee are under the
|
18
|
+
`Holidays` namespace specifically. Anything that is not a method off of `Holidays` or the core extension is not covered by
|
19
|
+
semver. Please take this into account when relying on this gem as a dependency.
|
18
20
|
|
19
21
|
## Time zones
|
20
22
|
|
@@ -53,6 +55,16 @@ Get informal holidays in February.
|
|
53
55
|
Holidays.between(from, to, :informal)
|
54
56
|
=> [{:name => 'Valentine\'s Day',...}]
|
55
57
|
|
58
|
+
Return all available regions:
|
59
|
+
|
60
|
+
Holidays.available_regions
|
61
|
+
=> [:ar, :at, ..., :sg] # this will be a big array
|
62
|
+
|
63
|
+
To check if there are any holidays taking place during a specified work week:
|
64
|
+
|
65
|
+
Holidays.any_holidays_during_work_week?(Date.civil(2016, 1, 1))
|
66
|
+
=> true
|
67
|
+
|
56
68
|
### Loading Custom Definitions on the fly
|
57
69
|
|
58
70
|
Load custom definitions file on the fly and use them immediately.
|
@@ -112,32 +124,11 @@ If you are checking holidays regularly you can cache your results for improved p
|
|
112
124
|
|
113
125
|
Holidays.cache_between(Time.now, 2.years.from_now, :ca, :us, :observed)
|
114
126
|
|
115
|
-
Holidays for the regions specified within the dates specified will be pre-calculated.
|
116
|
-
|
117
|
-
See the [original pull request](https://github.com/alexdunae/holidays/pull/36) for more details.
|
127
|
+
Holidays for the regions specified within the dates specified will be pre-calculated and stored in-memory. Future lookups will be much faster.
|
118
128
|
|
119
129
|
### How to contribute
|
120
130
|
|
121
|
-
|
122
|
-
|
123
|
-
* Edit desired definition YAML file(s) located under `definitions/`. If you are adding a new region be sure to update `definitions/index.yaml` as well
|
124
|
-
* Run `bundle exec rake generate` to generate updated final definitions (they will be located under `lib/generated_definitions/`)
|
125
|
-
* Run `bundle exec rake test` to ensure your changes did not introduce errors
|
126
|
-
* Open a PR with *all* of these changes. You *MUST* include the generated definition files in your PR. There is no automatic process to generated definitions at this time
|
127
|
-
|
128
|
-
Including documentation with your updates is very much appreciated. A simple Wikipedia entry or government link in the comments alongside your changes would be perfect.
|
129
|
-
|
130
|
-
Lastly, note that there are many 'meta' regions. For example, there are regions for Europe, Scandinavia, and North America. If your new region(s) falls into these areas consider adding them. You can find these 'meta' regions in `definitions/index.yaml`.
|
131
|
-
|
132
|
-
#### For non-definition functionality
|
133
|
-
|
134
|
-
* Fork the repository
|
135
|
-
* Make your changes
|
136
|
-
* Create a PR pointing back to `master`
|
137
|
-
|
138
|
-
Don't worry about versioning, we'll handle it on our end.
|
139
|
-
|
140
|
-
Tests are required. If your PR results in lower test coverage then it will not be accepted.
|
131
|
+
See our [contribution guidelines](CONTRIBUTING.md) for information on how to help out!
|
141
132
|
|
142
133
|
### Credits and code
|
143
134
|
|
@@ -145,4 +136,4 @@ Tests are required. If your PR results in lower test coverage then it will not b
|
|
145
136
|
* Maintained by [Hana Wang](https://github.com/hahahana), 2013
|
146
137
|
* Maintained by [Phil Trimble](https://github.com/ptrimble), 2014-present
|
147
138
|
|
148
|
-
Plus all of these [wonderful contributors!](https://github.com/
|
139
|
+
Plus all of these [wonderful contributors!](https://github.com/holidays/holidays/contributors)
|
data/REFERENCES
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
=== References
|
2
2
|
|
3
|
-
|
3
|
+
We are eternally grateful to the following sources.
|
4
4
|
|
5
5
|
==== Date calculations
|
6
6
|
* http://michaelthompson.org/technikos/holidays.php
|
@@ -8,9 +8,12 @@ I am grateful to the following sources.
|
|
8
8
|
==== Easter calculations
|
9
9
|
* http://www.assa.org.au/edm.html
|
10
10
|
* http://www.smart.net/~mmontes/ec-cal.html
|
11
|
+
* https://github.com/Loyolny/when_easter - graciously allowed by Michał Nierebiński
|
11
12
|
|
12
13
|
==== World dates
|
13
14
|
* http://www.un.org/geninfo/faq/factsheets/FS18.HTM
|
14
15
|
* http://en.wikipedia.org/wiki/List_of_holidays_by_country
|
15
16
|
|
17
|
+
Other sources for specific regions are noted in the definitions files themselves.
|
16
18
|
|
19
|
+
If a commit sneaks past the maintainers without attribution then please, let us know immediately! It was entirely unintentional.
|
data/Rakefile
CHANGED
@@ -7,6 +7,9 @@ require 'yaml'
|
|
7
7
|
require 'fileutils'
|
8
8
|
require 'holidays'
|
9
9
|
|
10
|
+
DEFINITION_PATH = 'definitions'
|
11
|
+
DEFINITION_TESTS_PATH = 'test/defs'
|
12
|
+
|
10
13
|
Rake::TestTask.new(:test) do |t|
|
11
14
|
t.libs << 'test'
|
12
15
|
t.test_files = FileList['test/**/test_*.rb']
|
@@ -14,30 +17,57 @@ end
|
|
14
17
|
|
15
18
|
task :default => :test
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
+
desc "Run tests for only a single region. Do not provide sub regions. Example (without quotes): 'rake test_region jp'"
|
21
|
+
task :test_region do
|
22
|
+
# Magic to define empty tasks on the fly so we have nicer arguments, see http://cobwwweb.com/4-ways-to-pass-arguments-to-a-rake-task
|
23
|
+
ARGV.each { |a| task a.to_sym do ; end }
|
24
|
+
|
25
|
+
if ARGV[1].nil? || ARGV[1].empty?
|
26
|
+
raise ArgumentError.new("You must provide a region. Example (without quotes): 'rake test_region us'")
|
27
|
+
end
|
20
28
|
|
29
|
+
region = ARGV[1].downcase
|
30
|
+
|
31
|
+
unless Holidays.available_regions.include?(region.to_sym)
|
32
|
+
raise ArgumentError.new("Region '#{region}' not recognized")
|
33
|
+
end
|
34
|
+
|
35
|
+
unless File.file?("#{DEFINITION_TESTS_PATH}/test_defs_#{region}.rb")
|
36
|
+
raise ArgumentError.new("Test file not found for region '#{region}'. Do not use sub regions, try the overall region instead. Example: 'us' instead of 'us_dc'")
|
37
|
+
end
|
38
|
+
|
39
|
+
sh "bundle exec ruby #{DEFINITION_TESTS_PATH}/test_defs_#{region}.rb"
|
40
|
+
end
|
41
|
+
|
42
|
+
desc 'Launch IRB session'
|
43
|
+
task :console do
|
44
|
+
sh "irb -rubygems -I lib -r holidays.rb"
|
45
|
+
end
|
46
|
+
|
47
|
+
desc 'Generate definitions and tests used in main holiday logic based on raw YAML definitions'
|
48
|
+
namespace :generate do
|
21
49
|
desc 'Generate the holiday definition files'
|
22
50
|
task :definitions do
|
23
51
|
# load the index
|
24
|
-
def_index = YAML.load_file("#{
|
52
|
+
def_index = YAML.load_file("#{DEFINITION_PATH}/index.yaml")
|
25
53
|
|
26
54
|
# create a dir for the generated tests
|
27
|
-
FileUtils.mkdir_p(
|
55
|
+
FileUtils.mkdir_p(DEFINITION_TESTS_PATH)
|
28
56
|
|
29
57
|
all_regions = []
|
30
58
|
|
31
59
|
def_index['defs'].each do |region, files|
|
32
60
|
puts "Building #{region} definition module:"
|
33
|
-
files = files.collect { |f| "#{
|
61
|
+
files = files.collect { |f| "#{DEFINITION_PATH}/#{f}" }.uniq
|
62
|
+
|
63
|
+
regions, rules_by_month, custom_methods, tests = Holidays::DefinitionFactory.file_parser.parse_definition_files(files)
|
64
|
+
module_src, test_src = Holidays::DefinitionFactory.source_generator.generate_definition_source(region, files, regions, rules_by_month, custom_methods, tests)
|
34
65
|
|
35
|
-
module_src, test_src, regions = Holidays.parse_definition_files_and_return_source(region, files)
|
36
66
|
File.open("lib/#{Holidays::DEFINITIONS_PATH}/#{region.downcase.to_s}.rb","w") do |file|
|
37
67
|
file.puts module_src
|
38
68
|
end
|
39
69
|
unless test_src.empty?
|
40
|
-
File.open("#{
|
70
|
+
File.open("#{DEFINITION_TESTS_PATH}/test_defs_#{region.downcase.to_s}.rb","w") do |file|
|
41
71
|
file.puts test_src
|
42
72
|
end
|
43
73
|
end
|
data/benchmark.rb
ADDED
data/definitions/README.md
CHANGED
@@ -51,7 +51,7 @@ The two required properties are:
|
|
51
51
|
|
52
52
|
For example, the following holiday is on the first of January and available in the `:ca`, `:us` and `:au` regions:
|
53
53
|
|
54
|
-
```
|
54
|
+
```yaml
|
55
55
|
1:
|
56
56
|
- name: New Year's Day
|
57
57
|
regions: [ca, us, au]
|
@@ -65,7 +65,7 @@ For example, the following holiday is on the first of January and available in t
|
|
65
65
|
|
66
66
|
For example, the following holiday is on the first Monday of September and available in the `:ca` region:
|
67
67
|
|
68
|
-
```
|
68
|
+
```yaml
|
69
69
|
9:
|
70
70
|
- name: Labour Day
|
71
71
|
regions: [ca]
|
@@ -73,6 +73,156 @@ For example, the following holiday is on the first Monday of September and avail
|
|
73
73
|
wday: 1
|
74
74
|
```
|
75
75
|
|
76
|
+
### 'Formal' vs 'Informal' types
|
77
|
+
|
78
|
+
As mentioned above you can specify two different types. By default a holiday is considered 'formal'. By adding a `type: informal` to a definition you will mark it as 'informal' and it will only show up if the user specifically asks for it.
|
79
|
+
|
80
|
+
Example:
|
81
|
+
|
82
|
+
```yaml
|
83
|
+
9:
|
84
|
+
- name: Some Holiday
|
85
|
+
regions: [fr]
|
86
|
+
mday: 1
|
87
|
+
type: informal
|
88
|
+
```
|
89
|
+
|
90
|
+
If a user submits:
|
91
|
+
|
92
|
+
```ruby
|
93
|
+
Holidays.on(Date.civil(2016, 9, 1), :fr)
|
94
|
+
```
|
95
|
+
|
96
|
+
then they will not see the holiday. However, if they submit:
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
Holidays.on(Date.civil(2016, 9, 1), :fr, :informal)
|
100
|
+
```
|
101
|
+
|
102
|
+
Then the holiday will be returned. This is especially useful for holidays like "Valentine's Day" in the USA, where it is commonly recognized as a holiday in society but not as a day that is celebrated by taking the day off.
|
103
|
+
|
104
|
+
### Year ranges
|
105
|
+
|
106
|
+
Certain holidays in various countries are only in effect during specific year ranges. For example, a new holiday might come into effect that is only valid after a speciic year (say, 2017).
|
107
|
+
|
108
|
+
To address this we have the ability to specify these 'year ranges' in the definition. The gem will then only return a match on a date that adheres to these rules.
|
109
|
+
|
110
|
+
There are a total of four selectors that can be specified. All must be specified in terms of 'years'.
|
111
|
+
|
112
|
+
#### `before`
|
113
|
+
|
114
|
+
The 'before' selector will only find a match if the supplied date takes place
|
115
|
+
before or equal to the holiday.
|
116
|
+
|
117
|
+
Example:
|
118
|
+
|
119
|
+
```yaml
|
120
|
+
7:
|
121
|
+
name: 振替休日
|
122
|
+
regions: [jp]
|
123
|
+
mday: 1
|
124
|
+
year_ranges:
|
125
|
+
- before: 2002
|
126
|
+
```
|
127
|
+
|
128
|
+
This will return successfully:
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
Holidays.on(Date.civil(2000, 7, 1), :jp)
|
132
|
+
```
|
133
|
+
|
134
|
+
This will not:
|
135
|
+
|
136
|
+
```ruby
|
137
|
+
Holidays.on(Date.civil(2016, 7, 1), :jp)
|
138
|
+
```
|
139
|
+
|
140
|
+
#### `after`
|
141
|
+
|
142
|
+
The 'after' selector will only find a match if the supplied date takes place
|
143
|
+
after or equal to the holiday.
|
144
|
+
|
145
|
+
Example:
|
146
|
+
|
147
|
+
```yaml
|
148
|
+
7:
|
149
|
+
name: 振替休日
|
150
|
+
regions: [jp]
|
151
|
+
mday: 1
|
152
|
+
year_ranges:
|
153
|
+
- after: 2002
|
154
|
+
```
|
155
|
+
|
156
|
+
This will return successfully:
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
Holidays.on(Date.civil(2016, 7, 1), :jp)
|
160
|
+
```
|
161
|
+
|
162
|
+
This will not:
|
163
|
+
|
164
|
+
```ruby
|
165
|
+
Holidays.on(Date.civil(2000, 7, 1), :jp)
|
166
|
+
```
|
167
|
+
|
168
|
+
#### `limited`
|
169
|
+
|
170
|
+
The 'limited' selector will only find a match if the supplied date takes place during
|
171
|
+
one of the specified years. Multiple years can be specified.
|
172
|
+
|
173
|
+
An array of years *must* be supplied. Individual integers will result in an error.
|
174
|
+
|
175
|
+
Example:
|
176
|
+
|
177
|
+
```yaml
|
178
|
+
7:
|
179
|
+
name: 振替休日
|
180
|
+
regions: [jp]
|
181
|
+
mday: 1
|
182
|
+
year_ranges:
|
183
|
+
- limited: [2002]
|
184
|
+
```
|
185
|
+
|
186
|
+
This will return successfully:
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
Holidays.on(Date.civil(2002, 7, 1), :jp)
|
190
|
+
```
|
191
|
+
|
192
|
+
This will not:
|
193
|
+
|
194
|
+
```ruby
|
195
|
+
Holidays.on(Date.civil(2000, 7, 1), :jp)
|
196
|
+
```
|
197
|
+
|
198
|
+
#### `between`
|
199
|
+
|
200
|
+
The 'between' selector will only find a match if the supplied date takes place during the specified range of years. Only a single range is allowed at this time.
|
201
|
+
|
202
|
+
Example:
|
203
|
+
|
204
|
+
```yaml
|
205
|
+
7:
|
206
|
+
name: 振替休日
|
207
|
+
regions: [jp]
|
208
|
+
mday: 1
|
209
|
+
year_ranges:
|
210
|
+
- between: 1996..2002
|
211
|
+
```
|
212
|
+
|
213
|
+
This will return successfully:
|
214
|
+
|
215
|
+
```ruby
|
216
|
+
Holidays.on(Date.civil(2000, 7, 1), :jp)
|
217
|
+
```
|
218
|
+
|
219
|
+
This will not:
|
220
|
+
|
221
|
+
```ruby
|
222
|
+
Holidays.on(Date.civil(2003, 7, 1), :jp)
|
223
|
+
Holidays.on(Date.civil(1995, 7, 1), :jp)
|
224
|
+
```
|
225
|
+
|
76
226
|
## Methods
|
77
227
|
|
78
228
|
In addition to defining holidays by day or week, you can create custom methods to calculate a date. These should be placed under the `methods` property. Methods named in this way can then be referenced by entries in the `months` property.
|
@@ -81,16 +231,17 @@ For example, Canada celebrates Victoria Day, which falls on the Monday on or bef
|
|
81
231
|
|
82
232
|
```
|
83
233
|
methods:
|
84
|
-
ca_victoria_day:
|
85
|
-
|
86
|
-
|
234
|
+
ca_victoria_day:
|
235
|
+
arguments: year
|
236
|
+
source: |
|
237
|
+
date = Date.civil(year, 5, 24)
|
87
238
|
if date.wday > 1
|
88
239
|
date -= (date.wday - 1)
|
89
240
|
elsif date.wday == 0
|
90
241
|
date -= 6
|
91
242
|
end
|
243
|
+
|
92
244
|
date
|
93
|
-
end
|
94
245
|
```
|
95
246
|
|
96
247
|
This would be represented in `months` entry as:
|
@@ -108,7 +259,7 @@ If a holiday can occur in different months (e.g. Easter) it can go in the '0' mo
|
|
108
259
|
0:
|
109
260
|
- name: Easter Monday
|
110
261
|
regions: [ca]
|
111
|
-
function: easter(year)
|
262
|
+
function: easter(year)
|
112
263
|
```
|
113
264
|
|
114
265
|
There are pre-existing methods for highly-used calculations. They are:
|
@@ -127,10 +278,38 @@ There are pre-existing methods for highly-used calculations. They are:
|
|
127
278
|
0:
|
128
279
|
- name: Good Friday
|
129
280
|
regions: [us]
|
130
|
-
function: easter(year)
|
281
|
+
function: easter(year)
|
282
|
+
function_modifier: -2
|
131
283
|
type: informal
|
132
284
|
```
|
133
285
|
|
286
|
+
Use the `function_modifier` property, which can be positive or negative, to modify the result of the function.
|
287
|
+
|
288
|
+
In addition, you may only specify the following values for arguments into a custom method: `date`, `year`, `month`, `day`.
|
289
|
+
|
290
|
+
If attempt to specify anything else then you will receive an error on definition generation. This is because these are the only values that are available to
|
291
|
+
call into the custom methods will calculating the result of a function.
|
292
|
+
|
293
|
+
Correct example:
|
294
|
+
|
295
|
+
```
|
296
|
+
1:
|
297
|
+
- name: Custom Method
|
298
|
+
regions: [us]
|
299
|
+
function: custom_method(year, month, day)
|
300
|
+
```
|
301
|
+
|
302
|
+
If you do the following:
|
303
|
+
|
304
|
+
```
|
305
|
+
1:
|
306
|
+
- name: Custom Method
|
307
|
+
regions: [us]
|
308
|
+
function: custom_method(week)
|
309
|
+
```
|
310
|
+
|
311
|
+
This will result in an error since `week` is not a recognized method argument.
|
312
|
+
|
134
313
|
### Calculating observed dates
|
135
314
|
|
136
315
|
Users can specify that this gem only return holidays on their 'observed' day. This can be especially useful if they are using this gem for business-related logic. If you wish for your definitions to allow for this then you can add the `observed` property to your entry. This requires a method to help calculate the observed day.
|