timeboss 1.0.1 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/gem-push.yml +31 -0
  3. data/.github/workflows/ruby.yml +6 -4
  4. data/.travis.yml +11 -1
  5. data/Gemfile +2 -1
  6. data/README.md +7 -2
  7. data/Rakefile +3 -1
  8. data/bin/tbsh +7 -6
  9. data/lib/tasks/calendars.rake +4 -4
  10. data/lib/tasks/timeboss.rake +2 -2
  11. data/lib/timeboss/calendar/day.rb +3 -2
  12. data/lib/timeboss/calendar/half.rb +2 -1
  13. data/lib/timeboss/calendar/month.rb +2 -1
  14. data/lib/timeboss/calendar/parser.rb +9 -8
  15. data/lib/timeboss/calendar/period.rb +9 -6
  16. data/lib/timeboss/calendar/quarter.rb +2 -1
  17. data/lib/timeboss/calendar/support/formatter.rb +5 -4
  18. data/lib/timeboss/calendar/support/has_fiscal_weeks.rb +17 -0
  19. data/lib/timeboss/calendar/support/has_iso_weeks.rb +30 -0
  20. data/lib/timeboss/calendar/support/month_basis.rb +1 -1
  21. data/lib/timeboss/calendar/support/monthly_unit.rb +8 -8
  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 +20 -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/calendar.rb +8 -7
  31. data/lib/timeboss/calendars/broadcast.rb +10 -7
  32. data/lib/timeboss/calendars/gregorian.rb +4 -5
  33. data/lib/timeboss/calendars.rb +3 -2
  34. data/lib/timeboss/version.rb +2 -1
  35. data/lib/timeboss.rb +2 -0
  36. data/spec/{calendar → lib/timeboss/calendar}/day_spec.rb +14 -14
  37. data/spec/{calendar → lib/timeboss/calendar}/quarter_spec.rb +9 -9
  38. data/spec/lib/timeboss/calendar/support/monthly_unit_spec.rb +91 -0
  39. data/spec/{calendar → lib/timeboss/calendar}/support/unit_spec.rb +23 -22
  40. data/spec/{calendar → lib/timeboss/calendar}/week_spec.rb +20 -20
  41. data/spec/lib/timeboss/calendars/broadcast_spec.rb +796 -0
  42. data/spec/lib/timeboss/calendars/gregorian_spec.rb +793 -0
  43. data/spec/{calendars_spec.rb → lib/timeboss/calendars_spec.rb} +19 -19
  44. data/spec/spec_helper.rb +2 -2
  45. data/timeboss.gemspec +17 -14
  46. metadata +53 -23
  47. data/spec/calendar/support/monthly_unit_spec.rb +0 -85
  48. data/spec/calendars/broadcast_spec.rb +0 -796
  49. data/spec/calendars/gregorian_spec.rb +0 -684
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 847be3292a921e4222074f98d62271bfbea96b9b
4
- data.tar.gz: 40866d6a468f3dddc282af7ef893637a8e323b9f
2
+ SHA256:
3
+ metadata.gz: b856796bb4e37e5776aeed86c19dd42832af3091b189f01878d907de5cbf1864
4
+ data.tar.gz: 824c18de591069e4c46d01dc14dc2c1a2ee54881b670218014adf3d4d220a0da
5
5
  SHA512:
6
- metadata.gz: e06fb2e4b8d023d3725a2db5fb98a427cf4b705be7f34e5ca7a52a4c8e3aca9a142868d0f5e01529727c46fa86513daf8a27cdb20fabca5b783b4d74145691a1
7
- data.tar.gz: ef5d7f72b7f26469cc5c34d3628faae0a75cdcc91b0d41c84cb2d81c9767abcf3729269a453fe352dbe69d09e4a719f24688d2495e735f17faf3bc0d4e5bb512
6
+ metadata.gz: 24bc5de8281c36802fb79b92b79a2381794710d320d2890d022c40f40aef4cedb1e3fe963085e3e1ea39fe9f51715994ccca4e5844c0e8bfb2784cbb65c2a339
7
+ data.tar.gz: a1fb6c4825ad05f9dd21a8514c6e6dc24a4904cb235a2a1d16b888e3664fa5f92c6ea8b4ccef3c09198c8e2aea272fb662610bd25fc5ed210f2b095feb90fab3
@@ -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}}"
@@ -17,6 +17,9 @@ jobs:
17
17
  test:
18
18
 
19
19
  runs-on: ubuntu-latest
20
+ strategy:
21
+ matrix:
22
+ ruby-version: ['2.7', '3.0']
20
23
 
21
24
  steps:
22
25
  - uses: actions/checkout@v2
@@ -24,10 +27,9 @@ jobs:
24
27
  # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
25
28
  # change this to (see https://github.com/ruby/setup-ruby#versioning):
26
29
  # uses: ruby/setup-ruby@v1
27
- uses: ruby/setup-ruby@ec106b438a1ff6ff109590de34ddc62c540232e0
30
+ uses: ruby/setup-ruby@473e4d8fe5dd94ee328fdfca9f8c9c7afc9dae5e
28
31
  with:
29
- ruby-version: 2.6
30
- - name: Install dependencies
31
- run: bundle install
32
+ ruby-version: ${{ matrix.ruby-version }}
33
+ bundler-cache: true # runs 'bundle install' and caches installed gems automatically
32
34
  - name: Run tests
33
35
  run: bundle exec rspec
data/.travis.yml CHANGED
@@ -1,7 +1,17 @@
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
9
+ deploy:
10
+ provider: rubygems
11
+ api_key:
12
+ secure: f7s86k3ZRgaao32goumx0EFSquj8v8vwLBQP0uPd5lZ5OlDjUIbzAGCLpP4IARFf7MhYUUxWqwU7A0Z2MJHgmf4hT2VdVco4kGC4WztMgSI2JwY8Uo21/QJgI82jIfZ6yfSjF8OC3eh9irqJxXfhzspO9DY4p+nJkMJnpG5Y1e5FjS9zM3gS80TD9fauIMEi3fOLDNYEZ95SgjrkX2MHDYQWN1nfFlkRtybSHJ2u2Ad3Ulr5c/1gIoJviJCm8l5Bwo3MnvBtSuHHjFOaH9UTcmDUGpBjr7GMoqn3m053aB1F3ImYwL9+il0rtj+PE1lNaVbUM/QDKp8gDcbo433m8oMiGRpouz0fdIi95fqsshZmSU9sZX6HPiOuURXXwrjW7n3bj71+qZ7zWPTyZB8p3Y6ocp/r6Aj0ewELJksjnbYqSuyYv0o5sKTh2AUMawcqWAnDlZWgMq4UqKQiaWlhZMN1guQIWO6Xq9xdoiIxcqRUTJ7dUAGsfv+GIs2iPLvh20DHudYN70J5b4xzZLFgPQOJbTGlQQtC18m2PaYvcdsZ1qzttQIs0fcgeKno1Ltcman6/yqbAdKsSjifLUcdqHiWOUk5Dh5l4S+iSVazILVFFHwV89JI1+ipuS1nnIaRcmfIkV3GB+aXcbwwYc89mLkXBVmezs+scygK0KUhoyU=
13
+ gem: timeboss
14
+ on:
15
+ tags: true
16
+ repo: kevinstuffandthings/timeboss
17
+ skip_cleanup: '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)
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
 
@@ -160,7 +160,7 @@ $ tbsh
160
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
161
 
162
162
  ```bash
163
- $ docker run --rm -it ruby:2.6.6-slim /bin/bash -c "gem install timeboss >/dev/null && tbsh"
163
+ $ docker run --rm -it ruby:3.0-slim /bin/bash -c "gem install timeboss shellable >/dev/null && tbsh"
164
164
  ```
165
165
 
166
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!_
@@ -170,9 +170,14 @@ To create a custom calendar, simply extend the `TimeBoss::Calendar` class, and i
170
170
 
171
171
  ```ruby
172
172
  require 'timeboss/calendar'
173
+ require 'timeboss/calendar/support/has_fiscal_weeks'
173
174
 
174
175
  module MyCalendars
175
176
  class AugustFiscal < TimeBoss::Calendar
177
+ # The calendar we wish to implement has "fiscal weeks", meaning that the weeks start on
178
+ # the day of the containing period.
179
+ include TimeBoss::Calendar::Support::HasFiscalWeeks
180
+
176
181
  def initialize
177
182
  # For each calendar, operation, the class will be instantiated with an ordinal value
178
183
  # for `year` and `month`. It is the instance's job to translate those ordinals into
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,13 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'timeboss/calendars'
4
- require 'shellable'
3
+ require "timeboss"
4
+ require "timeboss/calendars"
5
+ require "shellable"
5
6
 
6
7
  calendar = if ARGV.length == 1
7
- TimeBoss::Calendars[ARGV.first]
8
- else
9
- TimeBoss::Calendars.first.calendar
10
- end
8
+ TimeBoss::Calendars[ARGV.first]
9
+ else
10
+ TimeBoss::Calendars.first.calendar
11
+ end
11
12
 
12
13
  abort "Unknown calendar" if calendar.nil?
13
14
 
@@ -1,17 +1,17 @@
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 'shellable'
13
+ task repl: ["timeboss:init"] do
14
+ require "shellable"
15
15
  Shellable.open(entry.calendar)
16
16
  end
17
17
 
@@ -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
@@ -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,8 +29,8 @@ 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
@@ -112,12 +113,14 @@ module TimeBoss
112
113
 
113
114
  %w[day week month quarter half year].each do |size|
114
115
  define_method(size.pluralize) do
115
- entry = calendar.send("#{size}_for", self.begin.start_date)
116
- build_entries entry
116
+ entry = calendar.public_send("#{size}_for", self.begin.start_date) || self.begin.public_send(size, 1)
117
+ entries = build_entries(entry)
118
+ entries.pop if size == "week" && self.end.next.public_send(size, 1) == entries.last
119
+ entries
117
120
  end
118
121
 
119
122
  define_method(size) do |index = nil|
120
- entries = send(size.pluralize)
123
+ entries = public_send(size.pluralize)
121
124
  return entries[index - 1] unless index.nil?
122
125
  return nil unless entries.length == 1
123
126
  entries.first
@@ -127,7 +130,7 @@ module TimeBoss
127
130
  # Express this period as a date range.
128
131
  # @return [Range<Date, Date>]
129
132
  def to_range
130
- @_to_range ||= start_date .. end_date
133
+ @_to_range ||= start_date..end_date
131
134
  end
132
135
 
133
136
  def inspect
@@ -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 './translatable'
2
+
3
+ require_relative "./translatable"
3
4
 
4
5
  module TimeBoss
5
6
  class Calendar
@@ -18,10 +19,10 @@ module TimeBoss
18
19
  end
19
20
 
20
21
  def to_s
21
- base, text = 'year', unit.year.name
22
+ base, text = "year", unit.year.name
22
23
  periods.each do |period|
23
- sub = unit.send(period) or break
24
- index = sub.send("in_#{base}")
24
+ (sub = unit.public_send(period)) || break
25
+ index = sub.public_send("in_#{base}")
25
26
  text += "#{period[0].upcase}#{index}"
26
27
  base = period
27
28
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TimeBoss
4
+ class Calendar
5
+ module Support
6
+ module HasFiscalWeeks
7
+ def weeks_in(year:)
8
+ num_weeks = (((year.end_date - year.start_date) + 1) / 7.0).to_i
9
+ num_weeks.times.map do |i|
10
+ start_date = year.start_date + (i * 7).days
11
+ Week.new(self, start_date, start_date + 6.days)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TimeBoss
4
+ class Calendar
5
+ module Support
6
+ module HasIsoWeeks
7
+ def weeks_in(year:)
8
+ weeks = []
9
+ start_date = Date.commercial(year.year_index)
10
+ end_date = Date.commercial(year.next.year_index)
11
+ while start_date < end_date
12
+ weeks << Week.new(self, start_date, start_date + 6.days)
13
+ start_date += 7.days
14
+ end
15
+ weeks
16
+ end
17
+
18
+ class Week < Calendar::Week
19
+ def index
20
+ start_date.cweek
21
+ end
22
+
23
+ def year
24
+ calendar.year(start_date.cwyear)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -13,7 +13,7 @@ module TimeBoss
13
13
  end
14
14
 
15
15
  def to_range
16
- @_to_range ||= start_date .. end_date
16
+ @_to_range ||= start_date..end_date
17
17
  end
18
18
  end
19
19
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
- require_relative './unit'
2
+
3
+ require_relative "./unit"
3
4
 
4
5
  module TimeBoss
5
6
  class Calendar
@@ -22,10 +23,9 @@ module TimeBoss
22
23
  # Get a list of weeks contained within this period.
23
24
  # @return [Array<Week>]
24
25
  def weeks
26
+ raise UnsupportedUnitError unless calendar.supports_weeks?
25
27
  base = calendar.year(year_index)
26
- num_weeks = (((base.end_date - base.start_date) + 1) / 7.0).to_i
27
- num_weeks.times.map { |i| Week.new(calendar, base.start_date + (i * 7).days, base.start_date + ((i * 7) + 6).days) }
28
- .select { |w| w.start_date.between?(start_date, end_date) }
28
+ calendar.weeks_in(year: base).select { |w| (w.dates & dates).count >= 4 }
29
29
  end
30
30
 
31
31
  private
@@ -36,17 +36,17 @@ module TimeBoss
36
36
 
37
37
  def up
38
38
  if index == max_index
39
- calendar.send(self.class.type, year_index + 1, 1)
39
+ calendar.public_send(self.class.type, year_index + 1, 1)
40
40
  else
41
- calendar.send(self.class.type, year_index, index + 1)
41
+ calendar.public_send(self.class.type, year_index, index + 1)
42
42
  end
43
43
  end
44
44
 
45
45
  def down
46
46
  if index == 1
47
- calendar.send(self.class.type, year_index - 1, max_index)
47
+ calendar.public_send(self.class.type, year_index - 1, max_index)
48
48
  else
49
- calendar.send(self.class.type, year_index, index - 1)
49
+ calendar.public_send(self.class.type, year_index, index - 1)
50
50
  end
51
51
  end
52
52
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module TimeBoss
3
4
  class Calendar
4
5
  module Support
@@ -61,7 +62,7 @@ module TimeBoss
61
62
  entry = self
62
63
  while quantity > 0
63
64
  entries << entry
64
- entry = entry.send(navigator)
65
+ entry = entry.public_send(navigator)
65
66
  quantity -= 1
66
67
  end
67
68
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module TimeBoss
3
4
  class Calendar
4
5
  module Support
@@ -7,21 +8,21 @@ module TimeBoss
7
8
  periods = period.pluralize
8
9
 
9
10
  define_method("in_#{period}") do
10
- base = send(periods)
11
+ base = public_send(periods)
11
12
  return unless base.length == 1
12
- base.first.send(self.class.type.to_s.pluralize).find_index { |p| p == self } + 1
13
+ base.first.public_send(self.class.type.to_s.pluralize).find_index { |p| p == self } + 1
13
14
  end
14
15
 
15
16
  define_method("#{periods}_ago") do |offset|
16
- base_offset = send("in_#{period}") or return
17
- (calendar.send("this_#{period}") - offset).send(self.class.type.to_s.pluralize)[base_offset - 1]
17
+ (base_offset = public_send("in_#{period}")) || return
18
+ (calendar.public_send("this_#{period}") - offset).public_send(self.class.type.to_s.pluralize)[base_offset - 1]
18
19
  end
19
20
 
20
- define_method("#{periods}_ahead") { |o| send("#{periods}_ago", o * -1) }
21
+ define_method("#{periods}_ahead") { |o| public_send("#{periods}_ago", o * -1) }
21
22
 
22
- define_method("last_#{period}") { send("#{periods}_ago", 1) }
23
- define_method("this_#{period}") { send("#{periods}_ago", 0) }
24
- define_method("next_#{period}") { send("#{periods}_ahead", 1) }
23
+ define_method("last_#{period}") { public_send("#{periods}_ago", 1) }
24
+ define_method("this_#{period}") { public_send("#{periods}_ago", 0) }
25
+ define_method("next_#{period}") { public_send("#{periods}_ahead", 1) }
25
26
  end
26
27
 
27
28
  alias_method :yesterday, :last_day
@@ -133,7 +134,7 @@ module TimeBoss
133
134
  # Get the index-relative month 1 month forward.
134
135
  # Returns nil if no single month can be identified.
135
136
  # @return [Calendar::Month, nil]
136
-
137
+
137
138
  ### Quarters
138
139
 
139
140
  # @!method in_quarter
@@ -167,7 +168,7 @@ module TimeBoss
167
168
  # Get the index-relative quarter 1 quarter forward.
168
169
  # Returns nil if no single quarter can be identified.
169
170
  # @return [Calendar::Quarter, nil]
170
-
171
+
171
172
  ### Halves
172
173
 
173
174
  # @!method in_half
@@ -201,7 +202,7 @@ module TimeBoss
201
202
  # Get the index-relative half 1 half forward.
202
203
  # Returns nil if no single half can be identified.
203
204
  # @return [Calendar::Half, nil]
204
-
205
+
205
206
  ### Years
206
207
 
207
208
  # @!method in_year
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module TimeBoss
3
4
  class Calendar
4
5
  module Support
@@ -8,10 +9,10 @@ module TimeBoss
8
9
  PERIODS.each do |period|
9
10
  periods = period.pluralize
10
11
 
11
- define_method(periods) { calendar.send("#{periods}_for", self) }
12
+ define_method(periods) { calendar.public_send("#{periods}_for", self) }
12
13
 
13
14
  define_method(period) do |index = nil|
14
- entries = send(periods)
15
+ entries = public_send(periods)
15
16
  return entries[index - 1] unless index.nil?
16
17
  return nil unless entries.length == 1
17
18
  entries.first
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
- require_relative './navigable'
3
- require_relative './translatable'
4
- require_relative './shiftable'
5
- require_relative './formatter'
2
+
3
+ require_relative "./navigable"
4
+ require_relative "./translatable"
5
+ require_relative "./shiftable"
6
+ require_relative "./formatter"
6
7
 
7
8
  module TimeBoss
8
9
  class Calendar
@@ -16,7 +17,7 @@ module TimeBoss
16
17
  UnsupportedUnitError = Class.new(StandardError)
17
18
 
18
19
  def self.type
19
- self.name.demodulize.underscore
20
+ name.demodulize.underscore
20
21
  end
21
22
 
22
23
  def initialize(calendar, start_date, end_date)
@@ -28,8 +29,8 @@ module TimeBoss
28
29
  # Is the specified unit equal to this one, based on its unit type and date range?
29
30
  # @param entry [Unit] the unit to compare
30
31
  # @return [Boolean] true when periods are equal
31
- def ==(entry)
32
- self.class == entry.class && self.start_date == entry.start_date && self.end_date == entry.end_date
32
+ def ==(other)
33
+ self.class == other.class && start_date == other.start_date && end_date == other.end_date
33
34
  end
34
35
 
35
36
  # Format this period based on specified granularities.
@@ -59,33 +60,39 @@ module TimeBoss
59
60
  def offset(value)
60
61
  method = value.negative? ? :previous : :next
61
62
  base = self
62
- value.abs.times { base = base.send(method) }
63
+ value.abs.times { base = base.public_send(method) }
63
64
  base
64
65
  end
65
66
 
66
67
  # Move some number of units forward from this unit.
67
68
  # @param value [Integer]
68
69
  # @return [Unit]
69
- def +(value)
70
- offset(value)
70
+ def +(other)
71
+ offset(other)
71
72
  end
72
73
 
73
74
  # Move some number of units backward from this unit.
74
75
  # @param value [Integer]
75
76
  # @return [Unit]
76
- def -(value)
77
- offset(-value)
77
+ def -(other)
78
+ offset(-other)
78
79
  end
79
80
 
80
81
  # Express this period as a date range.
81
82
  # @return [Range<Date, Date>]
82
83
  def to_range
83
- @_to_range ||= start_date .. end_date
84
+ @_to_range ||= start_date..end_date
84
85
  end
85
86
 
86
87
  def inspect
87
88
  "#<#{self.class.name} start_date=#{start_date}, end_date=#{end_date}>"
88
89
  end
90
+
91
+ protected
92
+
93
+ def dates
94
+ @_dates ||= to_range.to_a
95
+ end
89
96
  end
90
97
  end
91
98
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module TimeBoss
3
4
  class Calendar
4
5
  module Waypoints
@@ -9,13 +10,13 @@ module TimeBoss
9
10
 
10
11
  define_method type do |year_index, index = 1|
11
12
  month = (index * size) - size + 1
12
- months = (month .. month + size - 1).map { |i| basis.new(year_index, i) }
13
+ months = (month..month + size - 1).map { |i| basis.new(year_index, i) }
13
14
  klass.new(self, year_index, index, months.first.start_date, months.last.end_date)
14
15
  end
15
16
 
16
17
  define_method "#{type}_for" do |date|
17
- window = send(type, date.year - 1, 1)
18
- while true
18
+ window = public_send(type, date.year - 1, 1)
19
+ loop do
19
20
  break window if window.to_range.include?(date)
20
21
  window = window.next
21
22
  end