billing_cycle 1.0.0 → 1.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: de1567f4fc4e2813c2e8a24d7c38d4972de4dd92
4
- data.tar.gz: e433e801af93c75c6d5dc056d9af3d34c236a0b3
2
+ SHA256:
3
+ metadata.gz: 56e5ae7abb7f48642d430ade7fa35c530b9dae71d9a62f8a8ba9b9e17aa4d9f3
4
+ data.tar.gz: 35c7a99568dfa8ce123f87445deef160fa2fa5ae7a4db857590cf84ae9b69499
5
5
  SHA512:
6
- metadata.gz: 0cb00109a6b6d23b477aa8c5b6b4c3304f8c39441bf42939f17624ab3e47300cb076727d7996dc44083f4596ae6487863016f2b0f3f5581dbd904d511c2b1878
7
- data.tar.gz: 7cf9c934466b6d9c4092f87f8f3af6aa60b18817786529f86599371b749991ccaf36717ebf68474f28ffafed8eb12f112d4a46e2e5173e6a4afc0415e364972b
6
+ metadata.gz: 0577b5c653533ca5450de90f69570c1b6ccf89dac6f3ee14f0883d019d0939bd086f1023d7a3bc72dcef793cc8798b44cf019d41acd0df14c2269cc81514418d
7
+ data.tar.gz: c1c22e8c030535db87b7a2ab53bd535131f3fd61ecc935e1ce425f2150f24c8aa4e8e26805d8449f9f5e029d868958eb14f28ca05c0775973ea16d060f3c0877
data/README.md CHANGED
@@ -5,7 +5,8 @@
5
5
  [![Test Coverage](https://codeclimate.com/github/simplymadeapps/billing_cycle/badges/coverage.svg)](https://codeclimate.com/github/simplymadeapps/billing_cycle/coverage)
6
6
  [![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](http://www.rubydoc.info/github/simplymadeapps/billing_cycle/)
7
7
 
8
- Billing Cycle is a gem used to calculate the next billing date for a recurring subscription.
8
+ Billing Cycle is a gem used to calculate the billing due dates and time elapsed/remaining in
9
+ a recurring subscription's billing cycle.
9
10
 
10
11
  ## Installation
11
12
 
@@ -23,6 +24,12 @@ $ bundle
23
24
 
24
25
  ## Usage
25
26
 
27
+ ### Due Dates
28
+
29
+ Calculating due dates requires the original billing date as an anchor to determine due dates
30
+ in the future. `BillingCycle::BillingCycle` does the work to handle edge cases like having
31
+ a monthly subscription that started on the 31st when there's not 31 days in every month.
32
+
26
33
  ```ruby
27
34
  original_billing_date = Time.zone.parse("2018-01-31 00:00:00")
28
35
  billing_interval = 1.month
@@ -34,11 +41,15 @@ Time.zone.now
34
41
  billing_cycle.next_due_at
35
42
  # => Sat, 30 Jun 2018 00:00:00 CDT -05:00
36
43
 
37
- billing_cycle.next_due_at(Time.zone.parse("2020-02-01 00:00:00")
38
- # => Sat, 29 Feb 2020 00:00:00 CST -06:00
39
-
40
44
  billing_cycle.previous_due_at
41
45
  # => Thu, 31 May 2018 00:00:00 CDT -05:00
46
+ ```
47
+
48
+ A time can be passed in as "now" instead of implicitly using the current time.
49
+
50
+ ```ruby
51
+ billing_cycle.next_due_at(Time.zone.parse("2020-02-01 00:00:00")
52
+ # => Sat, 29 Feb 2020 00:00:00 CST -06:00
42
53
 
43
54
  billing_cycle.previous_due_at(Time.zone.parse("2020-02-01 00:00:00")
44
55
  # => Fri, 31 Jan 2020 00:00:00 CST -06:00
@@ -59,6 +70,67 @@ billing_cycle.previous_due_at
59
70
  # => nil
60
71
  ```
61
72
 
73
+ ### Time Elapsed and Remaining
74
+
75
+ The time elapsed and remaining can be used for displaying how much time has been used
76
+ and how much time is left in a billing cycle.
77
+
78
+ ```ruby
79
+ original_billing_date = Time.zone.parse("2019-06-01 00:00:00")
80
+ billing_interval = 1.month
81
+ billing_cycle = BillingCycle::BillingCycle.new(original_billing_date, billing_interval)
82
+
83
+ Time.zone.now
84
+ # => Sun, 16 Jun 2019 00:00:00 CDT -05:00
85
+
86
+ billing_cycle.time_elapsed
87
+ # => 1296000.0 (seconds)
88
+
89
+ billing_cycle.time_remaining
90
+ # => 1296000.0 (seconds)
91
+ ```
92
+
93
+ An interval can be passed in instead of implicitly using seconds and time can be passed in as "now"
94
+ instead of implicitly using the current time.
95
+
96
+ ```ruby
97
+ billing_cycle.time_elapsed(1.day, Time.zone.parse("2019-06-07 00:00:00"))
98
+ # => 6.0 (days)
99
+
100
+ billing_cycle.time_remaining(1.day, Time.zone.parse("2019-06-07 00:00:00"))
101
+ # => 24.0 (days)
102
+ ```
103
+
104
+ ### Percent Elapsed and Remaining
105
+
106
+ The percent elapsed and remaining can be used for calculating subscription pricing when charging
107
+ or refunding for a partial billing cycle. The percentages are returned as a fraction of 1.0.
108
+
109
+ ```ruby
110
+ original_billing_date = Time.zone.parse("2019-06-01 00:00:00")
111
+ billing_interval = 1.month
112
+ billing_cycle = BillingCycle::BillingCycle.new(original_billing_date, billing_interval)
113
+
114
+ Time.zone.now
115
+ # => Sun, 16 Jun 2019 00:00:00 CDT -05:00
116
+
117
+ billing_cycle.percent_elapsed
118
+ # => 0.5
119
+
120
+ billing_cycle.percent_remaining
121
+ # => 0.5
122
+ ```
123
+
124
+ A time can be passed in as "now" instead of implicitly using the current time.
125
+
126
+ ```ruby
127
+ billing_cycle.percent_elapsed(Time.zone.parse("2019-06-07 00:00:00"))
128
+ # => 0.2
129
+
130
+ billing_cycle.percent_remaining(Time.zone.parse("2019-06-07 00:00:00"))
131
+ # => 0.8
132
+ ```
133
+
62
134
  ## Contributing
63
135
 
64
136
  1. Fork it
@@ -68,4 +140,5 @@ billing_cycle.previous_due_at
68
140
  5. Create new Pull Request
69
141
 
70
142
  ## License
143
+
71
144
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -35,6 +35,20 @@ module BillingCycle
35
35
  next_due_at
36
36
  end
37
37
 
38
+ # Returns the percentage of time that's elapsed between the previous due date and the next due date.
39
+ # @param now [Time] The current time
40
+ # @return [Float] The percentage as a fraction of 1.0
41
+ def percent_elapsed(now = Time.zone.now)
42
+ time_elapsed(1.second, now) / seconds_in_cycle(now)
43
+ end
44
+
45
+ # Returns the percentage of time that's remaining between the previous due date and the next due date.
46
+ # @param now [Time] The current time
47
+ # @return [Float] The percentage as a fraction of 1.0
48
+ def percent_remaining(now = Time.zone.now)
49
+ time_remaining(1.second, now) / seconds_in_cycle(now)
50
+ end
51
+
38
52
  # Returns the previous billing date based on the subscription
39
53
  # @param now [Time] The current time
40
54
  # @return [Time] The previous billing date/time
@@ -55,6 +69,21 @@ module BillingCycle
55
69
  previous_due_at
56
70
  end
57
71
 
72
+ # Returns the time elapsed since the previous due date.
73
+ # @param interval [ActiveSupport::Duration] The duration
74
+ # @param now [Time] The current time
75
+ # @return [Float] The number of intervals since the previous due date
76
+ def time_elapsed(interval = 1.second, now = Time.zone.now)
77
+ (now - previous_due_at(now)) / interval
78
+ end
79
+
80
+ # Returns the time remaining until the next due date.
81
+ # @param now [Time] The current time
82
+ # @return [Float] The number of intervals until the next due date
83
+ def time_remaining(interval = 1.second, now = Time.zone.now)
84
+ (next_due_at(now) - now) / interval
85
+ end
86
+
58
87
  private
59
88
 
60
89
  # Calculate the due date based on number of billing cycles since
@@ -86,9 +115,17 @@ module BillingCycle
86
115
  end
87
116
 
88
117
  # Returns the number billing cycles that have occurred between the created date and "now".
118
+ # @param now [Time] The current time
89
119
  # @return [Integer]
90
120
  def number_of_cycles_since_created(now)
91
121
  (interval_value * ((now - created_at).to_i / interval)).to_i
92
122
  end
123
+
124
+ # Returns the total number of seconds in the current billing cycle.
125
+ # @param now [Time] The current time
126
+ # @return [Float]
127
+ def seconds_in_cycle(now)
128
+ next_due_at(now) - previous_due_at(now)
129
+ end
93
130
  end
94
131
  end
@@ -1,3 +1,3 @@
1
1
  module BillingCycle
2
- VERSION = "1.0.0".freeze
2
+ VERSION = "1.1.0".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: billing_cycle
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Pattison
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-10 00:00:00.000000000 Z
11
+ date: 2019-08-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -155,8 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
155
155
  - !ruby/object:Gem::Version
156
156
  version: '0'
157
157
  requirements: []
158
- rubyforge_project:
159
- rubygems_version: 2.5.2
158
+ rubygems_version: 3.0.3
160
159
  signing_key:
161
160
  specification_version: 4
162
161
  summary: Utility for calculating the next billing date for a recurring subscription.