Home > Enterprise >  Calculating A Cycle number using dates for a 28 day repeating cycle
Calculating A Cycle number using dates for a 28 day repeating cycle

Time:11-25

I have a job that runs every 28 days. and I want to assign it a cycle number based on a starting reference date.

e.g

1st cycle is 01/27/22. and that cycle number would be 2201. subsequently I want to calculate the cycle number based on the current date. but for each year there could be either 13 or 14 cycles.

I've managed to figure out the number of cycles since the reference date to figure out the latest cycle date (see below)

const REF_ZERO_DATE = '01/27/2022';
const REF_ZERO_CYCLE_YEAR = "22";
const REF_ZERO_CYCLE_NUM = "01"; 
    
    $today = new \DateTime("2023/12/29");
    echo ("Today = ".$today->format("Y/m/d")."\n");
    $ref_zero = new \DateTime(self::REF_ZERO_DATE);
    echo ("ref_zero = ".$ref_zero->format("Y/m/d")."\n");

    $number_of_days_since_ref_zero = $today->diff($ref_zero)->format("%a");
    echo ("Number of days since ref zero = ".$number_of_days_since_ref_zero."\n");

    $number_of_cycles_since_ref_zero = floor($number_of_days_since_ref_zero/28);
    echo ("Number of cycles since ref zero = ".$number_of_cycles_since_ref_zero."\n");

    $interval = 'P' . $number_of_cycles_since_ref_zero*28 . 'D';
    echo ("Interval = ".$interval);

    $date_of_lastest_cycle = date_add($ref_zero,new \DateInterval($interval));
    echo ("last Cycle Date = ".$date_of_lastest_cycle->format("Y/m/d")."\n");

   

But my math for the cycle adjustment is missing coping with 12 or 13 cycle in a specific year.

CodePudding user response:

It is not explicitly stated whether the cycle of the previous year continues into the next or not.

The scenario in which the cycles can overlap between years is more complicated, so this is assumed.

The interval count code was extracted to the following function:

function calculateIntervalCount($startDate, $endDate, $interval) {
    $start = new \DateTime($startDate);
    $end = new \DateTime($endDate);
    $interval = new \DateInterval($interval);
    
    $periodDays = intval($end->diff($start)->format('%a'));
    $intervalDays = intval($interval->format('%d'));
    
    return floor($periodDays / $intervalDays);
}

There are two cases when calculating the interval count of a particular year:

  1. year of start and end are the same year
  2. year of end is after year of start

In the first case the interval count is the same as the interval count of the whole period.

In the second case the interval count of a particular year can be calculated from the difference between the interval counts of the whole period and the period before the end year.

The following function returns the cycle number:

function calculateCycleNumber($startDate, $endDate, $interval) {
    $totalCycles = calculateIntervalCount($startDate,$endDate,$interval);
    
    $startYear = intval((new \DateTime($startDate))->format('Y'));
    $endYear = intval((new \DateTime($endDate))->format('Y'));
    
    if($startYear < $endYear) {
        $endOfLastYearDate = (new \DateTime($endDate))->modify('last day of December last year')->format('Y-m-d');
        $cyclesSinceEndOfLastYear = calculateIntervalCount($endOfLastYearDate, $endDate, $interval);
        $yearCycle = $totalCycles - $cyclesSinceEndOfLastYear   1;
    } else {
        $yearCycle = $totalCycles;
    }
    
    $yearCode = substr($endYear,-2);
    $yearCycleCode = sprintf('d', $yearCycle);

    return $yearCode . $yearCycleCode;
}

A cycle number of 2314 was obtained with the inputs provided.

echo calculateCycleNumber('01/27/2022','2023/12/29','P28D');

Note that 14 is possible in case of overlapping cycles.

CodePudding user response:

You can use timestamp, where you add 28 days each time so you get the next date and so on.

Get the next timestamp

$next_date = strtotime(' 28 day', $timestamp);

Convert to readable date

echo date('m/d/Y', $next_date);
  • Related