- The DatePeriod class
- Class synopsis
- Predefined Constants
- Properties
- Changelog
- Table of Contents
- User Contributed Notes 11 notes
- Как получить все дни между датами в PHP
- Количество дней между датами
- Формирование массива, содержащий все дни из интервала
- Результат:
- Функция на основе strtotime
- Результат:
- Класс DatePeriod
- Обзор классов
- Предопределённые константы
- Свойства
- Список изменений
- User Contributed Notes 1 note
The DatePeriod class
A date period allows iteration over a set of dates and times, recurring at regular intervals, over a given period.
Class synopsis
Predefined Constants
Properties
The number of recurrences, if the DatePeriod instance had been created by explicitly passing $recurrences . See also DatePeriod::getRecurrences() .
Whether to include the start date in the set of recurring dates or not.
The start date of the period.
During iteration this will contain the current date within the period.
The end date of the period.
An ISO 8601 repeating interval specification.
Changelog
Version | Description |
---|---|
8.0.0 | DatePeriod implements IteratorAggregate now. Previously, Traversable was implemented instead. |
Table of Contents
- DatePeriod::__construct — Creates a new DatePeriod object
- DatePeriod::getDateInterval — Gets the interval
- DatePeriod::getEndDate — Gets the end date
- DatePeriod::getRecurrences — Gets the number of recurrences
- DatePeriod::getStartDate — Gets the start date
User Contributed Notes 11 notes
Just an example to include the end date using the DateTime method ‘modify’
$begin = new DateTime ( ‘2012-08-01’ );
$end = new DateTime ( ‘2012-08-31’ );
$end = $end -> modify ( ‘+1 day’ );
$interval = new DateInterval ( ‘P1D’ );
$daterange = new DatePeriod ( $begin , $interval , $end );
foreach( $daterange as $date ) echo $date -> format ( «Ymd» ) . «
» ;
>
?>
Thanks much to those of you who supplied sample code; that helps a lot.
I wanted to mention another thing that helped me: when you do that foreach ( $period as $dt ), the $dt values are DateTime objects.
That may be obvious to those of you with more experience, but I wasn’t sure until I looked it up on Stack Overflow. So I figured it was worth posting here to help others like me who might’ve been confused or uncertain.
Calculating business days can be cumbersome. Here is an iterator for handling business days. Usage examples below for adding # of business days and calculating how many business days between two dates.
Counting # of Business Days between two dates
function countBusinessDays ( $start , $stop )
if( $start > $stop ) $tmpStart = clone $start ;
$start = clone $stop ;
$stop = clone $tmpStart ;
>
// Adding the time to the end date will include it
$period = new \ DatePeriod ( $start -> setTime ( 0 , 0 , 0 ), new \ DateInterval ( ‘P1D’ ), $stop -> setTime ( 23 , 59 , 59 ), \ DatePeriod :: EXCLUDE_START_DATE );
$periodIterator = new BusinessDayPeriodIterator ( $period );
$businessDays = 0 ;
while( $periodIterator -> valid ()) // If we run into a weekend, don’t count it
if(! $periodIterator -> isWeekend ()) $businessDays ++;
>
$periodIterator -> next ();
>
return $businessDays ;
>
?>
Add # of business days
function addBusinessDays (\ DateTime $startDateTime , $daysToAdd )
$endDateTime = clone $startDateTime ;
$endDateTime -> add (new \ DateInterval ( ‘P’ . $daysToAdd . ‘D’ ))-> setTime ( 23 , 59 , 59 );
$period = new \ DatePeriod ( $startDateTime , new \ DateInterval ( ‘P1D’ ), $endDateTime );
$periodIterator = new BusinessDayPeriodIterator ( $period );
$adjustedEndingDate = clone $startDateTime ;
while( $periodIterator -> valid ()) $adjustedEndingDate = $periodIterator -> current ();
// If we run into a weekend, extend our days
if( $periodIterator -> isWeekend ()) $periodIterator -> extend ();
>
$periodIterator -> next ();
>
When looping over a DatePeriod object, the returned objects always implement DateTimeInterface. The exact type returned depends on how the DatePeriod was created. If $start was a DateTimeImmutable, the objects returned will be of type DateTimeImmutable. If a DateTime object was used, the objects returned will be of type DateTime.
The iterator seems to check the time as well, it excludes the end element if its time is 00:00:00. So the slightly safer version (to compare it against joshs suggestion) is to use $date->setTime(23, 59, 59) instead of $date->modify(«+1 day»).
Nice example from PHP Spring Conference (thanks to Johannes Schlüter and David Zülke)
$begin = new DateTime ( ‘2007-12-31’ );
$end = new DateTime ( ‘2009-12-31 23:59:59’ );
$interval = DateInterval :: createFromDateString ( ‘last thursday of next month’ );
$period = new DatePeriod ( $begin , $interval , $end , DatePeriod :: EXCLUDE_START_DATE );
foreach ( $period as $dt )
echo $dt -> format ( «l Y-m-d H:i:s\n» );
?>
DateInterval specs could be found at http://en.wikipedia.org/wiki/ISO_8601#Time_intervals
DatePeriod is not compatible with negative intervals.
To do so you can simply use DateInterval and loop through it yourself like this: (not start should be ahead of end if you use a negative interval
class DateRange extends ArrayIterator
protected $oDate = null;
protected $oStartDate = null;
protected $oEndDate = null;
protected $oInterval = null;
public function __construct( DateTime $oStartDate, DateTime $oEndDate, DateInterval $oInterval = null )
$this->oStartDate = $oStartDate;
$this->oDate = clone $oStartDate;
$this->oEndDate = $oEndDate;
$this->oInterval = $oInterval;
>
public function next()
$this->oDate->add($this->oInterval);
return $this->oDate;
>
public function current()
return $this->oDate;
>
public function valid()
if ($this->oStartDate > $this->oEndDate)
return $this->oDate >= $this->oEndDate;
>
return $this->oDate oEndDate;
>
$oRange = new DateRange(new DateTime(«2013-10-01»), new DateTime(«2013-01-01»), DateInterval::createFromDateString(«-1 month») );
foreach ($oRange as $oDate)
echo $oDate->format(«Y-m-d») . «
«;
>
If you want to include the end-date, add one day to it:
$startDate = new DateTime ();
$endDate = new DateTime ();
$startDateInt = new DateInterval ( «P1Y» );
$endDateInt = new DateInterval ( «P1D» );
$startDate -> sub ( $startDateInt );
$endDate -> add ( $endDateInt );
$periodInt = new DateInterval ( «P1M» );
$period = new DatePeriod ( $startDate , $periodInt , $endDate );
// At februari 2011:
// $period = (8,9,10,11,12,1,2)
?>
This class isn’t always intuitive. End is exclusive. All you need to do to include it is to add a second (the smallest amount).
php -r ‘
/***/$p1d = new DateInterval(«P1D»);
/***/$b = (new DateTime())->setTime(0, 0, 0, 0);
/***/$a = (clone $b)->sub($p1d);
It is a sign of the end times.
An extra piece of information on how to use the (modify method) to easily get date ranges:
$subscription_start_date = new DateTime ( ‘now’ );
// Modify the $subscription_start_date date value to required date range,
// this could be in days or months depending on how your application is designed
// Days
$subscription_expiration = $subscription_start_date -> modify ( ‘+60 days’ );
echo $subscription_expiration -> format ( ‘Y-m-d’ ) . «\n» ;
// Months
$subscription_expiration = $subscription_start_date -> modify ( ‘+2 Months’ );
echo $subscription_expiration -> format ( ‘Y-m-d’ ) . «\n» ;
// Or even in years
$subscription_expiration = $subscription_start_date -> modify ( ‘+2 years’ );
echo $subscription_expiration -> format ( ‘Y-m-d’ ) . «\n» ;
?>
As someone noted, at least in 7.2, dates with time 0 are excluded from the start and end.
To get a regular span of dates I ended up with:
$dates = new DatePeriod(
( new DateTime($date_start) )->setTime(0,0,1),
new DateInterval(‘P1D’),
( new DateTime($date_end) )->setTime(0,0,1)
);
- Date/Time
- Introduction
- Installing/Configuring
- Predefined Constants
- Examples
- DateTime
- DateTimeImmutable
- DateTimeInterface
- DateTimeZone
- DateInterval
- DatePeriod
- Date/Time Functions
- Supported Date and Time Formats
- List of Supported Timezones
Как получить все дни между датами в PHP
Несколько примеров как найти все дни в промежутке между двумя датами в виде значения и списка.
Количество дней между датами
$date_1 = '28.03.2022 00:00'; $date_2 = '02.04.2022 23:59'; $seconds = abs(strtotime($date_1) - strtotime($date_2)); echo round($seconds / 86400, 1); // 6
$date_1 = '28.03.2022 00:00'; $date_2 = '02.04.2022 18:00'; $seconds = abs(strtotime($date_1) - strtotime($date_2)); echo round($seconds / 86400, 1); // 5.6
Формирование массива, содержащий все дни из интервала
Первый способ – использование классов DatePeriod, DateTime и DateInterval (доступны с версии PHP 5.3).
* Если в конечной дате не указать время (23:59), то в результирующем массиве не будет последнего дня.
$period = new DatePeriod( new DateTime('28.03.2022'), new DateInterval('P1D'), new DateTime('02.04.2022 23:59') ); $dates = array(); foreach ($period as $key => $value) < $dates[] = $value->format('d.m.Y'); > print_r($dates);
Результат:
Array ( [0] => 28.03.2022 [1] => 29.03.2022 [2] => 30.03.2022 [3] => 31.03.2022 [4] => 01.04.2022 [5] => 02.04.2022 )
Функция на основе strtotime
function get_dates($start, $end, $format = 'd.m.Y') < $day = 86400; $start = strtotime($start . ' -1 days'); $end = strtotime($end . ' +1 days'); $nums = round(($end - $start) / $day); $days = array(); for ($i = 1; $i < $nums; $i++) < $days[] = date($format, ($start + ($i * $day))); >return $days; > $dates = get_dates('28.03.2022', '02.04.2022'); print_r($dates);
Результат:
Array ( [0] => 28.03.2022 [1] => 29.03.2022 [2] => 30.03.2022 [3] => 31.03.2022 [4] => 01.04.2022 [5] => 02.04.2022 )
Класс DatePeriod
Позволяет перемещаться в заданном временном интервале на равные промежутки времени.
Обзор классов
Предопределённые константы
Исключает начальную дату, используется в DatePeriod::__construct() .
DatePeriod::INCLUDE_END_DATE
Включает дату окончания, используется в DatePeriod::__construct() .
Свойства
Минимальное количество экземпляров, возвращаемое итератором.
Если количество повторений было явно передано с помощью параметра recurrences в конструктор экземпляра DatePeriod , то это свойство содержит это значение, плюс один, если дата начала не была отключена с помощью константы DatePeriod::EXCLUDE_START_DATE , плюс один, если дата окончания была включена с помощью константы DatePeriod::INCLUDE_END_DATE .
Если количество повторений не было передано явно, то это свойство содержит минимальное количество возвращённых экземпляров. Это будет 0 , плюс один, если дата начала не отключена с помощью константы DatePeriod::EXCLUDE_START_DATE , плюс один, если дата окончания была включена с помощью константы DatePeriod::INCLUDE_END_DATE .
$start = new DateTime ( ‘2018-12-31 00:00:00’ );
$end = new DateTime ( ‘2021-12-31 00:00:00’ );
$interval = new DateInterval ( ‘P1M’ );
$recurrences = 5 ;?php
// повторения явно задаются в конструкторе
$period = new DatePeriod ( $start , $interval , $recurrences , DatePeriod :: EXCLUDE_START_DATE );
echo $period -> recurrences , «\n» ;$period = new DatePeriod ( $start , $interval , $recurrences );
echo $period -> recurrences , «\n» ;$period = new DatePeriod ( $start , $interval , $recurrences , DatePeriod :: INCLUDE_END_DATE );
echo $period -> recurrences , «\n» ;// повторения не заданы в конструкторе
$period = new DatePeriod ( $start , $interval , $end );
echo $period -> recurrences , «\n» ;$period = new DatePeriod ( $start , $interval , $end , DatePeriod :: EXCLUDE_START_DATE );
echo $period -> recurrences , «\n» ;
?>Результат выполнения данного примера:
Включать ли дату окончания в набор повторяющихся дат или нет.
Включать ли начальную дату в набор дат или нет.
В процессе итерации будет содержать текущую дату периода.
Спецификация повторяющегося интервала согласно ISO 8601.
Список изменений
Версия Описание 8.2.0 Были добавлены константа DatePeriod::INCLUDE_END_DATE и свойство include_end_date . 8.0.0 Класс DatePeriod теперь реализует интерфейс IteratorAggregate . Ранее вместо этого был реализован интерфейс Traversable . User Contributed Notes 1 note
When looping over a DatePeriod object, the returned objects always implement DateTimeInterface. The exact type returned depends on how the DatePeriod was created. If $start was a DateTimeImmutable, the objects returned will be of type DateTimeImmutable. If a DateTime object was used, the objects returned will be of type DateTime.
- Дата/время
- Введение
- Установка и настройка
- Предопределённые константы
- Примеры
- DateTime
- DateTimeImmutable
- DateTimeInterface
- DateTimeZone
- DateInterval
- DatePeriod
- Функции даты и времени
- Допустимые форматы даты/времени
- Список поддерживаемых часовых поясов