timeboss 1.0.1 → 1.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) 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 +1 -1
  7. data/Rakefile +3 -1
  8. data/lib/tasks/calendars.rake +4 -4
  9. data/lib/tasks/timeboss.rake +2 -2
  10. data/lib/timeboss.rb +1 -0
  11. data/lib/timeboss/calendar.rb +5 -4
  12. data/lib/timeboss/calendar/day.rb +3 -2
  13. data/lib/timeboss/calendar/half.rb +2 -1
  14. data/lib/timeboss/calendar/month.rb +2 -1
  15. data/lib/timeboss/calendar/parser.rb +9 -8
  16. data/lib/timeboss/calendar/period.rb +6 -5
  17. data/lib/timeboss/calendar/quarter.rb +2 -1
  18. data/lib/timeboss/calendar/support/formatter.rb +5 -4
  19. data/lib/timeboss/calendar/support/month_basis.rb +1 -1
  20. data/lib/timeboss/calendar/support/monthly_unit.rb +7 -6
  21. data/lib/timeboss/calendar/support/navigable.rb +2 -1
  22. data/lib/timeboss/calendar/support/shiftable.rb +12 -11
  23. data/lib/timeboss/calendar/support/translatable.rb +3 -2
  24. data/lib/timeboss/calendar/support/unit.rb +14 -13
  25. data/lib/timeboss/calendar/waypoints/absolute.rb +4 -3
  26. data/lib/timeboss/calendar/waypoints/relative.rb +14 -13
  27. data/lib/timeboss/calendar/week.rb +3 -2
  28. data/lib/timeboss/calendar/year.rb +2 -1
  29. data/lib/timeboss/calendars.rb +3 -2
  30. data/lib/timeboss/calendars/broadcast.rb +8 -7
  31. data/lib/timeboss/calendars/gregorian.rb +2 -1
  32. data/lib/timeboss/version.rb +2 -1
  33. data/spec/calendar/day_spec.rb +14 -14
  34. data/spec/calendar/quarter_spec.rb +9 -9
  35. data/spec/calendar/support/monthly_unit_spec.rb +36 -35
  36. data/spec/calendar/support/unit_spec.rb +23 -22
  37. data/spec/calendar/week_spec.rb +20 -20
  38. data/spec/calendars/broadcast_spec.rb +310 -310
  39. data/spec/calendars/gregorian_spec.rb +258 -258
  40. data/spec/calendars_spec.rb +19 -19
  41. data/spec/spec_helper.rb +2 -2
  42. data/timeboss.gemspec +15 -14
  43. metadata +21 -7
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: cd2408c9c89006534d10c61c485b8adf4adc5fb8d3fd819ce904ed99c8985db8
4
+ data.tar.gz: e27776f25a4fae89655cc04c07e91e8b607fcc50eb65090be0e6ecd16349c4e3
5
5
  SHA512:
6
- metadata.gz: e06fb2e4b8d023d3725a2db5fb98a427cf4b705be7f34e5ca7a52a4c8e3aca9a142868d0f5e01529727c46fa86513daf8a27cdb20fabca5b783b4d74145691a1
7
- data.tar.gz: ef5d7f72b7f26469cc5c34d3628faae0a75cdcc91b0d41c84cb2d81c9767abcf3729269a453fe352dbe69d09e4a719f24688d2495e735f17faf3bc0d4e5bb512
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}}"
@@ -17,6 +17,9 @@ jobs:
17
17
  test:
18
18
 
19
19
  runs-on: ubuntu-latest
20
+ strategy:
21
+ matrix:
22
+ ruby-version: ['2.6', '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) [![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
 
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 }
@@ -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
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,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,12 @@ 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
+ entry = calendar.public_send("#{size}_for", self.begin.start_date)
116
117
  build_entries entry
117
118
  end
118
119
 
119
120
  define_method(size) do |index = nil|
120
- entries = send(size.pluralize)
121
+ entries = public_send(size.pluralize)
121
122
  return entries[index - 1] unless index.nil?
122
123
  return nil unless entries.length == 1
123
124
  entries.first
@@ -127,7 +128,7 @@ module TimeBoss
127
128
  # Express this period as a date range.
128
129
  # @return [Range<Date, Date>]
129
130
  def to_range
130
- @_to_range ||= start_date .. end_date
131
+ @_to_range ||= start_date..end_date
131
132
  end
132
133
 
133
134
  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
@@ -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
@@ -25,7 +26,7 @@ module TimeBoss
25
26
  base = calendar.year(year_index)
26
27
  num_weeks = (((base.end_date - base.start_date) + 1) / 7.0).to_i
27
28
  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) }
29
+ .select { |w| w.start_date.between?(start_date, end_date) }
29
30
  end
30
31
 
31
32
  private
@@ -36,17 +37,17 @@ module TimeBoss
36
37
 
37
38
  def up
38
39
  if index == max_index
39
- calendar.send(self.class.type, year_index + 1, 1)
40
+ calendar.public_send(self.class.type, year_index + 1, 1)
40
41
  else
41
- calendar.send(self.class.type, year_index, index + 1)
42
+ calendar.public_send(self.class.type, year_index, index + 1)
42
43
  end
43
44
  end
44
45
 
45
46
  def down
46
47
  if index == 1
47
- calendar.send(self.class.type, year_index - 1, max_index)
48
+ calendar.public_send(self.class.type, year_index - 1, max_index)
48
49
  else
49
- calendar.send(self.class.type, year_index, index - 1)
50
+ calendar.public_send(self.class.type, year_index, index - 1)
50
51
  end
51
52
  end
52
53
  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