Skip to content

Instantly share code, notes, and snippets.

@ahmadshah
Last active August 29, 2015 14:01
Show Gist options
  • Save ahmadshah/b61f303b1c17ff52a45d to your computer and use it in GitHub Desktop.
Save ahmadshah/b61f303b1c17ff52a45d to your computer and use it in GitHub Desktop.
Date Recurring Scheduler By Month
function batch_scheduler($start, $end, $interval) {
$years = array();
$recurrings = array($start);
preg_match('/^[0-9]{4}/', $start, $startYear);
preg_match('/^[0-9]{4}/', $end, $endYear);
$diff = $endYear[0] - $startYear[0];
if ($diff > 5) {
for ($i = 0; $i <= $diff; $i = $i+5) {
$years[] = $startYear[0] + $i;
}
if ( ! in_array($endYear[0], $years)) {
$years[] = $endYear[0];
}
for ($m = 1; $m < count($years); $m++) {
$s = preg_replace('/^[0-9]{4}/', $years[$m-1], $start);
$e = preg_replace('/^[0-9]{4}/', $years[$m], $end);
$scheduler = new Scheduler($s, $e);
$recurrings[] = $scheduler->setRecurring($interval)->get();
}
} else {
$scheduler = new Scheduler($start, $end);
$recurrings[] = $scheduler->setRecurring($interval)->get();
}
return array_flatten(array_unique(array_flatten($recurrings)));
}
<?php
use \Exception;
use Carbon\Carbon;
class Scheduler {
/**
* Scheduler starting date
*
* @var string
*/
protected $startDate;
/**
* Scheduler end date
*
* @var string
*/
protected $endDate;
/**
* Recurrings scheduler dates
*
* @var array
*/
protected $recurrings = array();
/**
* Instantiate scheduler
*
* @param string $startDate
* @param string $endDate
*/
public function __construct($startDate, $endDate)
{
$this->setDates($startDate, $endDate);
}
/**
* Set start and end date for scheduler
*
* @param string $startDate
* @param string $endDate
*/
public function setDates($startDate, $endDate)
{
$start = $this->toCarbon($startDate);
$end = $this->toCarbon($endDate);
if ($end < $start) {
throw new Exception("End date {$endDate} cannot be lower than start date {$startDate}");
}
$this->startDate = $startDate;
$this->endDate = $end->format('Y-m-d');
}
/**
* Set scheduler recurring by month
*
* @param integer $months
* @return mixed
*/
public function setRecurring($months, $startDate = null, $format = 'Y-m-d')
{
if ($months > 12) {
throw new Exception("Scheduler recurring interval cannot be more than 12 months. {$months} given.");
}
$start = $this->toCarbon($this->startDate);
$this->recurrings = $this->getNextRecurringDate($start, $months);
return $this;
}
/**
* Get recurrings scheduler dates
*
* @return array
*/
public function get()
{
$recurrings = $this->recurrings;
$end = $this->toCarbon($this->endDate);
$last = $this->toCarbon(array_pop($recurrings));
if ($last > $end) {
array_pop($this->recurrings);
}
return $this->recurrings;
}
/**
* Get next recurring dates
*
* @param Carbon\Carbon $base
* @param integer $months [description]
* @return array
*/
protected function getNextRecurringDate(Carbon $base, $interval)
{
$dates = array();
list($year, $month, $day) = $this->calculateNextDate($base->format('Y-m-d'), $interval);
$next = $this->toCarbon("{$year}-{$month}-{$day}");
$nextTotalDays = $next->format('t');
$start = $this->toCarbon($this->startDate);
$end = $this->toCarbon($this->endDate);
$recurring = $base->addMonths($interval);
if ($recurring->month > $month) {
$nextDate = $this->toCarbon("{$year}-{$month}-{$nextTotalDays}");
$diff = $recurring->diffInDays($nextDate);
$recurring->subDays($diff);
}
if ($recurring->day != $start->day and $recurring->month != 2) {
$recurring->day = $start->day;
}
if ($start->day == $start->lastOfMonth()->day) {
$recurring->day = $recurring->lastOfMonth()->day;
}
$dates[] = $recurring->format('Y-m-d');
if ($recurring < $end) {
$dates[] = $this->getNextRecurringDate($recurring, $interval);
}
return array_flatten($dates);
}
/**
* Get next recurring date
*
* @param string $base
* @param integer $interval
* @return array
*/
protected function calculateNextDate($base, $interval)
{
list($year, $month, $day) = $this->toArray($base);
$nextMonth = $month + $interval;
if ($nextMonth > Carbon::MONTHS_PER_YEAR) {
$nextMonth = $nextMonth - Carbon::MONTHS_PER_YEAR;
$year = $year+1;
}
return array($year, (string) $nextMonth, '1');
}
/**
* Convert MySQL DateTime format to array
*
* @param string $date
* @param string $seperator
* @return array
*/
protected function toArray($date, $seperator = '-')
{
$dates = explode($seperator, $date);
return $dates;
}
/**
* Convert date string to Carbon object
*
* @param string $date
* @return Carbon\Carbon
*/
protected function toCarbon($date)
{
$carbon = Carbon::createFromTimestamp(strtotime($date));
return $carbon;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment