timeboss 0.3.0 → 1.0.5

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.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/gem-push.yml +31 -0
  3. data/.github/workflows/ruby.yml +35 -0
  4. data/.travis.yml +3 -2
  5. data/Gemfile +2 -1
  6. data/README.md +17 -7
  7. data/Rakefile +3 -1
  8. data/bin/tbsh +2 -2
  9. data/lib/tasks/calendars.rake +5 -5
  10. data/lib/tasks/timeboss.rake +2 -2
  11. data/lib/timeboss.rb +1 -0
  12. data/lib/timeboss/calendar.rb +5 -4
  13. data/lib/timeboss/calendar/day.rb +3 -2
  14. data/lib/timeboss/calendar/half.rb +2 -1
  15. data/lib/timeboss/calendar/month.rb +2 -1
  16. data/lib/timeboss/calendar/parser.rb +9 -8
  17. data/lib/timeboss/calendar/period.rb +88 -12
  18. data/lib/timeboss/calendar/quarter.rb +2 -1
  19. data/lib/timeboss/calendar/support/formatter.rb +5 -4
  20. data/lib/timeboss/calendar/support/month_basis.rb +1 -1
  21. data/lib/timeboss/calendar/support/monthly_unit.rb +7 -6
  22. data/lib/timeboss/calendar/support/navigable.rb +2 -1
  23. data/lib/timeboss/calendar/support/shiftable.rb +12 -11
  24. data/lib/timeboss/calendar/support/translatable.rb +3 -2
  25. data/lib/timeboss/calendar/support/unit.rb +18 -13
  26. data/lib/timeboss/calendar/waypoints/absolute.rb +4 -3
  27. data/lib/timeboss/calendar/waypoints/relative.rb +14 -13
  28. data/lib/timeboss/calendar/week.rb +3 -2
  29. data/lib/timeboss/calendar/year.rb +2 -1
  30. data/lib/timeboss/calendars.rb +3 -2
  31. data/lib/timeboss/calendars/broadcast.rb +8 -7
  32. data/lib/timeboss/calendars/gregorian.rb +2 -1
  33. data/lib/timeboss/version.rb +2 -1
  34. data/spec/calendar/day_spec.rb +14 -14
  35. data/spec/calendar/quarter_spec.rb +9 -9
  36. data/spec/calendar/support/monthly_unit_spec.rb +36 -35
  37. data/spec/calendar/support/unit_spec.rb +23 -22
  38. data/spec/calendar/week_spec.rb +20 -20
  39. data/spec/calendars/broadcast_spec.rb +310 -310
  40. data/spec/calendars/gregorian_spec.rb +258 -258
  41. data/spec/calendars_spec.rb +19 -19
  42. data/spec/spec_helper.rb +2 -2
  43. data/timeboss.gemspec +16 -14
  44. metadata +33 -5
  45. data/lib/timeboss/support/shellable.rb +0 -17
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a66336923993e3b4319dd8d0dc925d936ba7e6897f50f1c679a23f37a35e8f8
4
- data.tar.gz: 3925a5fd244c6fac67ba026f0f3738398bc67f6cc75e015f8eea21caf78f5d84
3
+ metadata.gz: cd2408c9c89006534d10c61c485b8adf4adc5fb8d3fd819ce904ed99c8985db8
4
+ data.tar.gz: e27776f25a4fae89655cc04c07e91e8b607fcc50eb65090be0e6ecd16349c4e3
5
5
  SHA512:
6
- metadata.gz: 87ebf1f8c61e12cd086c33336abca2b5a76ee59cc6117711f166672bd9958c753eb68e38e29ed6aeaccb927520eabaf819da50a62b11879186778f97c982c632
7
- data.tar.gz: 5bc4914fb3f90bb391fb0e3bb852d25764f926492fccc74ff4ecc56ba321fbad9030fb3812423d4c2ed8bc2c61b2e79b9def7ed34a7789061a2367f122888da1
6
+ metadata.gz: 5b7e5694b2955fbf6043d2e52bc8d0e6e15cbedc8fdee19123473b0487f2a9ba48b88b5cf8bd6e0eeb93db2537724e12a9aeb00378e9cad4022dbc9fc01c8887
7
+ data.tar.gz: aefad770303d38a8d2b31baa406cccee9ababea5b2415d6599ec2645e5fca418c61ccbe8f4b6f4aa29a7ead7aea3200b2bce0b83f58f6e6416fb7fb3c9f38b21
@@ -0,0 +1,31 @@
1
+ name: Ruby Gem
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+
7
+ jobs:
8
+ build:
9
+ name: Build + Publish
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: read
13
+ packages: write
14
+
15
+ steps:
16
+ - uses: actions/checkout@v2
17
+ - name: Set up Ruby 2.6
18
+ uses: actions/setup-ruby@v1
19
+ with:
20
+ ruby-version: 2.6.x
21
+
22
+ - name: Publish to RubyGems
23
+ run: |
24
+ mkdir -p $HOME/.gem
25
+ touch $HOME/.gem/credentials
26
+ chmod 0600 $HOME/.gem/credentials
27
+ printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
28
+ gem build *.gemspec
29
+ gem push *.gem
30
+ env:
31
+ GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
@@ -0,0 +1,35 @@
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
9
+
10
+ on:
11
+ push:
12
+ branches: [ master ]
13
+ pull_request:
14
+ branches: [ master ]
15
+
16
+ jobs:
17
+ test:
18
+
19
+ runs-on: ubuntu-latest
20
+ strategy:
21
+ matrix:
22
+ ruby-version: ['2.6', '2.7', '3.0']
23
+
24
+ steps:
25
+ - uses: actions/checkout@v2
26
+ - name: Set up Ruby
27
+ # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
28
+ # change this to (see https://github.com/ruby/setup-ruby#versioning):
29
+ # uses: ruby/setup-ruby@v1
30
+ uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
31
+ with:
32
+ ruby-version: ${{ matrix.ruby-version }}
33
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
34
+ - name: Run tests
35
+ run: bundle exec rspec
data/.travis.yml CHANGED
@@ -1,14 +1,15 @@
1
1
  language: ruby
2
2
  rvm:
3
- - 2.4
4
3
  - 2.5
5
4
  - 2.6
5
+ - 2.7
6
+ - 3.0
6
7
  script:
7
8
  - bundle exec rspec
8
9
  deploy:
9
10
  provider: rubygems
10
11
  api_key:
11
- secure: jUWa2Jx0HRVv7Dl0zYPTskHQ+RJGy2TUcBWOjyFbBUbeDKiRh8J/NnbMuCOvmL94htSaFk5lcs6k74Itu6jW12+KyT98OAnOardFPFuI0cHHhIMEhF6ms8EhyOCZ0vvR9zav11gfNzyF716qO09DQSDuoKWWNdhrYj8a5paLdbHuRqQiw3YUmnjVQ/v9SPYaZ7ziXC4X4tBxQhK2ujNsNfztSVrpYb6pnsXnt+hFQOnskzi0+er4854iymykeyNVgB71KgivrE3T55ZTXPPglshsZQE7M7FlYA5L3bwzR7SlA202yFYHB3hUN3obwO3BjO4OiAdKQnSosBHaXI13ZvCOz02AfEJhwoxkBXw1/2CvSQ12QQPVgqkpxWY03h+URk+gGHCV+JaqZPCV9excmVWg/IOQou0IJ6h84VFViyVc2aFVN2AIdoaG3NsppbV3j4VuLG6J2VVpNmUzN3pGgi5YSjVq9Hp+huXZFfWpnUgAxc680hKgcFajE3JNANG+NbNEeoDmITvZyV5kvJklgUKPsl2wNk+wY/GGrSBgNOVlyXqTWLZb/8Z/cSrN5DEc6D5BIS/SG95wlCRT8jUqbyEPjT+H77TH2ySfwWZzblLqbIxaLiZr3hX16oMdUx7Cya5LKLFgQBpU6cFUxvZX7SqHwjk1vnuG592Kxd9GkX4=
12
+ secure: f7s86k3ZRgaao32goumx0EFSquj8v8vwLBQP0uPd5lZ5OlDjUIbzAGCLpP4IARFf7MhYUUxWqwU7A0Z2MJHgmf4hT2VdVco4kGC4WztMgSI2JwY8Uo21/QJgI82jIfZ6yfSjF8OC3eh9irqJxXfhzspO9DY4p+nJkMJnpG5Y1e5FjS9zM3gS80TD9fauIMEi3fOLDNYEZ95SgjrkX2MHDYQWN1nfFlkRtybSHJ2u2Ad3Ulr5c/1gIoJviJCm8l5Bwo3MnvBtSuHHjFOaH9UTcmDUGpBjr7GMoqn3m053aB1F3ImYwL9+il0rtj+PE1lNaVbUM/QDKp8gDcbo433m8oMiGRpouz0fdIi95fqsshZmSU9sZX6HPiOuURXXwrjW7n3bj71+qZ7zWPTyZB8p3Y6ocp/r6Aj0ewELJksjnbYqSuyYv0o5sKTh2AUMawcqWAnDlZWgMq4UqKQiaWlhZMN1guQIWO6Xq9xdoiIxcqRUTJ7dUAGsfv+GIs2iPLvh20DHudYN70J5b4xzZLFgPQOJbTGlQQtC18m2PaYvcdsZ1qzttQIs0fcgeKno1Ltcman6/yqbAdKsSjifLUcdqHiWOUk5Dh5l4S+iSVazILVFFHwV89JI1+ipuS1nnIaRcmfIkV3GB+aXcbwwYc89mLkXBVmezs+scygK0KUhoyU=
12
13
  gem: timeboss
13
14
  on:
14
15
  tags: true
data/Gemfile CHANGED
@@ -1,3 +1,4 @@
1
1
  # frozen_string_literal: true
2
- source 'https://rubygems.org'
2
+
3
+ source "https://rubygems.org"
3
4
  gemspec
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # TimeBoss [![Build Status](https://travis-ci.com/kevinstuffandthings/timeboss.svg?branch=master)](https://travis-ci.com/kevinstuffandthings/timeboss) [![Gem Version](https://badge.fury.io/rb/timeboss.svg)](https://badge.fury.io/rb/timeboss) [![Run on Repl.it](https://repl.it/badge/github/kevinstuffandthings/timeboss)](https://repl.it/github/kevinstuffandthings/timeboss)
1
+ # TimeBoss ![Build Status](https://github.com/kevinstuffandthings/timeboss/actions/workflows/ruby.yml/badge.svg) [![Gem Version](https://badge.fury.io/rb/timeboss.svg)](https://badge.fury.io/rb/timeboss) [![Run on Repl.it](https://repl.it/badge/github/kevinstuffandthings/timeboss)](https://repl.it/github/kevinstuffandthings/timeboss)
2
2
 
3
3
  A gem providing convenient navigation of the [Broadcast Calendar](https://en.wikipedia.org/wiki/Broadcast_calendar), the standard Gregorian calendar, and is easily extensible to support multiple financial calendars.
4
4
 
@@ -40,7 +40,7 @@ You can ask simple questions of the calendar:
40
40
 
41
41
  ```ruby
42
42
  period = calendar.parse('2019Q4') # or '2018', or '2019-12-21', or '2020W32', or '2020M3W2'
43
- # => #<TimeBoss::Calendar::Quarter:0x007f82d50e2478>
43
+ # => #<TimeBoss::Calendar::Quarter start_date=2019-09-30, end_date=2019-12-29>
44
44
  period.to_s
45
45
  # => "2019Q4: 2019-09-30 thru 2019-12-29"
46
46
  period.next.start_date.to_s # try previous, too!
@@ -117,6 +117,9 @@ week = calendar.parse('2014W29').this_week
117
117
 
118
118
  calendar.this_week.next_year.to_s # run 2020W29
119
119
  # => "2021W29: 2021-07-12 thru 2021-07-18"
120
+
121
+ calendar.week(2016, this_week.in_year) # run 2020-07-22
122
+ # => #<TimeBoss::Calendar::Week start_date=2016-07-18, end_date=2016-07-24>
120
123
  ```
121
124
 
122
125
  Complicated range expressions can be parsed using the `..` range operator, or evaluated with `thru`:
@@ -136,7 +139,7 @@ period = calendar.parse('2020W3..2020Q1')
136
139
  The examples above are just samples. Try different periods, operators, etc. All of the non-week-based operations will work similarly on the `TimeBoss::Calendars::Gregorian` calendar.
137
140
 
138
141
  ### REPL
139
- To open a REPL for the broadcast calendar, use the `tbsh` executable, or the `timeboss:calendars:broadcast:repl` rake task.
142
+ To open a [REPL](https://repl.it/github/kevinstuffandthings/timeboss) locally for the broadcast calendar, use the `tbsh` executable, or the `timeboss:calendars:broadcast:repl` rake task.
140
143
 
141
144
  For the Gregorian calendar (or any other implemented calendars), supply the name on the command line.
142
145
  - `tbsh gregorian`
@@ -147,13 +150,19 @@ You will find yourself in the context of an instantiated `TimeBoss::Calendar` ob
147
150
  ```bash
148
151
  $ tbsh
149
152
  2.4.1 :001 > next_quarter
150
- => #<TimeBoss::Calendar::Quarter:0x007fe04c16a1c8 @calendar=#<TimeBoss::Calendars::Broadcast:0x007fe04c1a0458 @basis=TimeBoss::Calendars::Broadcast::Basis>, @year_index=2020, @index=4, @start_date=#<Date: 2020-09-28 ((2459121j,0s,0n),+0s,2299161j)>, @end_date=#<Date: 2020-12-27 ((2459211j,0s,0n),+0s,2299161j)>>
153
+ => #<TimeBoss::Calendar::Quarter start_date=2020-09-28, end_date=2020-12-27>
151
154
  2.4.1 :002 > last_year
152
- => #<TimeBoss::Calendar::Year:0x007fe04c161ca8 @calendar=#<TimeBoss::Calendars::Broadcast:0x007fe04c1a0458 @basis=TimeBoss::Calendars::Broadcast::Basis>, @year_index=2019, @index=1, @start_date=#<Date: 2018-12-31 ((2458484j,0s,0n),+0s,2299161j)>, @end_date=#<Date: 2019-12-29 ((2458847j,0s,0n),+0s,2299161j)>>
155
+ => #<TimeBoss::Calendar::Year start_date=2018-12-31, end_date=2019-12-29>
153
156
  2.4.1 :003 > parse('this_quarter .. this_quarter+4').months.map(&:name)
154
157
  => ["2020M7", "2020M8", "2020M9", "2020M10", "2020M11", "2020M12", "2021M1", "2021M2", "2021M3", "2021M4", "2021M5", "2021M6", "2021M7", "2021M8", "2021M9"]
155
158
  ```
156
159
 
160
+ If you want to try things out locally without installing the gem or updating your ruby environment, you can use [Docker](https://docker.com):
161
+
162
+ ```bash
163
+ $ docker run --rm -it ruby:2.6.6-slim /bin/bash -c "gem install timeboss >/dev/null && tbsh"
164
+ ```
165
+
157
166
  _Having trouble with the REPL? If you are using the examples from the [Usage](#Usage) section, keep in mind that the REPL is already in the context of the calendar -- so you don't need to specify the receiver!_
158
167
 
159
168
  ## Creating new calendars
@@ -229,5 +238,6 @@ With the new calendar implemented, it can be accessed in one of 2 ways:
229
238
  calendar.this_year
230
239
  ```
231
240
 
232
- ## TODO
233
- - [ ] Add comprehensive documentation
241
+ # Problems?
242
+ Please submit an [issue](https://github.com/kevinstuffandthings/timeboss/issues).
243
+ We'll figure out how to get you up and running with TimeBoss as smoothly as possible.
data/Rakefile CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "bundler/setup"
3
4
  require "bundler/gem_tasks"
5
+ require "standard/rake"
4
6
 
5
- Dir.glob('lib/tasks/*.rake').each { |r| load r }
7
+ Dir.glob("lib/tasks/*.rake").each { |r| load r }
data/bin/tbsh CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'timeboss/calendars'
4
- require 'timeboss/support/shellable'
4
+ require 'shellable'
5
5
 
6
6
  calendar = if ARGV.length == 1
7
7
  TimeBoss::Calendars[ARGV.first]
@@ -12,4 +12,4 @@ calendar = if ARGV.length == 1
12
12
  abort "Unknown calendar" if calendar.nil?
13
13
 
14
14
  puts "Active calendar: #{calendar.title}"
15
- TimeBoss::Support::Shellable.open(calendar)
15
+ Shellable.open(calendar)
@@ -1,18 +1,18 @@
1
- require './lib/timeboss/calendars'
1
+ require "./lib/timeboss/calendars"
2
2
 
3
3
  namespace :timeboss do
4
4
  namespace :calendars do
5
5
  TimeBoss::Calendars.each do |entry|
6
6
  namespace entry.name do
7
7
  desc "Evaluate an expression for the #{entry.name} calendar"
8
- task :evaluate, %i[expression] => ['timeboss:init'] do |_, args|
8
+ task :evaluate, %i[expression] => ["timeboss:init"] do |_, args|
9
9
  puts entry.calendar.parse(args[:expression])
10
10
  end
11
11
 
12
12
  desc "Open a REPL with the #{entry.name} calendar"
13
- task repl: ['timeboss:init'] do
14
- require 'timeboss/support/shellable'
15
- TimeBoss::Support::Shellable.open(entry.calendar)
13
+ task repl: ["timeboss:init"] do
14
+ require "shellable"
15
+ Shellable.open(entry.calendar)
16
16
  end
17
17
 
18
18
  task shell: ["timeboss:calendars:#{entry.name}:repl"]
@@ -1,6 +1,6 @@
1
1
  namespace :timeboss do
2
2
  task :init do
3
- require './lib/timeboss'
4
- require './lib/timeboss/calendars'
3
+ require "./lib/timeboss"
4
+ require "./lib/timeboss/calendars"
5
5
  end
6
6
  end
data/lib/timeboss.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "timeboss/version"
3
4
 
4
5
  # TimeBoss
@@ -1,10 +1,11 @@
1
1
  # frozen_string_literal: true
2
- require 'active_support/inflector'
3
- require 'active_support/core_ext/numeric/time'
2
+
3
+ require "active_support/inflector"
4
+ require "active_support/core_ext/numeric/time"
4
5
 
5
6
  %w[day week month quarter half year].each { |f| require_relative "./calendar/#{f}" }
6
7
  %w[waypoints period parser].each { |f| require_relative "./calendar/#{f}" }
7
- require_relative './calendar/support/month_basis'
8
+ require_relative "./calendar/support/month_basis"
8
9
 
9
10
  module TimeBoss
10
11
  class Calendar
@@ -43,7 +44,7 @@ module TimeBoss
43
44
 
44
45
  def self.register!
45
46
  return unless TimeBoss::Calendars.method_defined?(:register)
46
- TimeBoss::Calendars.register(self.name.to_s.demodulize.underscore, self)
47
+ TimeBoss::Calendars.register(name.to_s.demodulize.underscore, self)
47
48
  end
48
49
  private_class_method :register!
49
50
 
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
- require_relative './support/unit'
2
+
3
+ require_relative "./support/unit"
3
4
 
4
5
  module TimeBoss
5
6
  class Calendar
@@ -17,7 +18,7 @@ module TimeBoss
17
18
  # Get a "pretty" representation of this day.
18
19
  # @return [String] (e.g. "August 3, 2020")
19
20
  def title
20
- start_date.strftime('%B %-d, %Y')
21
+ start_date.strftime("%B %-d, %Y")
21
22
  end
22
23
 
23
24
  alias_method :to_s, :name
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
- require_relative './support/monthly_unit'
2
+
3
+ require_relative "./support/monthly_unit"
3
4
 
4
5
  module TimeBoss
5
6
  class Calendar
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
- require_relative './support/monthly_unit'
2
+
3
+ require_relative "./support/monthly_unit"
3
4
 
4
5
  module TimeBoss
5
6
  class Calendar
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module TimeBoss
3
4
  class Calendar
4
5
  class Parser
5
- RANGE_DELIMITER = '..'
6
+ RANGE_DELIMITER = ".."
6
7
  InvalidPeriodIdentifierError = Class.new(StandardError)
7
8
  attr_reader :calendar
8
9
 
@@ -11,7 +12,7 @@ module TimeBoss
11
12
  end
12
13
 
13
14
  def parse(identifier = nil)
14
- return nil unless (identifier || '').strip.length > 0
15
+ return nil unless (identifier || "").strip.length > 0
15
16
  return parse_identifier(identifier) unless identifier&.include?(RANGE_DELIMITER)
16
17
  bases = identifier.split(RANGE_DELIMITER).map { |i| parse_identifier(i.strip) } unless identifier.nil?
17
18
  bases ||= [parse_identifier(nil)]
@@ -24,13 +25,13 @@ module TimeBoss
24
25
 
25
26
  def parse_identifier(identifier)
26
27
  captures = identifier&.match(/^([^-]+)(\s*[+-]\s*[0-9]+)$/)&.captures
27
- base, offset = captures || [identifier, '0']
28
- period = parse_period(base&.strip) or raise InvalidPeriodIdentifierError
29
- period.offset(offset.gsub(/\s+/, '').to_i)
28
+ base, offset = captures || [identifier, "0"]
29
+ (period = parse_period(base&.strip)) || raise(InvalidPeriodIdentifierError)
30
+ period.offset(offset.gsub(/\s+/, "").to_i)
30
31
  end
31
32
 
32
33
  def parse_period(identifier)
33
- return calendar.send(identifier) if calendar.respond_to?(identifier.to_s)
34
+ return calendar.public_send(identifier) if calendar.respond_to?(identifier.to_s)
34
35
  parse_term(identifier || Date.today.year.to_s)
35
36
  end
36
37
 
@@ -38,13 +39,13 @@ module TimeBoss
38
39
  return Day.new(calendar, Date.parse(identifier)) if identifier.match?(/^[0-9]{4}-?[01][0-9]-?[0-3][0-9]$/)
39
40
 
40
41
  raise InvalidPeriodIdentifierError unless identifier.match?(/^[HQMWD0-9]+$/)
41
- period = if identifier.to_i == 0 then calendar.this_year else calendar.year(identifier.to_i) end
42
+ period = identifier.to_i == 0 ? calendar.this_year : calendar.year(identifier.to_i)
42
43
  %w[half quarter month week day].each do |size|
43
44
  prefix = size[0].upcase
44
45
  next unless identifier.include?(prefix)
45
46
  junk, identifier = identifier.split(prefix)
46
47
  raise InvalidPeriodIdentifierError if junk.match?(/\D/)
47
- period = period.send(size.pluralize)[identifier.to_i - 1] or raise InvalidPeriodIdentifierError
48
+ (period = period.public_send(size.pluralize)[identifier.to_i - 1]) || raise(InvalidPeriodIdentifierError)
48
49
  end
49
50
  period
50
51
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module TimeBoss
3
4
  class Calendar
4
5
  class Period
@@ -28,35 +29,110 @@ module TimeBoss
28
29
 
29
30
  %i[name title to_s].each do |message|
30
31
  define_method(message) do
31
- text = self.begin.send(message)
32
- text = "#{text} #{Parser::RANGE_DELIMITER} #{self.end.send(message)}" unless self.end == self.begin
32
+ text = self.begin.public_send(message)
33
+ text = "#{text} #{Parser::RANGE_DELIMITER} #{self.end.public_send(message)}" unless self.end == self.begin
33
34
  text
34
35
  end
35
36
  end
36
37
 
38
+ #
39
+ # i hate this
40
+ #
41
+
42
+ ### Days
43
+
44
+ # @!method days
45
+ # Get a list of days that fall within this period.
46
+ # @return [Array<Calendar::Day>]
47
+
48
+ # @!method day(index = nil)
49
+ # Get the day this period represents.
50
+ # Returns nil if no single day can be identified.
51
+ # @return [Array<Calendar::Day>, nil]
52
+
53
+ ### Weeks
54
+
55
+ # @!method weeks
56
+ # Get a list of weeks that fall within this period.
57
+ # @return [Array<Calendar::Week>]
58
+
59
+ # @!method week(index = nil)
60
+ # Get the week this period represents.
61
+ # Returns nil if no single week can be identified.
62
+ # @return [Array<Calendar::Week>, nil]
63
+
64
+ ### Months
65
+
66
+ # @!method months
67
+ # Get a list of months that fall within this period.
68
+ # @return [Array<Calendar::Month>]
69
+
70
+ # @!method month(index = nil)
71
+ # Get the month this period represents.
72
+ # Returns nil if no single month can be identified.
73
+ # @return [Array<Calendar::Month>, nil]
74
+
75
+ ### Quarters
76
+
77
+ # @!method quarters
78
+ # Get a list of quarters that fall within this period.
79
+ # @return [Array<Calendar::Quarter>]
80
+
81
+ # @!method quarter(index = nil)
82
+ # Get the quarter this period represents.
83
+ # Returns nil if no single quarter can be identified.
84
+ # @return [Array<Calendar::Quarter>, nil]
85
+
86
+ ### Halves
87
+
88
+ # @!method halves
89
+ # Get a list of halves that fall within this period.
90
+ # @return [Array<Calendar::Half>]
91
+
92
+ # @!method half(index = nil)
93
+ # Get the half this period represents.
94
+ # Returns nil if no single half can be identified.
95
+ # @return [Array<Calendar::Half>, nil]
96
+
97
+ ### Years
98
+
99
+ # @!method years
100
+ # Get a list of years that fall within this period.
101
+ # @return [Array<Calendar::Year>]
102
+
103
+ # @!method year(index = nil)
104
+ # Get the year this period represents.
105
+ # Returns nil if no single year can be identified.
106
+ # @return [Array<Calendar::Year>, nil]
107
+
108
+ # Does this period cover the current date?
109
+ # @return [Boolean]
110
+ def current?
111
+ to_range.include?(Date.today)
112
+ end
113
+
37
114
  %w[day week month quarter half year].each do |size|
38
115
  define_method(size.pluralize) do
39
- entry = calendar.send("#{size}_for", self.begin.start_date)
116
+ entry = calendar.public_send("#{size}_for", self.begin.start_date)
40
117
  build_entries entry
41
118
  end
42
119
 
43
- define_method(size) do
44
- entries = send(size.pluralize)
120
+ define_method(size) do |index = nil|
121
+ entries = public_send(size.pluralize)
122
+ return entries[index - 1] unless index.nil?
45
123
  return nil unless entries.length == 1
46
124
  entries.first
47
125
  end
48
126
  end
49
127
 
50
- # Does this period cover the current date?
51
- # @return [Boolean]
52
- def current?
53
- to_range.include?(Date.today)
54
- end
55
-
56
128
  # Express this period as a date range.
57
129
  # @return [Range<Date, Date>]
58
130
  def to_range
59
- @_to_range ||= start_date .. end_date
131
+ @_to_range ||= start_date..end_date
132
+ end
133
+
134
+ def inspect
135
+ "#<#{self.class.name}[#{self.begin.inspect}..#{self.end.inspect}] start_date=#{start_date}, end_date=#{end_date}>"
60
136
  end
61
137
 
62
138
  private