0.01
No release in over 3 years
Low commit activity in last 3 years
Billing Cycle is a gem used to calculate the next billing date for a recurring subscription.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies
 Project Readme

Billing Cycle

Build Status Code Climate Test Coverage Yard Docs

Billing Cycle is a gem used to calculate the billing due dates and time elapsed/remaining in a recurring subscription's billing cycle.

Installation

Add this line to your application's Gemfile:

gem "billing_cycle"

And then execute:

$ bundle

Usage

Due Dates

Calculating due dates requires the original billing date as an anchor to determine due dates in the future. BillingCycle::BillingCycle does the work to handle edge cases like having a monthly subscription that started on the 31st when there's not 31 days in every month.

original_billing_date = Time.zone.parse("2018-01-31 00:00:00")
billing_interval = 1.month
billing_cycle = BillingCycle::BillingCycle.new(original_billing_date, billing_interval)

Time.zone.now
# => Tue, 26 Jun 2018 00:00:00 CDT -05:00

billing_cycle.next_due_at
# => Sat, 30 Jun 2018 00:00:00 CDT -05:00

billing_cycle.previous_due_at
# => Thu, 31 May 2018 00:00:00 CDT -05:00

A time can be passed in as "now" instead of implicitly using the current time.

billing_cycle.next_due_at(Time.zone.parse("2020-02-01 00:00:00")
# => Sat, 29 Feb 2020 00:00:00 CST -06:00

billing_cycle.previous_due_at(Time.zone.parse("2020-02-01 00:00:00")
# => Fri, 31 Jan 2020 00:00:00 CST -06:00

If the original billing date is in the future, the next_due_at will always be the original billing date, and the previous_due_at will be nil.

original_billing_date = Time.zone.parse("9999-12-31 00:00:00")
billing_interval = 1.month
billing_cycle = BillingCycle::BillingCycle.new(original_billing_date, billing_interval)

billing_cycle.next_due_at
# => Fri, 31 Dec 9999 00:00:00 CST -06:00

billing_cycle.previous_due_at
# => nil

Time Elapsed and Remaining

The time elapsed and remaining can be used for displaying how much time has been used and how much time is left in a billing cycle.

original_billing_date = Time.zone.parse("2019-06-01 00:00:00")
billing_interval = 1.month
billing_cycle = BillingCycle::BillingCycle.new(original_billing_date, billing_interval)

Time.zone.now
# => Sun, 16 Jun 2019 00:00:00 CDT -05:00

billing_cycle.time_elapsed
# => 1296000.0 (seconds)

billing_cycle.time_remaining
# => 1296000.0 (seconds)

An interval can be passed in instead of implicitly using seconds and time can be passed in as "now" instead of implicitly using the current time.

billing_cycle.time_elapsed(1.day, Time.zone.parse("2019-06-07 00:00:00"))
# => 6.0 (days)

billing_cycle.time_remaining(1.day, Time.zone.parse("2019-06-07 00:00:00"))
# => 24.0 (days)

Percent Elapsed and Remaining

The percent elapsed and remaining can be used for calculating subscription pricing when charging or refunding for a partial billing cycle. The percentages are returned as a fraction of 1.0.

original_billing_date = Time.zone.parse("2019-06-01 00:00:00")
billing_interval = 1.month
billing_cycle = BillingCycle::BillingCycle.new(original_billing_date, billing_interval)

Time.zone.now
# => Sun, 16 Jun 2019 00:00:00 CDT -05:00

billing_cycle.percent_elapsed
# => 0.5

billing_cycle.percent_remaining
# => 0.5

A time can be passed in as "now" instead of implicitly using the current time.

billing_cycle.percent_elapsed(Time.zone.parse("2019-06-07 00:00:00"))
# => 0.2

billing_cycle.percent_remaining(Time.zone.parse("2019-06-07 00:00:00"))
# => 0.8

Contributing

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create new Pull Request

License

The gem is available as open source under the terms of the MIT License.