Skip to content

Instantly share code, notes, and snippets.

@andrewscaya
Forked from sasin91/DateRange.php
Created November 29, 2018 13:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrewscaya/028e7f5d3c061b86e4d3bb732b1dcb3a to your computer and use it in GitHub Desktop.
Save andrewscaya/028e7f5d3c061b86e4d3bb732b1dcb3a to your computer and use it in GitHub Desktop.
Easily create a collection of dates within range of two dates.
<?php
namespace App\Support;
use ArrayIterator;
use Countable;
use DatePeriod;
use DateTime;
use DateInterval;
use IteratorAggregate;
use Illuminate\Support\Carbon;
class DateRange implements IteratorAggregate, Countable
{
/**
* The start of the date range.
*
* @var \DateTime
*/
protected $starts_at;
/**
* The end of the date range.
*
* @var \DateTime
*/
protected $ends_at;
/**
* The space between the dates.
*
* @var \DateInterval
*/
protected $interval;
/**
* The date format.
*
* @var string
*/
protected $format = 'Y-m-d';
/**
* Key of the dates.
*
* @var string
*/
protected $keyedBy;
/**
* Construct the DateRange.
*
* @param string|null $starts_at [defaults to now.]
* @param string|null $ends_at [defaults to end of year.]
* @param string|null $interval [The interval between each date.]
*/
public function __construct($starts_at = null, $ends_at = null, $interval = null)
{
$this->startsAt($starts_at ?: Carbon::now());
$this->endsAt($ends_at ?: Carbon::now()->endOfYear());
$this->interval($interval ?: '1 day');
}
/**
* Delegate calls to the underlying collection.
*
* @param string $method
* @param array $parameters
* @return mixed | \Illuminate\Support\Collection
*/
public function __call($method, $parameters = [])
{
return $this->create()->$method(...$parameters);
}
/**
* Delegate undefined attributes to the underyling Collection.
*
* @param string $key
* @return mixed
*/
public function __get($key)
{
if (property_exists($this, $key)) {
return $this->$key;
}
return $this->create()->$key;
}
/**
* Assign a key for each of the dates
*
* @param string $key
* @return $this
*/
public function keyedBy(string $key)
{
$this->keyedBy = $key;
return $this;
}
/**
* The date format
*
* @param string $format
* @return $this
*/
public function format(string $format)
{
$this->format = $format;
return $this;
}
/**
* Set the start date
*
* @param string|\DateTime $date
* @return $this
*/
public function startsAt($date)
{
$this->starts_at = Carbon::parse($date);
return $this;
}
/**
* Set the end date
*
* @param string|\DateTime $date
* @return $this
*/
public function endsAt($date)
{
$this->ends_at = Carbon::parse($date);
return $this;
}
/**
* Set the date interval
*
* @param \DateInterval | string $value
* @return $this
*/
public function interval($value)
{
if (is_string($value)) {
$this->interval = DateInterval::createFromDateString($value);
} else {
$this->interval = $value;
}
return $this;
}
/**
* Create the dateRange collection
*
* @return \Illuminate\Support\Collection
*/
public function create()
{
$dates = $this->formatDates($this->dates());
$results = $this->assignKeyToDates($dates);
return collect($results);
}
/**
* Get the raw date array
*
* @return array
*/
public function dates()
{
return iterator_to_array(new DatePeriod($this->starts_at, $this->interval, $this->ends_at));
}
/**
* Get the iterator from the collection
*
* @return \ArrayIterator
*/
public function getIterator()
{
return $this->create()->getIterator();
}
/**
* Count the total number of dates.
*
* @return int
*/
public function count()
{
return count($this->dates());
}
/**
* Format the DateTime objects into strings.
*
* @param array $range
* @return array
*/
protected function formatDates(array $range)
{
if (blank($this->format)) {
return $range;
}
return array_map(function ($date) {
return $date->format($this->format);
}, $range);
}
/**
* Assign the key to each of the dates
*
* @param array $dates
* @return array
*/
protected function assignKeyToDates(array $dates)
{
if (blank($this->keyedBy)) {
return $dates;
}
$results = [];
foreach ($dates as $date) {
$results[] = [$this->keyedBy => $date];
}
return $results;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment