fat_period 2.0.0 → 3.0.0
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/.envrc +0 -1
- data/.github/workflows/ruby.yml +54 -0
- data/.rubocop.yml +3 -0
- data/CHANGELOG.org +29 -0
- data/Gemfile +12 -11
- data/README.org +388 -19
- data/Rakefile +22 -5
- data/bin/console +1 -0
- data/fat_period.gemspec +4 -3
- data/lib/fat_period/date.rb +2 -0
- data/lib/fat_period/period.rb +81 -44
- data/lib/fat_period/version.rb +3 -1
- data/lib/fat_period.rb +6 -1
- metadata +22 -11
- data/.github/workflows/gem-push.yml +0 -48
- data/.travis.yml +0 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dadf65165f7640c1ed71d1b39446a330f810779a23acc6975986249b71918a8e
|
|
4
|
+
data.tar.gz: c118e93977b2133c99fbb53bcc64eea6dd7a98f30f05bfe64742f501d7d60753
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8cb63a7e83eb0035be2d3757a7969ff5c9ef244be16495e4aa0a1dcb2276e229d287a695ce8ec8cfdff21c891c076a2d29b6ccbffdb585f821fcfe578e8f3dde
|
|
7
|
+
data.tar.gz: 4d121f6f04a7780ded6ed2d6f7bb8de6c32e89ea2e96d97f14029f1800ce6ca4516dd6769887210ca5557816c978c39b270b289dee1f84d61737d6216e4ae4d5
|
data/.envrc
CHANGED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# This workflow uses actions that are not certified by GitHub.
|
|
2
|
+
# They are provided by a third-party and are governed by
|
|
3
|
+
# separate terms of service, privacy policy, and support
|
|
4
|
+
# documentation.
|
|
5
|
+
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
|
|
6
|
+
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
|
|
7
|
+
|
|
8
|
+
name: Ruby CI (setup-ruby)
|
|
9
|
+
|
|
10
|
+
on:
|
|
11
|
+
push:
|
|
12
|
+
pull_request:
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
test:
|
|
16
|
+
runs-on: ubuntu-24.04
|
|
17
|
+
strategy:
|
|
18
|
+
matrix:
|
|
19
|
+
ruby: [3.2.2, 3.3.0, 3.4.0]
|
|
20
|
+
steps:
|
|
21
|
+
- name: Check out code
|
|
22
|
+
uses: actions/checkout@v4
|
|
23
|
+
|
|
24
|
+
- name: Install build dependencies (needed if Ruby must be compiled)
|
|
25
|
+
run: |
|
|
26
|
+
sudo apt-get update
|
|
27
|
+
sudo apt-get install -y --no-install-recommends \
|
|
28
|
+
build-essential autoconf bison libssl-dev libreadline-dev \
|
|
29
|
+
zlib1g-dev libyaml-dev libffi-dev libgdbm-dev libncurses5-dev \
|
|
30
|
+
libgmp-dev pkg-config
|
|
31
|
+
|
|
32
|
+
- name: Set up Ruby
|
|
33
|
+
uses: ruby/setup-ruby@v1
|
|
34
|
+
with:
|
|
35
|
+
ruby-version: ${{ matrix.ruby }}
|
|
36
|
+
bundler-cache: true
|
|
37
|
+
|
|
38
|
+
- name: Verify Ruby
|
|
39
|
+
run: |
|
|
40
|
+
ruby -v
|
|
41
|
+
gem -v
|
|
42
|
+
shell: bash
|
|
43
|
+
|
|
44
|
+
- name: Install gems
|
|
45
|
+
run: |
|
|
46
|
+
gem install bundler --conservative
|
|
47
|
+
# optional: use vendor/bundle to keep gems within repo workspace
|
|
48
|
+
bundle config set --local path 'vendor/bundle' || true
|
|
49
|
+
bundle install --jobs 4 --retry 3
|
|
50
|
+
shell: bash
|
|
51
|
+
|
|
52
|
+
- name: Run tests
|
|
53
|
+
run: bundle exec rake
|
|
54
|
+
shell: bash
|
data/.rubocop.yml
ADDED
data/CHANGELOG.org
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
* Version 3.0.0
|
|
2
|
+
- Use the newly-spun-out fat_date library in place of fat_core/date, which no
|
|
3
|
+
longer exists starting with fat_core version 6.0.0.
|
|
4
|
+
- The fat_date library uses ~Date.spec~ instead of ~Date.parse_spec~, which is
|
|
5
|
+
just cleaner to type.
|
|
6
|
+
- The new ~fat_date~ libraries come with some notable enhancements to date
|
|
7
|
+
specs, including:
|
|
8
|
+
1. Skip modifiers, which allow the spec to "skip" from its usual target date
|
|
9
|
+
to the nearest day-of-week, either before or after the target date, and
|
|
10
|
+
either including or not including the target date as a candidate.
|
|
11
|
+
2. Changes the semimonth specifier from uppercase roman to A or B, so
|
|
12
|
+
2025-10-A (rather than 2025-I) is now the first semimonth for October,
|
|
13
|
+
2025, and 2025-10-B (rather than 2025-II) is now the second semimonth.
|
|
14
|
+
This allows week-of-month specs to be case insensitive, so 2025-10-i,
|
|
15
|
+
2025-10-ii, 2025-10-iii, 2025-10-iv, and 2025-10-v, can represent the
|
|
16
|
+
first through fifth week of October, 2025, as well as 2025-10-I,
|
|
17
|
+
2025-10-II, 2025-10-III, 2025-10-IV, and 2025-10-V.
|
|
18
|
+
3. In general, all the spec involving letters should now be case insensitive.
|
|
19
|
+
- Some other code cleanup with no impact on the API.
|
|
20
|
+
|
|
21
|
+
* Version 2.1.0
|
|
22
|
+
- When the first date is later than the second in ~Period.new~, raise
|
|
23
|
+
~ArgumentError~ exception instead of returning nil.
|
|
24
|
+
- Allow ~Period.parse_phrase~ to parse a 'per' clause and return an Array of
|
|
25
|
+
Periods that are sub-periods of the period given by the from- and
|
|
26
|
+
to-clauses.
|
|
27
|
+
- Add ~Period.ensure(arg)~ to try to return a ~Period~ from a string that can
|
|
28
|
+
be parsed as a ~Period~, an object that has a ~to_period~ method, or return
|
|
29
|
+
the ~arg~ if its already a ~Period~.
|
data/Gemfile
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
source 'https://rubygems.org'
|
|
2
4
|
|
|
3
5
|
# Specify your gem's dependencies in fat_period.gemspec
|
|
4
6
|
gemspec
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
gem '
|
|
8
|
-
gem '
|
|
9
|
-
gem 'pry
|
|
10
|
-
gem '
|
|
11
|
-
gem '
|
|
12
|
-
gem '
|
|
13
|
-
gem 'rubocop
|
|
14
|
-
gem 'rubocop-
|
|
15
|
-
|
|
16
|
-
gem 'rubocop-shopify'
|
|
8
|
+
group :development do
|
|
9
|
+
gem 'bundler'
|
|
10
|
+
gem 'debug'
|
|
11
|
+
gem 'pry'
|
|
12
|
+
gem 'pry-doc'
|
|
13
|
+
gem 'rake'
|
|
14
|
+
gem 'rspec'
|
|
15
|
+
gem 'rubocop', require: false
|
|
16
|
+
gem 'rubocop-ddoherty', git: 'https://github.com/ddoherty03/rubocop-ddoherty.git', branch: 'master', require: false
|
|
17
|
+
end
|
data/README.org
CHANGED
|
@@ -1,22 +1,103 @@
|
|
|
1
|
-
#+
|
|
1
|
+
#+TITLE: FatPeriod User Guide
|
|
2
|
+
#+OPTIONS: toc:5
|
|
3
|
+
#+PROPERTY: header-args:ruby :colnames no :session fat_period :hlines yes :exports both :wrap example :ruby "bundle exec irb --prompt=simple"
|
|
4
|
+
#+PROPERTY: header-args:sh :exports code
|
|
2
5
|
#+LATEX_HEADER: \usepackage[margin=0.75in]{geometry}
|
|
3
6
|
|
|
4
|
-
|
|
5
|
-
This is for markdown output:
|
|
7
|
+
[[https://github.com/ddoherty03/fat_period/actions/workflows/ruby.yml][https://github.com/ddoherty03/fat_period/actions/workflows/ruby.yml/badge.svg?branch=master]]
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
+
* Setup for Code Blocks :noexport:
|
|
10
|
+
Run this block before all others to ensure that we are reading the libraries
|
|
11
|
+
from the source directory.
|
|
9
12
|
|
|
10
|
-
|
|
13
|
+
#+begin_src ruby :results output :export no
|
|
14
|
+
Dir.chdir("/home/ded/src/fat_period")
|
|
15
|
+
puts "Current directory: #{Dir.pwd}"
|
|
16
|
+
puts "Ruby LOADPATH:"
|
|
17
|
+
$LOAD_PATH.unshift(File.expand_path("lib", Dir.pwd)) unless $:[0].match?(%r{src/fat_period/lib})
|
|
18
|
+
$:[0..10].each { |d| puts d }
|
|
19
|
+
puts "..."
|
|
20
|
+
require 'fat_period'
|
|
21
|
+
#+end_src
|
|
22
|
+
|
|
23
|
+
#+RESULTS:
|
|
24
|
+
#+begin_example
|
|
25
|
+
Current directory: /home/ded/src/fat_period
|
|
26
|
+
Ruby LOADPATH:
|
|
27
|
+
/home/ded/src/fat_period/lib
|
|
28
|
+
/home/ded/.rbenv/versions/3.4.1/lib/ruby/gems/3.4.0/gems/bundler-2.6.7/lib
|
|
29
|
+
/home/ded/.rbenv/rbenv.d/exec/gem-rehash
|
|
30
|
+
/home/ded/.rbenv/versions/3.4.1/lib/ruby/gems/3.4.0/bundler/gems/rubocop-ddoherty-6b28e9614f18/lib
|
|
31
|
+
/home/ded/.rbenv/versions/3.4.1/lib/ruby/gems/3.4.0/gems/rubocop-shopify-2.17.1/lib
|
|
32
|
+
/home/ded/.rbenv/versions/3.4.1/lib/ruby/gems/3.4.0/gems/rubocop-rspec-3.7.0/lib
|
|
33
|
+
/home/ded/.rbenv/versions/3.4.1/lib/ruby/gems/3.4.0/gems/rubocop-rake-0.7.1/lib
|
|
34
|
+
/home/ded/.rbenv/versions/3.4.1/lib/ruby/gems/3.4.0/gems/rubocop-performance-1.26.1/lib
|
|
35
|
+
/home/ded/.rbenv/versions/3.4.1/lib/ruby/gems/3.4.0/gems/rubocop-1.81.6/lib
|
|
36
|
+
/home/ded/.rbenv/versions/3.4.1/lib/ruby/gems/3.4.0/gems/unicode-display_width-3.2.0/lib
|
|
37
|
+
/home/ded/.rbenv/versions/3.4.1/lib/ruby/gems/3.4.0/gems/unicode-emoji-4.1.0/lib
|
|
38
|
+
...
|
|
39
|
+
#+end_example
|
|
40
|
+
|
|
41
|
+
* Version
|
|
42
|
+
#+begin_src ruby :wrap EXAMPLE
|
|
43
|
+
"Current version is: #{FatPeriod::VERSION}"
|
|
44
|
+
#+end_src
|
|
45
|
+
|
|
46
|
+
#+begin_EXAMPLE
|
|
47
|
+
Current version is: 3.0.0
|
|
48
|
+
#+end_EXAMPLE
|
|
11
49
|
|
|
12
50
|
* Introduction
|
|
13
51
|
|
|
14
|
-
~FatPeriod~ provides a Ruby ~Period~ class for dealing with time periods
|
|
15
|
-
is ranges whose endpoints are ~Date
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
52
|
+
~FatPeriod~ provides a Ruby ~Period~ class for dealing with time periods of
|
|
53
|
+
days, that is ranges whose endpoints are of class ~Date~. It's target is
|
|
54
|
+
financial applications, but it serves well for any application where periods
|
|
55
|
+
of time are useful. It builds on the [[https://github.com/ddoherty03/fat_date][fat_date]] gem, which provides
|
|
56
|
+
enhancements to the ~Date~ class, especially its class method ~Date.spec~ for
|
|
57
|
+
interpreting a rich set of "specs" as the beginning or end of a variety of
|
|
58
|
+
calendar-related periods.
|
|
59
|
+
|
|
60
|
+
In addition, set operations are provided for Period, as well as methods for
|
|
61
|
+
breaking a larger periods into an array of smaller periods of various 'chunk'
|
|
62
|
+
sizes that correspond to calendar-related periods such as days, weeks, months,
|
|
63
|
+
and so forth.
|
|
64
|
+
|
|
65
|
+
* Table of Contents :toc:noexport:
|
|
66
|
+
- [[#version][Version]]
|
|
67
|
+
- [[#introduction][Introduction]]
|
|
68
|
+
- [[#installation][Installation]]
|
|
69
|
+
- [[#installing-the-gem][Installing the gem]]
|
|
70
|
+
- [[#usage][Usage]]
|
|
71
|
+
- [[#constant-periodforever][Constant Period::FOREVER]]
|
|
72
|
+
- [[#construction-of-periods][Construction of Periods]]
|
|
73
|
+
- [[#periodnew][Period.new]]
|
|
74
|
+
- [[#periodparse][Period.parse]]
|
|
75
|
+
- [[#with-only-a-from-spec][With Only a From-Spec]]
|
|
76
|
+
- [[#with-both-a-from-spec-and-to-spec][With Both a From-Spec and To-Spec]]
|
|
77
|
+
- [[#using-skip-modifiers][Using Skip Modifiers]]
|
|
78
|
+
- [[#periodparse_phrase][Period.parse_phrase]]
|
|
79
|
+
- [[#periodensure][Period.ensure]]
|
|
80
|
+
- [[#conversion][Conversion]]
|
|
81
|
+
- [[#to-range][To Range]]
|
|
82
|
+
- [[#to-string][To String]]
|
|
83
|
+
- [[#tex-form][TeX Form]]
|
|
84
|
+
- [[#comparison][Comparison]]
|
|
85
|
+
- [[#enumeration][Enumeration]]
|
|
86
|
+
- [[#size][Size]]
|
|
87
|
+
- [[#chunking][Chunking]]
|
|
88
|
+
- [[#set-operations][Set Operations]]
|
|
89
|
+
- [[#subset-determination][Subset Determination]]
|
|
90
|
+
- [[#superset-determination][Superset Determination]]
|
|
91
|
+
- [[#intersection][Intersection]]
|
|
92
|
+
- [[#difference][Difference]]
|
|
93
|
+
- [[#union][Union]]
|
|
94
|
+
- [[#coverage][Coverage]]
|
|
95
|
+
- [[#contains][Contains?]]
|
|
96
|
+
- [[#overlapping][Overlapping]]
|
|
97
|
+
- [[#spanning][Spanning]]
|
|
98
|
+
- [[#gaps][Gaps]]
|
|
99
|
+
- [[#development][Development]]
|
|
100
|
+
- [[#contributing][Contributing]]
|
|
20
101
|
|
|
21
102
|
* Installation
|
|
22
103
|
|
|
@@ -41,9 +122,17 @@ Or install it yourself as:
|
|
|
41
122
|
#+END_SRC
|
|
42
123
|
|
|
43
124
|
* Usage
|
|
125
|
+
** Constant Period::FOREVER
|
|
44
126
|
|
|
45
|
-
|
|
127
|
+
The ~Period~ class depends on the extensions to ~Date~ made by the ~fat_core~
|
|
128
|
+
gem, which you can read about [[https://github.com/ddoherty03/fat_core][here]]. It defines a constant, ~Period::FOREVER~,
|
|
129
|
+
which is defined as extending from ~Date::BOT~ to ~Date::EOT~, which are
|
|
130
|
+
defined in ~fat_date~ as 1900-01-01 and 3000-12-31, respectively and define
|
|
131
|
+
the beginning of time and end of time for practical commercial purposes. The
|
|
132
|
+
constant is not frozen, so you can re-define it to your liking.
|
|
46
133
|
|
|
134
|
+
** Construction of Periods
|
|
135
|
+
*** Period.new
|
|
47
136
|
A Period is constructed with two arguments for the begin and end date. The
|
|
48
137
|
begin date must be on or before the end date. Each argument can be (1) a
|
|
49
138
|
Date, (2) a string parseable as a Date by the Date.parse method, or (3) an
|
|
@@ -53,15 +142,295 @@ object that responds to ~#to_s~ and can be parsed as a Date by Date.parse:
|
|
|
53
142
|
p1 = Period.new(Date.today, Date.today + 30)
|
|
54
143
|
p2 = Period.new('Nov 22, 1963', Date.today)
|
|
55
144
|
p3 = Period.new('1961-01-21', '1963-11-22')
|
|
56
|
-
|
|
145
|
+
[[p1.to_s], [p2.to_s], [p3.to_s]]
|
|
57
146
|
#+end_SRC
|
|
58
147
|
|
|
59
|
-
|
|
148
|
+
#+RESULTS:
|
|
149
|
+
| 2025-03-20 to 2025-04-19 |
|
|
150
|
+
| 1963-11-22 to 2025-03-20 |
|
|
151
|
+
| 1961-01-21 to 1963-11-22 |
|
|
60
152
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
153
|
+
#+begin_src ruby
|
|
154
|
+
["Camelot lasted #{p3.length} days"]
|
|
155
|
+
#+end_src
|
|
156
|
+
|
|
157
|
+
#+RESULTS:
|
|
158
|
+
| Camelot lasted 1036 days |
|
|
159
|
+
|
|
160
|
+
*** Period.parse
|
|
161
|
+
A more convenient way to construct a period is provided by ~Period.parse~. It
|
|
162
|
+
takes two strings as its arguments, a mandatory "from-spec" and an optional
|
|
163
|
+
"to-spec":
|
|
164
|
+
|
|
165
|
+
A "spec" is a string designating some period of time. There are many ways of
|
|
166
|
+
specifying a period, which are detailed below.
|
|
167
|
+
|
|
168
|
+
**** With Only a From-Spec
|
|
169
|
+
|
|
170
|
+
If only a from-spec is given, it defines both the beginning and end of the
|
|
171
|
+
overall period:
|
|
172
|
+
|
|
173
|
+
#+begin_src ruby
|
|
174
|
+
tab = []
|
|
175
|
+
tab << ['From Spec', 'Result']
|
|
176
|
+
tab << nil
|
|
177
|
+
froms = ['2020', '2020-2Q', '2020-W15', '2020-09', '2020-09-A', '2020-09-iii']
|
|
178
|
+
froms.each do |f|
|
|
179
|
+
tab << [f, Period.parse(f).inspect]
|
|
180
|
+
end
|
|
181
|
+
tab
|
|
182
|
+
#+end_src
|
|
183
|
+
|
|
184
|
+
#+begin_example
|
|
185
|
+
| From Spec | Result |
|
|
186
|
+
|-------------+--------------------------------|
|
|
187
|
+
| 2020 | Period(2020-01-01..2020-12-31) |
|
|
188
|
+
| 2020-2Q | Period(2020-04-01..2020-06-30) |
|
|
189
|
+
| 2020-W15 | Period(2020-04-06..2020-04-12) |
|
|
190
|
+
| 2020-09 | Period(2020-09-01..2020-09-30) |
|
|
191
|
+
| 2020-09-A | Period(2020-09-01..2020-09-15) |
|
|
192
|
+
| 2020-09-iii | Period(2020-09-14..2020-09-20) |
|
|
193
|
+
#+end_example
|
|
194
|
+
|
|
195
|
+
**** With Both a From-Spec and To-Spec
|
|
196
|
+
But, if a to-spec is also given, the from-spec defines the beginning of the
|
|
197
|
+
period and the to-spec defines the end of the period. In particular, the
|
|
198
|
+
beginning of the period is the first day of the from-spec and the end of the
|
|
199
|
+
period is the last day of the to-spec:
|
|
200
|
+
|
|
201
|
+
#+begin_src ruby
|
|
202
|
+
tab = []
|
|
203
|
+
tab << ['From Spec', 'To Spec', 'Result']
|
|
204
|
+
tab << nil
|
|
205
|
+
from_tos = [['2020', '2020-2Q'], ['2020-2Q', '2020-W15'], ['2020-W15', '2020-09'], ['2020-09', '2020-09-A'], ['2020-09-A', '2020-09-iii']]
|
|
206
|
+
from_tos.each do |f, t|
|
|
207
|
+
tab << [f, t, Period.parse(f, t).inspect]
|
|
208
|
+
end
|
|
209
|
+
tab
|
|
210
|
+
#+end_src
|
|
211
|
+
|
|
212
|
+
#+begin_example
|
|
213
|
+
| From Spec | To Spec | Result |
|
|
214
|
+
|-----------+-------------+--------------------------------|
|
|
215
|
+
| 2020 | 2020-2Q | Period(2020-01-01..2020-06-30) |
|
|
216
|
+
| 2020-2Q | 2020-W15 | Period(2020-04-01..2020-04-12) |
|
|
217
|
+
| 2020-W15 | 2020-09 | Period(2020-04-06..2020-09-30) |
|
|
218
|
+
| 2020-09 | 2020-09-A | Period(2020-09-01..2020-09-15) |
|
|
219
|
+
| 2020-09-A | 2020-09-iii | Period(2020-09-01..2020-09-20) |
|
|
220
|
+
#+end_example
|
|
221
|
+
|
|
222
|
+
**** Using Skip Modifiers
|
|
223
|
+
One new feature of FatDate is the ability to add a "skip modifier" to the end
|
|
224
|
+
of a date spec to skip forward or backward to the first day-of-week either on
|
|
225
|
+
or before/after the date given by the spec. For example, the following
|
|
226
|
+
demonstrates that one can set the 'to' spec to the /last/ Wednesday of 2025 or
|
|
227
|
+
the last Wednesday /before/ the end of 2025. Using '>' or '>=' specified
|
|
228
|
+
skipping forward instead.
|
|
229
|
+
|
|
230
|
+
#+begin_src ruby
|
|
231
|
+
tab = []
|
|
232
|
+
tab << ['From Spec', 'To Spec', 'Result', 'Description']
|
|
233
|
+
tab << nil
|
|
234
|
+
from_to_descs = [['2025-2Q', '2025<=Wed', 'From 2q to last Wednesday of 2025'],
|
|
235
|
+
['2025-2Q', '2025<Wed', 'From 2q to last Wednesday /before/ the end of 2025'],
|
|
236
|
+
['2012-11', '2012-11<=Thur', 'November 2012 through last Thursday'],
|
|
237
|
+
['2012-11', '2012-11-4Thur', 'And through Thanksgiving (not always the /last/ Thursday!)']
|
|
238
|
+
]
|
|
239
|
+
from_to_descs.each do |f, t, d|
|
|
240
|
+
tab << [f, t, Period.parse(f, t).inspect, d]
|
|
241
|
+
end
|
|
242
|
+
tab
|
|
243
|
+
#+end_src
|
|
244
|
+
|
|
245
|
+
#+begin_example
|
|
246
|
+
| From Spec | To Spec | Result | Description |
|
|
247
|
+
|-----------+---------------+--------------------------------+------------------------------------------------------------|
|
|
248
|
+
| 2025-2Q | 2025<=Wed | Period(2025-04-01..2025-12-31) | From 2q to last Wednesday of 2025 |
|
|
249
|
+
| 2025-2Q | 2025<Wed | Period(2025-04-01..2025-12-31) | From 2q to last Wednesday /before/ the end of 2025 |
|
|
250
|
+
| 2012-11 | 2012-11<=Thur | Period(2012-11-01..2012-11-29) | November 2012 through last Thursday |
|
|
251
|
+
| 2012-11 | 2012-11-4Thur | Period(2012-11-01..2012-11-22) | And through Thanksgiving (not always the /last/ Thursday!) |
|
|
252
|
+
#+end_example
|
|
253
|
+
|
|
254
|
+
*** Period.parse_phrase
|
|
255
|
+
For example:
|
|
256
|
+
|
|
257
|
+
The ~Period.parse_phrase~ method will take a string having a 'from', 'to', and
|
|
258
|
+
'per' clause and return an Array of Periods encompassing the same period as
|
|
259
|
+
~Period.parse~, but optionally broken into sub-periods each having the length
|
|
260
|
+
specified by the 'per' clause. ~Period.parse_phrase~ always returns an Array
|
|
261
|
+
of Periods even if there is no 'per' clause and the Array has only one
|
|
262
|
+
member. If there is no 'to' clause, the returned period is from the start of
|
|
263
|
+
the 'from' period to its end. If there is neither a 'from' or a 'to' clause,
|
|
264
|
+
it tries to interpret the beginning of the phrase as a valid spec and uses it
|
|
265
|
+
as a 'from' clause.
|
|
266
|
+
|
|
267
|
+
#+begin_src ruby
|
|
268
|
+
tab = []
|
|
269
|
+
tab << ['k', 'Sub Period']
|
|
270
|
+
tab << nil
|
|
271
|
+
pds = Period.parse_phrase('from 2025 to 2025-3Q per month')
|
|
272
|
+
pds.each_with_index do |pd, k|
|
|
273
|
+
tab << [k, pd.inspect]
|
|
274
|
+
end
|
|
275
|
+
tab
|
|
276
|
+
#+end_src
|
|
277
|
+
|
|
278
|
+
#+begin_example
|
|
279
|
+
| k | Sub Period |
|
|
280
|
+
|---+--------------------------------|
|
|
281
|
+
| 0 | Period(2025-01-01..2025-01-31) |
|
|
282
|
+
| 1 | Period(2025-02-01..2025-02-28) |
|
|
283
|
+
| 2 | Period(2025-03-01..2025-03-31) |
|
|
284
|
+
| 3 | Period(2025-04-01..2025-04-30) |
|
|
285
|
+
| 4 | Period(2025-05-01..2025-05-31) |
|
|
286
|
+
| 5 | Period(2025-06-01..2025-06-30) |
|
|
287
|
+
| 6 | Period(2025-07-01..2025-07-31) |
|
|
288
|
+
| 7 | Period(2025-08-01..2025-08-31) |
|
|
289
|
+
| 8 | Period(2025-09-01..2025-09-30) |
|
|
290
|
+
#+end_example
|
|
291
|
+
|
|
292
|
+
The period named in the 'per' clause is called a 'chunk' and there are several
|
|
293
|
+
valid chunk names in ~FatPeriod~:
|
|
294
|
+
|
|
295
|
+
| Chunk Name |
|
|
296
|
+
|------------|
|
|
297
|
+
| year |
|
|
298
|
+
| half |
|
|
299
|
+
| quarter |
|
|
300
|
+
| bimonth |
|
|
301
|
+
| month |
|
|
302
|
+
| semimonth |
|
|
303
|
+
| biweek |
|
|
304
|
+
| week |
|
|
305
|
+
| day |
|
|
306
|
+
|
|
307
|
+
Here is the same period broken into weeks. Notice that the first and last
|
|
308
|
+
"weeks" are not whole weeks because parts of them fall outside the boundaries
|
|
309
|
+
of the overall period.
|
|
310
|
+
|
|
311
|
+
#+begin_src ruby
|
|
312
|
+
tab = []
|
|
313
|
+
tab << ['k', 'Sub Period']
|
|
314
|
+
tab << nil
|
|
315
|
+
pds = Period.parse_phrase('from 2025 to 2025-3Q per week')
|
|
316
|
+
pds.each_with_index do |pd, k|
|
|
317
|
+
tab << [k, pd.inspect]
|
|
318
|
+
end
|
|
319
|
+
tab
|
|
320
|
+
#+end_src
|
|
321
|
+
|
|
322
|
+
#+begin_example
|
|
323
|
+
| k | Sub Period |
|
|
324
|
+
|----+--------------------------------|
|
|
325
|
+
| 0 | Period(2025-01-01..2025-01-05) |
|
|
326
|
+
| 1 | Period(2025-01-06..2025-01-12) |
|
|
327
|
+
| 2 | Period(2025-01-13..2025-01-19) |
|
|
328
|
+
| 3 | Period(2025-01-20..2025-01-26) |
|
|
329
|
+
| 4 | Period(2025-01-27..2025-02-02) |
|
|
330
|
+
| 5 | Period(2025-02-03..2025-02-09) |
|
|
331
|
+
| 6 | Period(2025-02-10..2025-02-16) |
|
|
332
|
+
| 7 | Period(2025-02-17..2025-02-23) |
|
|
333
|
+
| 8 | Period(2025-02-24..2025-03-02) |
|
|
334
|
+
| 9 | Period(2025-03-03..2025-03-09) |
|
|
335
|
+
| 10 | Period(2025-03-10..2025-03-16) |
|
|
336
|
+
| 11 | Period(2025-03-17..2025-03-23) |
|
|
337
|
+
| 12 | Period(2025-03-24..2025-03-30) |
|
|
338
|
+
| 13 | Period(2025-03-31..2025-04-06) |
|
|
339
|
+
| 14 | Period(2025-04-07..2025-04-13) |
|
|
340
|
+
| 15 | Period(2025-04-14..2025-04-20) |
|
|
341
|
+
| 16 | Period(2025-04-21..2025-04-27) |
|
|
342
|
+
| 17 | Period(2025-04-28..2025-05-04) |
|
|
343
|
+
| 18 | Period(2025-05-05..2025-05-11) |
|
|
344
|
+
| 19 | Period(2025-05-12..2025-05-18) |
|
|
345
|
+
| 20 | Period(2025-05-19..2025-05-25) |
|
|
346
|
+
| 21 | Period(2025-05-26..2025-06-01) |
|
|
347
|
+
| 22 | Period(2025-06-02..2025-06-08) |
|
|
348
|
+
| 23 | Period(2025-06-09..2025-06-15) |
|
|
349
|
+
| 24 | Period(2025-06-16..2025-06-22) |
|
|
350
|
+
| 25 | Period(2025-06-23..2025-06-29) |
|
|
351
|
+
| 26 | Period(2025-06-30..2025-07-06) |
|
|
352
|
+
| 27 | Period(2025-07-07..2025-07-13) |
|
|
353
|
+
| 28 | Period(2025-07-14..2025-07-20) |
|
|
354
|
+
| 29 | Period(2025-07-21..2025-07-27) |
|
|
355
|
+
| 30 | Period(2025-07-28..2025-08-03) |
|
|
356
|
+
| 31 | Period(2025-08-04..2025-08-10) |
|
|
357
|
+
| 32 | Period(2025-08-11..2025-08-17) |
|
|
358
|
+
| 33 | Period(2025-08-18..2025-08-24) |
|
|
359
|
+
| 34 | Period(2025-08-25..2025-08-31) |
|
|
360
|
+
| 35 | Period(2025-09-01..2025-09-07) |
|
|
361
|
+
| 36 | Period(2025-09-08..2025-09-14) |
|
|
362
|
+
| 37 | Period(2025-09-15..2025-09-21) |
|
|
363
|
+
| 38 | Period(2025-09-22..2025-09-28) |
|
|
364
|
+
| 39 | Period(2025-09-29..2025-09-30) |
|
|
365
|
+
#+end_example
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
*** Period.ensure
|
|
369
|
+
~Period.ensure~ tries to interpret its argument as a ~Period~ and returns it;
|
|
370
|
+
otherwise it throws an ~ArgumentError~ exception:
|
|
371
|
+
|
|
372
|
+
- if the argument responds to the ~to_period~ method, it invokes that on the
|
|
373
|
+
argument and returns it;
|
|
374
|
+
- if the argument is a ~String~, it uses ~Period.parse_phrase~ to try to
|
|
375
|
+
interepret it as a ~Period~;
|
|
376
|
+
- if it is already a ~Period~, it just returns the argument;
|
|
377
|
+
- otherwise, it throws an ~ArgumentError~ exception.
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
#+begin_src ruby
|
|
381
|
+
class ContainingMonth
|
|
382
|
+
def initialize(dat)
|
|
383
|
+
@dat = Date.ensure(dat)
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
def to_period
|
|
387
|
+
Period.month_containing(@dat)
|
|
388
|
+
end
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
cm = ContainingMonth.new('2025-09-22')
|
|
392
|
+
Period.ensure(cm)
|
|
393
|
+
#+end_src
|
|
394
|
+
|
|
395
|
+
#+begin_example
|
|
396
|
+
Period(2025-09-01..2025-09-30)
|
|
397
|
+
#+end_example
|
|
398
|
+
|
|
399
|
+
#+begin_src ruby
|
|
400
|
+
Period.ensure('from 2016 to 2018-3Q')
|
|
401
|
+
#+end_src
|
|
402
|
+
|
|
403
|
+
#+begin_example
|
|
404
|
+
Period(2016-01-01..2018-09-30)
|
|
405
|
+
#+end_example
|
|
406
|
+
|
|
407
|
+
#+begin_src ruby
|
|
408
|
+
Period.ensure(Period.new('2016-01-02', '2017-09-29'))
|
|
409
|
+
#+end_src
|
|
410
|
+
|
|
411
|
+
#+begin_example
|
|
412
|
+
Period(2016-01-02..2017-09-29)
|
|
413
|
+
#+end_example
|
|
414
|
+
|
|
415
|
+
** Conversion
|
|
416
|
+
*** To Range
|
|
417
|
+
*** To String
|
|
418
|
+
*** TeX Form
|
|
419
|
+
** Comparison
|
|
420
|
+
** Enumeration
|
|
421
|
+
** Size
|
|
422
|
+
** Chunking
|
|
423
|
+
** Set Operations
|
|
424
|
+
*** Subset Determination
|
|
425
|
+
*** Superset Determination
|
|
426
|
+
*** Intersection
|
|
427
|
+
*** Difference
|
|
428
|
+
*** Union
|
|
429
|
+
** Coverage
|
|
430
|
+
*** Contains?
|
|
431
|
+
*** Overlapping
|
|
432
|
+
*** Spanning
|
|
433
|
+
*** Gaps
|
|
65
434
|
|
|
66
435
|
* Development
|
|
67
436
|
|
data/Rakefile
CHANGED
|
@@ -1,9 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
require "rspec/core/rake_task"
|
|
1
|
+
# frozen_string_literal: true
|
|
3
2
|
|
|
4
|
-
require '
|
|
3
|
+
require 'bundler/gem_tasks'
|
|
4
|
+
require 'rspec/core/rake_task'
|
|
5
5
|
|
|
6
|
-
RuboCop::RakeTask.new
|
|
7
6
|
RSpec::Core::RakeTask.new(:spec)
|
|
8
7
|
|
|
9
|
-
|
|
8
|
+
########################################################################
|
|
9
|
+
# Rubocop tasks
|
|
10
|
+
########################################################################
|
|
11
|
+
# Option A (recommended): Keep using Bundler and run rubocop via `bundle exec`.
|
|
12
|
+
# This wrapper task ensures the rubocop run uses the gems from your Gemfile,
|
|
13
|
+
# even when you invoke `rake rubocop` (no need to remember `bundle exec rake`).
|
|
14
|
+
#
|
|
15
|
+
# You can pass extra RuboCop CLI flags with the RUBOCOP_OPTS environment variable:
|
|
16
|
+
# RUBOCOP_OPTS="--format simple" rake rubocop
|
|
17
|
+
|
|
18
|
+
desc 'Run rubocop under `bundle exec`'
|
|
19
|
+
task :rubocop do
|
|
20
|
+
opts = (ENV['RUBOCOP_OPTS'] || '').split
|
|
21
|
+
Bundler.with_unbundled_env do
|
|
22
|
+
sh 'bundle', 'exec', 'rubocop', *opts
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
task default: %i[spec rubocop]
|
data/bin/console
CHANGED
data/fat_period.gemspec
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
lib = File.expand_path('
|
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
require 'fat_period/version'
|
|
6
6
|
|
|
@@ -21,5 +21,6 @@ Gem::Specification.new do |spec|
|
|
|
21
21
|
# spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
22
22
|
spec.require_paths = ['lib']
|
|
23
23
|
|
|
24
|
-
spec.add_dependency 'fat_core', '>=
|
|
24
|
+
spec.add_dependency 'fat_core', '>= 6.0'
|
|
25
|
+
spec.add_dependency 'fat_date'
|
|
25
26
|
end
|
data/lib/fat_period/date.rb
CHANGED
data/lib/fat_period/period.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'fat_date'
|
|
3
4
|
|
|
4
5
|
# The Period class represents a range of Dates and supports a variety of
|
|
5
6
|
# operations on those ranges.
|
|
@@ -30,9 +31,7 @@ class Period
|
|
|
30
31
|
@last = Date.ensure_date(last).freeze
|
|
31
32
|
freeze
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
raise ArgumentError, "Period's first date is later than its last date"
|
|
34
|
+
raise ArgumentError, "Period's first date is later than its last date" if @first > @last
|
|
36
35
|
end
|
|
37
36
|
|
|
38
37
|
# These need to come after initialize is defined
|
|
@@ -43,7 +42,7 @@ class Period
|
|
|
43
42
|
# @group Parsing
|
|
44
43
|
#
|
|
45
44
|
# Return a period based on two date specs passed as strings (see
|
|
46
|
-
# `FatCore::Date.
|
|
45
|
+
# `FatCore::Date.spec`), a 'from' and a 'to' spec. The returned period
|
|
47
46
|
# begins on the first day of the period given as the `from` spec and ends on
|
|
48
47
|
# the last day given as the `to` spec. If the to spec is not given or is nil,
|
|
49
48
|
# the from spec is used for both the from- and to-spec.
|
|
@@ -54,47 +53,86 @@ class Period
|
|
|
54
53
|
# # Assuming this executes in December, 2014
|
|
55
54
|
# Period.parse('last_month', 'this_month').inspect #=> Period('2014-11-01..2014-12-31')
|
|
56
55
|
#
|
|
57
|
-
# @param from [String] spec ala FatCore::Date.
|
|
58
|
-
# @param to [String] spec ala FatCore::Date.
|
|
56
|
+
# @param from [String] spec ala FatCore::Date.spec
|
|
57
|
+
# @param to [String] spec ala FatCore::Date.spec
|
|
59
58
|
# @return [Period] from beginning of `from` to end of `to`
|
|
60
59
|
def self.parse(from, to = nil)
|
|
61
60
|
raise ArgumentError, 'Period.parse missing argument' unless from
|
|
62
61
|
|
|
63
62
|
to ||= from
|
|
64
|
-
first = Date.
|
|
65
|
-
second = Date.
|
|
63
|
+
first = Date.spec(from, :from)
|
|
64
|
+
second = Date.spec(to, :to)
|
|
66
65
|
Period.new(first, second) if first && second
|
|
67
66
|
end
|
|
68
67
|
|
|
69
|
-
# Return a
|
|
70
|
-
#
|
|
71
|
-
# with 'to'. A phrase with only a to spec is treated the same as one with
|
|
72
|
-
# only a from spec. If neither 'from' nor 'to' appear in phrase, treat the
|
|
73
|
-
# whole string as a from spec.
|
|
68
|
+
# Return a Period either from a given String or other type that can
|
|
69
|
+
# reasonably converted to a Period.
|
|
74
70
|
#
|
|
75
71
|
# @example
|
|
76
|
-
# Period.
|
|
77
|
-
#
|
|
78
|
-
# Period.
|
|
79
|
-
#
|
|
80
|
-
#
|
|
72
|
+
# Period.ensure('2014-11').inspect #=> Period('2014-11-01..2014-11-30')
|
|
73
|
+
# pd = Period.parse('2011')
|
|
74
|
+
# Period.ensure(pd).inspect #=> Period('2011-01-01..2011-12-31')
|
|
75
|
+
#
|
|
76
|
+
# @param prd [String|Period] or any candidate for conversion to Period
|
|
77
|
+
# @return Period correspondign to prd parameter
|
|
78
|
+
def self.ensure(prd)
|
|
79
|
+
return prd.to_period if prd.respond_to?(:to_period)
|
|
80
|
+
|
|
81
|
+
case prd
|
|
82
|
+
when String
|
|
83
|
+
if prd.match?(/from|to/i)
|
|
84
|
+
Period.parse_phrase(prd).first
|
|
85
|
+
else
|
|
86
|
+
Period.parse(prd)
|
|
87
|
+
end
|
|
88
|
+
when Period
|
|
89
|
+
prd
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Return an Array of Periods from a String phrase in which the from spec is
|
|
94
|
+
# introduced with 'from' and, optionally, the to spec is introduced with
|
|
95
|
+
# 'to' and optionally a 'per' clause is introduced by 'per'. A phrase with
|
|
96
|
+
# only a to spec is treated the same as one with only a from spec. If
|
|
97
|
+
# neither 'from' nor 'to' appear in phrase, treat the string before any
|
|
98
|
+
# per-clause as a from spec.
|
|
81
99
|
#
|
|
82
|
-
# @
|
|
100
|
+
# @example
|
|
101
|
+
# Period.parse_phrase('from 2014-11 to 2015-3Q') #=> [Period('2014-11-01..2015-09-30')]
|
|
102
|
+
# Period.parse_phrase('from 2014-11') #=> [Period('2014-11-01..2014-11-30')]
|
|
103
|
+
# Period.parse_phrase('from 2015-3Q') #=> [Period('2015-09-01..2015-12-31')]
|
|
104
|
+
# Period.parse_phrase('to 2015-3Q') #=> [Period('2015-09-01..2015-12-31')]
|
|
105
|
+
# Period.parse_phrase('2015-3Q') #=> [Period('2015-09-01..2015-12-31')]
|
|
106
|
+
# Period.parse_phrase('to 2015-3Q per week') #=> [Period('2015-09-01..2015-09-04')...]
|
|
107
|
+
# Period.parse_phrase('2015-3Q per month') #=> [Period('2015-09-01..2015-09-30')...]
|
|
108
|
+
#
|
|
109
|
+
# @param phrase [String] with 'from <spec> [to <spec>] [per chunk]'
|
|
83
110
|
# @return [Period] translated from phrase
|
|
84
|
-
def self.parse_phrase(phrase)
|
|
111
|
+
def self.parse_phrase(phrase, partial_first: true, partial_last: true, round_up_last: false)
|
|
85
112
|
phrase = phrase.clean
|
|
86
113
|
case phrase
|
|
87
|
-
when /\Afrom
|
|
88
|
-
from_phrase =
|
|
89
|
-
to_phrase =
|
|
90
|
-
when /\Afrom
|
|
91
|
-
from_phrase =
|
|
114
|
+
when /\Afrom\s+([^\s]+)\s+to\s+([^\s]+)(\s+per\s+[^\s]+)?\z/i
|
|
115
|
+
from_phrase = ::Regexp.last_match(1)
|
|
116
|
+
to_phrase = ::Regexp.last_match(2)
|
|
117
|
+
when /\Afrom\s+([^\s]+)(\s+per\s+[^\s]+)?\z/, /\Ato\s+([^\s]+)(\s+per\s+[^\s]+)?\z/i
|
|
118
|
+
from_phrase = ::Regexp.last_match(1)
|
|
92
119
|
to_phrase = nil
|
|
93
|
-
|
|
94
|
-
from_phrase =
|
|
120
|
+
when /\A([^\s]+)(\s+per\s+[^\s]+)?\z/
|
|
121
|
+
from_phrase = ::Regexp.last_match(1)
|
|
95
122
|
to_phrase = nil
|
|
123
|
+
else
|
|
124
|
+
raise ArgumentError, "unintelligible period phrase: '#{phrase}''"
|
|
125
|
+
end
|
|
126
|
+
# Return an Array of periods divided by chunks if any.
|
|
127
|
+
whole_period = parse(from_phrase, to_phrase)
|
|
128
|
+
if phrase =~ /per\s+(?<chunk>[a-z_]+)/i
|
|
129
|
+
chunk_size = Regexp.last_match[:chunk].downcase.to_sym
|
|
130
|
+
raise ArgumentError, "invalid chunk size #{chunk_size}" unless CHUNKS.include?(chunk_size)
|
|
131
|
+
|
|
132
|
+
whole_period.chunks(size: chunk_size, partial_first:, partial_last:, round_up_last:)
|
|
133
|
+
else
|
|
134
|
+
[whole_period]
|
|
96
135
|
end
|
|
97
|
-
parse(from_phrase, to_phrase)
|
|
98
136
|
end
|
|
99
137
|
|
|
100
138
|
# @group Conversion
|
|
@@ -183,23 +221,11 @@ class Period
|
|
|
183
221
|
end
|
|
184
222
|
|
|
185
223
|
def eql?(other)
|
|
186
|
-
return unless other.is_a?(Period)
|
|
224
|
+
return false unless other.is_a?(Period)
|
|
187
225
|
|
|
188
226
|
hash == other.hash
|
|
189
227
|
end
|
|
190
228
|
|
|
191
|
-
# Return whether this Period contains the given date.
|
|
192
|
-
#
|
|
193
|
-
# @param date [Date] date to test
|
|
194
|
-
# @return [Boolean] is the given date within this Period?
|
|
195
|
-
def contains?(date)
|
|
196
|
-
date = date.to_date if date.respond_to?(:to_date)
|
|
197
|
-
raise ArgumentError, 'argument must be a Date' unless date.is_a?(Date)
|
|
198
|
-
|
|
199
|
-
to_range.cover?(date)
|
|
200
|
-
end
|
|
201
|
-
alias_method :===, :contains?
|
|
202
|
-
|
|
203
229
|
include Enumerable
|
|
204
230
|
|
|
205
231
|
# @group Enumeration
|
|
@@ -284,7 +310,6 @@ class Period
|
|
|
284
310
|
quarter
|
|
285
311
|
half
|
|
286
312
|
year
|
|
287
|
-
irregular
|
|
288
313
|
].freeze
|
|
289
314
|
|
|
290
315
|
CHUNK_ORDER = {}
|
|
@@ -784,6 +809,18 @@ class Period
|
|
|
784
809
|
to_range.overlaps?(other.to_range)
|
|
785
810
|
end
|
|
786
811
|
|
|
812
|
+
# Return whether this Period contains the given date.
|
|
813
|
+
#
|
|
814
|
+
# @param date [Date] date to test
|
|
815
|
+
# @return [Boolean] is the given date within this Period?
|
|
816
|
+
def contains?(date)
|
|
817
|
+
date = date.to_date if date.respond_to?(:to_date)
|
|
818
|
+
raise ArgumentError, 'argument must be a Date' unless date.is_a?(Date)
|
|
819
|
+
|
|
820
|
+
to_range.cover?(date)
|
|
821
|
+
end
|
|
822
|
+
alias_method :===, :contains?
|
|
823
|
+
|
|
787
824
|
# Return whether any of the given periods overlap any other.
|
|
788
825
|
#
|
|
789
826
|
# @example
|
data/lib/fat_period/version.rb
CHANGED
data/lib/fat_period.rb
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
require 'date'
|
|
2
4
|
|
|
5
|
+
require 'active_support'
|
|
6
|
+
|
|
3
7
|
require 'fat_period/version'
|
|
4
8
|
require 'fat_period/date'
|
|
5
9
|
require 'fat_period/period'
|
|
6
10
|
|
|
7
|
-
require 'fat_core/date'
|
|
8
11
|
require 'fat_core/range'
|
|
9
12
|
require 'fat_core/string'
|
|
13
|
+
|
|
14
|
+
require 'fat_date'
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fat_period
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 3.0.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Daniel E. Doherty
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 2025-10-28 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: fat_core
|
|
@@ -16,15 +15,28 @@ dependencies:
|
|
|
16
15
|
requirements:
|
|
17
16
|
- - ">="
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
18
|
+
version: '6.0'
|
|
20
19
|
type: :runtime
|
|
21
20
|
prerelease: false
|
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
22
|
requirements:
|
|
24
23
|
- - ">="
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
27
|
-
|
|
25
|
+
version: '6.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: fat_date
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
28
40
|
email:
|
|
29
41
|
- ded@ddoherty.net
|
|
30
42
|
executables: []
|
|
@@ -32,10 +44,11 @@ extensions: []
|
|
|
32
44
|
extra_rdoc_files: []
|
|
33
45
|
files:
|
|
34
46
|
- ".envrc"
|
|
35
|
-
- ".github/workflows/
|
|
47
|
+
- ".github/workflows/ruby.yml"
|
|
36
48
|
- ".gitignore"
|
|
37
49
|
- ".rspec"
|
|
38
|
-
- ".
|
|
50
|
+
- ".rubocop.yml"
|
|
51
|
+
- CHANGELOG.org
|
|
39
52
|
- Gemfile
|
|
40
53
|
- LICENSE.txt
|
|
41
54
|
- README.org
|
|
@@ -50,7 +63,6 @@ files:
|
|
|
50
63
|
homepage: https://github.com/ddoherty03/fat_period
|
|
51
64
|
licenses: []
|
|
52
65
|
metadata: {}
|
|
53
|
-
post_install_message:
|
|
54
66
|
rdoc_options: []
|
|
55
67
|
require_paths:
|
|
56
68
|
- lib
|
|
@@ -65,8 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
65
77
|
- !ruby/object:Gem::Version
|
|
66
78
|
version: '0'
|
|
67
79
|
requirements: []
|
|
68
|
-
rubygems_version: 3.
|
|
69
|
-
signing_key:
|
|
80
|
+
rubygems_version: 3.6.3
|
|
70
81
|
specification_version: 4
|
|
71
82
|
summary: Implements a Period class as a Range of Dates.
|
|
72
83
|
test_files: []
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
name: Ruby Gem
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [ "master" ]
|
|
6
|
-
pull_request:
|
|
7
|
-
branches: [ "master" ]
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
build:
|
|
11
|
-
name: Build + Publish
|
|
12
|
-
runs-on: ubuntu-latest
|
|
13
|
-
permissions:
|
|
14
|
-
contents: read
|
|
15
|
-
packages: write
|
|
16
|
-
|
|
17
|
-
steps:
|
|
18
|
-
- uses: actions/checkout@v4
|
|
19
|
-
- name: Set up Ruby 2.6
|
|
20
|
-
# To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
|
|
21
|
-
# change this to (see https://github.com/ruby/setup-ruby#versioning):
|
|
22
|
-
# uses: ruby/setup-ruby@v1
|
|
23
|
-
uses: ruby/setup-ruby@55283cc23133118229fd3f97f9336ee23a179fcf # v1.146.0
|
|
24
|
-
with:
|
|
25
|
-
ruby-version: 2.6.x
|
|
26
|
-
|
|
27
|
-
- name: Publish to GPR
|
|
28
|
-
run: |
|
|
29
|
-
mkdir -p $HOME/.gem
|
|
30
|
-
touch $HOME/.gem/credentials
|
|
31
|
-
chmod 0600 $HOME/.gem/credentials
|
|
32
|
-
printf -- "---\n:github: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
|
33
|
-
gem build *.gemspec
|
|
34
|
-
gem push --KEY github --host https://rubygems.pkg.github.com/${OWNER} *.gem
|
|
35
|
-
env:
|
|
36
|
-
GEM_HOST_API_KEY: "Bearer ${{secrets.GITHUB_TOKEN}}"
|
|
37
|
-
OWNER: ${{ github.repository_owner }}
|
|
38
|
-
|
|
39
|
-
- name: Publish to RubyGems
|
|
40
|
-
run: |
|
|
41
|
-
mkdir -p $HOME/.gem
|
|
42
|
-
touch $HOME/.gem/credentials
|
|
43
|
-
chmod 0600 $HOME/.gem/credentials
|
|
44
|
-
printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
|
|
45
|
-
gem build *.gemspec
|
|
46
|
-
gem push *.gem
|
|
47
|
-
env:
|
|
48
|
-
GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
|