Djave
Djave

Reputation: 9359

Calculate the time remaining until a subscription

I have a subscription that can be subscribed to every month, every two months or every 3 months. That's represented as a subscription_frequency of 1, 2 or 3.

I then have a month_joined property (1 through 12).

But I'm trying to work out, when someone should receive their subscription. So far I know I want to work out when the user will next receive a subscription.

So I'm adding 12 to the current month, then subtracting the month_joined number, and then finding the remainder of their subscription_frequency, to add on to the current month to tell them when their next box is due.

public function nextsub()
{
    $remainder = ($current_month + 12 - $this->month_joined) % $this->subscription_frequency;
    return $current_month + remainder;
}

But all my number are coming out screwy. Here is dump of users:

[
{
current_month: 3,
month_joined: 1,
subscription_frequency: 1,
next_box: 3
},
{
current_month: 3,
month_joined: 3,
subscription_frequency: 3,
next_box: 3
},
{
current_month: 3,
month_joined: 11,
subscription_frequency: 3,
next_box: 4<----------------- this is incorrect
},
{
current_month: 3,
month_joined: 12,
subscription_frequency: 3,
next_box: 3<----------------- this is incorrect
},
{
current_month: 3,
month_joined: 8,
subscription_frequency: 2,
next_box: 4
},
{
current_month: 3,
month_joined: 1,
subscription_frequency: 1,
next_box: 3
},
{
current_month: 3,
month_joined: 3,
subscription_frequency: 2,
next_box: 3
},
{
current_month: 3,
month_joined: 2,
subscription_frequency: 3,
next_box: 4 <----------------- this is incorrect
},
{
current_month: 3,
month_joined: 2,
subscription_frequency: 1,
next_box: 3
}
]

What's the matter with my maths?

Upvotes: 0

Views: 64

Answers (2)

greg_diesel
greg_diesel

Reputation: 2970

This is hardly efficient but it should give you the next subscription month

  public function nextsub()
{
    $arrayofpossiblesubscriptionmonths=array();

    for($i=1;$i<=12;$i++){
        $submonth=$month_joined+($i*$this->subscription_frequency);
        if($submonth>12){
            $submonth=$submonth-12;
        }
        //this will create some duplicate months
        $arrayofpossiblesubscriptionmonths[]=$submonth;
    }
    //cleanup duplicates
    $uniquesubmonths=array_unique($arrayofpossiblesubscriptionmonths);

    //fix the order
    sort($uniquesubmonths);

    //since they are in order.  find the first one bigger than our current month
    foreach($uniquesubmonths as $onesub){
        if($onesub>$current_month){
            return $onesub;
        }
    }
}

Here is a CodeViper in action with a slightly altered function so I could pass the variables in easier http://codepad.viper-7.com/9Er2pi

      function nextsub($current_month,$month_joined,$subscription_frequency)
{



    $arrayofpossiblesubscriptionmonths=array();

    for($i=1;$i<=12;$i++){
        $submonth=$month_joined+($i*$subscription_frequency);
        if($submonth>12){
            $submonth=$submonth-12;
        }
        //this will create some duplicate months
        $arrayofpossiblesubscriptionmonths[]=$submonth;
    }
    //cleanup duplicates
    $uniquesubmonths=array_unique($arrayofpossiblesubscriptionmonths);

    //fix the order
    sort($uniquesubmonths);

    //since they are in order.  find the first one bigger than our current month
    foreach($uniquesubmonths as $onesub){
        if($onesub>$current_month){
            return $onesub;
        }
    }
}
$curmonth=3;
$monthjoined=1;
$sub_freq=1;
echo '<BR>Current month: '.$curmonth;
echo '<BR>Month Joined: '.$monthjoined;
echo '<BR>Subscription Frequency: '.$sub_freq;
echo '<BR>Next Subscription Month: '.nextsub($curmonth,$monthjoined,$sub_freq);

echo'<HR>';
$curmonth=3;
$monthjoined=11;
$sub_freq=3;
echo '<BR>Current month: '.$curmonth;
echo '<BR>Month Joined: '.$monthjoined;
echo '<BR>Subscription Frequency: '.$sub_freq;
echo '<BR>Next Subscription Month: '.nextsub($curmonth,$monthjoined,$sub_freq);

echo'<HR>';
$curmonth=3;
$monthjoined=8;
$sub_freq=2;
echo '<BR>Current month: '.$curmonth;
echo '<BR>Month Joined: '.$monthjoined;
echo '<BR>Subscription Frequency: '.$sub_freq;
echo '<BR>Next Subscription Month: '.nextsub($curmonth,$monthjoined,$sub_freq);

Output

Current month: 3
Month Joined: 1
Subscription Frequency: 1
Next Subscription Month: 4

Current month: 3
Month Joined: 11
Subscription Frequency: 3
Next Subscription Month: 5

Current month: 3
Month Joined: 8
Subscription Frequency: 2
Next Subscription Month: 4

Upvotes: 0

Anti
Anti

Reputation: 458

IMHO you could check if the current month is a month you should be sending the subscription (this doesn't check if you sent the subscription for the current month, this should be a separate functionality)

If you deliver in the month of subscription

enter code here
$shouldSubscriptionBeSent = ($currentMonth - $monthJoined) % $subscriptionFrequency === 0

If you deliver the next month after subscription

$shouldSubscriptionBeSent = ($currentMonth - $monthJoined - 1) % $subscriptionFrequency === 0

I think you should keep an array with the months you delivered, and the subscription month in fact should be a date, and afterwards you could find the subscription dates by adding the frequency months to the subscription date.

Upvotes: 1

Related Questions