Skip to content

Instantly share code, notes, and snippets.

@devxtoshi
Forked from cballou/stripe-proration.php
Created March 10, 2023 01:40
Show Gist options
  • Save devxtoshi/2d2110bb0eda67371ca7e5976daebd60 to your computer and use it in GitHub Desktop.
Save devxtoshi/2d2110bb0eda67371ca7e5976daebd60 to your computer and use it in GitHub Desktop.
Calculate a proration percentage given the current timestamp and a current billing period
<?php
/**
* Handle calculating a percentage/fraction (proration) we should charge the
* user for based on the current day of the month before their next bill cycle.
* To use yourself, implement a getSubscription method which returns an object
* containing current_period_start and current_period_end DateTime objects.
*
* @access public
* @return float
*/
function prorateUpcomingBillingCycle()
{
$now = new DateTime('now', new DateTimeZone('UTC'));
// determine the next billing cycle
$subscription = getSubscription();
$currentPeriodStart = $subscription->current_period_start;
$currentPeriodEnd = $subscription->current_period_end;
if (is_string($currentPeriodStart)) {
$currentPeriodStart = new DateTime($currentPeriodStart, new DateTimeZone('UTC'));
}
if (is_string($currentPeriodEnd)) {
$currentPeriodEnd = new DateTime($currentPeriodEnd, new DateTimeZone('UTC'));
}
// get the number of second difference between the cycle start and end date
$currentPeriodStartEpoch = (int) $currentPeriodStartEpoch->format('U');
$currentPeriodEndEpoch = (int) $currentPeriodEndEpoch->format('U');
$nowEpoch = (int) $now->format('U');
// if we aren't between the start and end of the subscription period, we have a problem
if ($nowEpoch < $currentPeriodStartEpoch || $nowEpoch > $currentPeriodEndEpoch) {
throw new Exception('The current timestamp does not fall within the current subscription period.');
}
// get the difference of the start and end time in seconds
$epochDifference = $currentPeriodEndEpoch - $currentPeriodStartEpoch;
// get the prorated number of seconds till the end of the subscription period
$remainingSecondsInPeriod = $currentPeriodEndEpoch - $nowEpoch;
// return fraction of the total seconds in the current billing period
return $remainingSecondsInPeriod / $epochDifference;
}
/**
* Returns an example subscription object with a 30 day subscription period.
*
* This is only for reference.
*
* @return object
*/
function getSubScription()
{
$now = new DateTime('now', new DateTimeZone('UTC'));
$obj = new stdClass();
$obj->current_period_start = clone $now;
$obj->current_period_start->sub(new DateInterval('P15D');
$obj->current_period_end = clone $now;
$obj->current_period_end->add(new DateInterval('P15D')));
return $obj;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment