У меня есть такой код:
private function validatePeriodArrayYear()
{
$this->time->setTimestamp( self::$data['to'] );
$year1 = $this->time->format('Y');
$this->time->setTimestamp( self::$data['from'] );
$year2 = $this->time->format('Y');
$overlap = $year1 - $year2;
if( $overlap > 0 ){
$end = clone $this->time;
$end->setTimestamp( self::$data['to'] );
$overlap++;
$interval = new DateInterval('P1Y');
$period = new DatePeriod( $this->time, $interval, $end );
var_dump($period);
$iteration = -1;
foreach( $period as $onePeriod ){
var_dump($onePeriod);
$iteration++;
if( $iteration > 0 ){
$onePeriod->setDate( $onePeriod->format('Y'), 1, 1 );
}
$from = $onePeriod->getTimestamp();
$onePeriod->setDate( $onePeriod->format('Y'), 12, 31 );
$onePeriod->setTime( 23, 59, 59 );
self::$data['zone'][$iteration] = array( 'from' => $from, 'to' => $onePeriod->getTimestamp() );
}
self::$data['zone'][$iteration]['to'] = self::$data['to'];
} else {
self::$data['zone'][] = array( 'from' => self::$data['from'], 'to' => self::$data['to'] );
}
}
Переменные
$this->time = new DateTime(),
self::$data['from'] = 1354316400,
self::$data['to'] = 1389653999
Выходная функция var_dump() выглядит следующим образом:
<pre>
object(DatePeriod)[337]
public start =>
object(DateTime)[336]
public date => string 2012-12-01 00:00:00 (length=19)
public timezone_type => int 3
public timezone => string Europe/Prague (length=13)
public current => null
public end =>
object(DateTime)[48]
public date => string 2014-01-13 23:59:59 (length=19)
public timezone_type => int 3
public timezone => string Europe/Prague (length=13)
public interval =>
object(DateInterval)[331]
public y => int 1
public m => int 0
public d => int 0
public h => int 0
public i => int 0
public s => int 0
public weekday => int 0
public weekday_behavior => int 0
public first_last_day_of => int 0
public invert => int 0
public days => boolean false
public special_type => int 0
public special_amount => int 0
public have_weekday_relative => int 0
public have_special_relative => int 0
public recurrences => int 1
public include_start_date => boolean true
object(DateTime)[326]
public date => string 2012-12-01 00:00:00 (length=19)
public timezone_type => int 3
public timezone => string Europe/Prague (length=13)
object(DateTime)[47]
public date => string 2013-12-01 00:00:00 (length=19)
public timezone_type => int 3
public timezone => string Europe/Prague (length=13)
После выполнения код сохраняется в переменной self::$data['zone']
вот так:
array (size=2)
0 =>
array (size=2)
from => int 1354316400
to => int 1356994799
1 =>
array (size=2)
from => int 1356994800
to => int 1389653999
преобразовано в даты:
01.12.2012 - 31.12.2012
01.01.2013 - 13.01.2014
Теперь, пожалуйста, поправьте меня, если это не будет генерировать это, и где ошибка в данном случае:
01.12.2012 - 31.12.2012
01.01.2013 - 31.12.2013
01.01.2014 - 13.01.2014
Дополнительная информация
$ php -v
PHP 5.5.6-1+debphp.org~raring+2 (cli) (built: Nov 21 2013 14:39:09)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2013 Zend Technologies
with Zend OPcache v7.0.3-dev, Copyright (c) 1999-2013, by Zend Technologies
with Xdebug v2.2.3, Copyright (c) 2002-2013, by Derick Rethans
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 13.10
Release: 13.10
Codename: saucy
$ uname -a
Linux userName-K55VJ 3.11.0-15-generic #23-Ubuntu SMP Mon Dec 9 18:17:04 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
Спасибо за ответы.
Редактировать
@Glavic: спасибо за информацию, теперь я полностью понимаю
Меня поразило, что если начальный и конечный год были одинаковыми, а я менял только месяцы или дни в этом году, то это иногда приводило к правильному результату, а иногда отсутствовало последний год.
Поэтому позвольте мне еще немного разобрать проблему.
Для пояснения я буду использовать другие входные переменные для лучшего понимания.
Переменные
self::$data['from'] = 1354316400 //1.12.2012 00:00:00
self::$data['to'] = 1417388400 //1.12.2014 00:00:00
Обратите внимание, что в self::$data['to']
не хватает одной секунды, потому что разница составила более 3 лет.
Код
$start = new DateTime()->setTimestamp( self::$data['from'] );
$end = new DateTime()->setTimestamp( self::$data['to'] );
$interval = new DateInterval('P1Y');
$period = new DatePeriod( $start, $interval, $end );
foreach( $period as $onePeriod ){
var_dump($onePeriod);
}
Выход
object(DateTime)
public date => string 2012-12-01 00:00:00 (length=19)
public timezone_type => int 3
public timezone => string Europe/Prague (length=13)
object(DateTime)
public date => string 2013-12-01 00:00:00 (length=19)
public timezone_type => int 3
public timezone => string Europe/Prague (length=13)
В этом случае внутри класса DatePeriod
создаются три даты:
2012-12-01 00:00:00
2013-12-01 00:00:00
2014-12-01 00 :00:00
Но последняя дата удалена, поэтому класс возвращает только два объекта DateTime
.
Теперь добавляем секунду к переменной self::$data['to']
и снова запускаем код.
Переменная
self::$data['from'] = 1354316400 //1.12.2012 00:00:00
self::$data['to'] = 1417388401 //1.12.2014 00:00:01
Выход
object(DateTime)
public date => string 2012-12-01 00:00:00 (length=19)
public timezone_type => int 3
public timezone => string Europe/Prague (length=13)
object(DateTime)
public date => string 2013-12-01 00:00:00 (length=19)
public timezone_type => int 3
public timezone => string Europe/Prague (length=13)
object(DateTime)
public date => string 2014-12-01 00:00:00 (length=19)
public timezone_type => int 3
public timezone => string Europe/Prague (length=13)
В этом случае внутри класса DatePeriod
создаются четыре даты:
2012-12-01 00:00:00
2013-12-01 00:00:00
2014-12-01 00 :00:00
01.12.2014 00:00:01
Последняя дата снова удалена.
Математически выраженный
{ x | a ≤ x < b }
a = дата начала
b = дата окончания
инициализировано x равно a
тогда создание каждого периода равно
x = x + период (в моем случае P1Y принадлежит {365 366})