sof-cycle 0.1.1 → 0.1.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a371875b67c2b91bcda00cd042bfa8f4daed5c0ecdbdff66b5680f546b039435
4
- data.tar.gz: 720805643f533158704ad8316a95f0cf1d31b02681a4a7654a4e859951216242
3
+ metadata.gz: e06eb27369a120ec1af76b5d96d6131e10dd7c5293a77a3a9f9a871f7782ccf9
4
+ data.tar.gz: f11c960b91981332057aba2bf3d5226d841b3e87b558f1b526f5e9a33fc7b011
5
5
  SHA512:
6
- metadata.gz: 48aa749e3b0c8a8c810d8e863025af1dadc964348f4f98670f03fade2da9aded8be063c2fe7893ee50b3f9836de3658dc93137a8c41fa9e7afd33e8a51e8c3b3
7
- data.tar.gz: 18148c4e037cd7edd5749ac2c216d13e63ac581065a2a6d45101947dfa5b9d041e611bbc64d36d20336c846cc0272c7eb3eeb077831372661de1512d2f0e3f2c
6
+ metadata.gz: '0808c221b655153d9bb4ae49cbf004586e320bc83f445a493b8dce07d0c15ab6c4c4b6675f1a7ff0f5be0698cd6d2b3961ee9cf0cfebfdd8173c812dc9c672ad'
7
+ data.tar.gz: 551deeaedd7f8a54667af773685e46d19d24b43a49a4f1578ac04e2482038f21ae4ac20a17a0adc99d91189f5a7966712e9b271eb45c14d46baa6b1dba8e568c
data/CHANGELOG.md CHANGED
@@ -5,18 +5,14 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [0.1.1] - 2024-08-09
8
+ ## [0.1.3] - 2024-09-01
9
9
 
10
- ### Added
10
+ ### Fixed
11
11
 
12
- - Basic example in README.md
13
- - Add `Cycles::EndOf` to handle cycles that cover through the end of the nth
14
- subsequent period
15
- - Add predicate methods for each `Cycle` subclass. E.g. `#dormant?`, `#within?`, etc
16
- - Refactor into namespaces
12
+ - `Cycles::EndOf` to have the correct behavior
17
13
 
18
- ## [0.1.0] - 2024-07-09
14
+ ## [0.1.2] - 2024-08-09
19
15
 
20
16
  ### Added
21
17
 
22
- - Initial extraction
18
+ - `Cycle#recurring?` to reveal if a given Cycle is one-and-done or must be repeated.
@@ -0,0 +1 @@
1
+ 78a488a4cea134800aeca3e3e06461a413c564b111d96b25a74c4ae44b5afa66a04d4c59be33cc455bab0c9b1d80cfdd3af1b980859ae3955cb1fd7350fe1459
@@ -2,6 +2,6 @@
2
2
 
3
3
  module SOF
4
4
  class Cycle
5
- VERSION = "0.1.1"
5
+ VERSION = "0.1.3"
6
6
  end
7
7
  end
data/lib/sof/cycle.rb CHANGED
@@ -25,7 +25,7 @@ module SOF
25
25
 
26
26
  delegate [:activated_notation, :volume, :from, :from_date, :time_span, :period,
27
27
  :humanized_period, :period_key, :active?] => :@parser
28
- delegate [:kind, :volume_only?, :valid_periods] => "self.class"
28
+ delegate [:kind, :recurring?, :volume_only?, :valid_periods] => "self.class"
29
29
  delegate [:period_count, :duration] => :time_span
30
30
  delegate [:calendar?, :dormant?, :end_of?, :lookback?, :volume_only?,
31
31
  :within?] => :kind_inquiry
@@ -130,10 +130,11 @@ module SOF
130
130
  @kind = nil
131
131
  @valid_periods = []
132
132
 
133
- def self.volume_only? = @volume_only
134
-
135
133
  class << self
136
134
  attr_reader :notation_id, :kind, :valid_periods
135
+ def volume_only? = @volume_only
136
+
137
+ def recurring? = raise "#{name} must implement #{__method__}"
137
138
  end
138
139
 
139
140
  # Raises an error if the given period isn't in the list of valid periods.
@@ -12,6 +12,8 @@ module SOF
12
12
  def frame_of_reference = "total"
13
13
  end
14
14
 
15
+ def self.recurring? = true
16
+
15
17
  def to_s
16
18
  "#{volume}x every #{period_count} calendar #{humanized_period}"
17
19
  end
@@ -10,6 +10,8 @@ module SOF
10
10
 
11
11
  attr_reader :cycle, :parser
12
12
 
13
+ def self.recurring? = false
14
+
13
15
  def kind = :dormant
14
16
 
15
17
  def dormant? = true
@@ -1,5 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Captures the logic for enforcing the EndOf cycle variant
4
+ # E.g. "V1E18MF2020-01-05" means:
5
+ # You're good until the end of the 17th subsequent month from 2020-01-05.
6
+ # Complete 1 by that date to reset the cycle.
7
+ #
8
+ # Some of the calculations are quite different from other cycles.
9
+ # Whereas other cycles look at completion dates to determine if the cycle is
10
+ # satisfied, this cycle checks whether the anchor date is prior to the final date.
3
11
  module SOF
4
12
  module Cycles
5
13
  class EndOf < Cycle
@@ -8,14 +16,42 @@ module SOF
8
16
  @kind = :end_of
9
17
  @valid_periods = %w[W M Q Y]
10
18
 
19
+ def self.recurring? = true
20
+
11
21
  def to_s
12
22
  return dormant_to_s if dormant?
13
23
 
14
24
  "#{volume}x by #{final_date.to_fs(:american)}"
15
25
  end
16
26
 
27
+ # Returns the expiration date for the cycle
28
+ #
29
+ # @param [nil] _ Unused parameter, maintained for compatibility
30
+ # @param anchor [nil] _ Unused parameter, maintained for compatibility
31
+ # @return [Date] The final date of the cycle
32
+ #
33
+ # @example
34
+ # Cycle.for("V1E18MF2020-01-09")
35
+ # .expiration_of(anchor: "2020-06-04".to_date)
36
+ # # => #<Date: 2021-06-30>
37
+ def expiration_of(_ = nil, anchor: nil) = final_date
38
+
39
+ # Is the supplied anchor date prior to the final date?
40
+ #
41
+ # @return [Boolean] true if the cycle is satisfied, false otherwise
42
+ def satisfied_by?(_ = nil, anchor: Date.current) = anchor <= final_date
43
+
44
+ # Calculates the final date of the cycle
45
+ #
46
+ # @param [nil] _ Unused parameter, maintained for compatibility
47
+ # @return [Date] The final date of the cycle calculated as the end of the
48
+ # nth subsequent period after the FROM date, where n = (period count - 1)
49
+ #
50
+ # @example
51
+ # Cycle.for("V1E18MF2020-01-09").final_date
52
+ # # => #<Date: 2021-06-30>
17
53
  def final_date(_ = nil) = time_span
18
- .end_date(start_date)
54
+ .end_date(start_date - 1.send(period))
19
55
  .end_of_month
20
56
 
21
57
  def start_date(_ = nil) = from_date.to_date
@@ -8,6 +8,8 @@ module SOF
8
8
  @kind = :lookback
9
9
  @valid_periods = %w[D W M Y]
10
10
 
11
+ def self.recurring? = true
12
+
11
13
  def to_s = "#{volume}x in the prior #{period_count} #{humanized_period}"
12
14
 
13
15
  def volume_to_delay_expiration(completion_dates, anchor:)
@@ -19,6 +19,8 @@ module SOF
19
19
  end
20
20
  end
21
21
 
22
+ def self.recurring? = false
23
+
22
24
  def to_s = "#{volume}x total"
23
25
 
24
26
  def covered_dates(dates, ...) = dates
@@ -8,6 +8,8 @@ module SOF
8
8
  @kind = :within
9
9
  @valid_periods = %w[D W M Y]
10
10
 
11
+ def self.recurring? = false
12
+
11
13
  def to_s = "#{volume}x within #{date_range}"
12
14
 
13
15
  def date_range
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sof-cycle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jim Gay
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-08-09 00:00:00.000000000 Z
11
+ date: 2024-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: forwardable
@@ -52,6 +52,7 @@ files:
52
52
  - Rakefile
53
53
  - checksums/sof-cycle-0.1.0.gem.sha512
54
54
  - checksums/sof-cycle-0.1.1.gem.sha512
55
+ - checksums/sof-cycle-0.1.2.gem.sha512
55
56
  - lib/sof-cycle.rb
56
57
  - lib/sof/cycle.rb
57
58
  - lib/sof/cycle/version.rb
@@ -83,7 +84,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
83
84
  - !ruby/object:Gem::Version
84
85
  version: '0'
85
86
  requirements: []
86
- rubygems_version: 3.4.13
87
+ rubygems_version: 3.5.11
87
88
  signing_key:
88
89
  specification_version: 4
89
90
  summary: Parse and interact with SOF cycle notation.