Upstream spatie/period state of the touched files before b1e3380fb0
This commit is contained in:
commit
5e077c8688
3 files changed
+355
No files matched your search
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
namespace Spatie\Period\PeriodTraits;
|
||||
|
||||
use DateTimeImmutable;
|
||||
use Spatie\Period\Boundaries;
|
||||
use Spatie\Period\Exceptions\CannotCeilLowerPrecision;
|
||||
use Spatie\Period\PeriodDuration;
|
||||
use Spatie\Period\Precision;
|
||||
|
||||
/** @mixin \Spatie\Period\Period */
|
||||
trait PeriodGetters
|
||||
{
|
||||
protected string $asString;
|
||||
|
||||
public function isStartIncluded(): bool
|
||||
{
|
||||
return $this->boundaries->startIncluded();
|
||||
}
|
||||
|
||||
public function isStartExcluded(): bool
|
||||
{
|
||||
return $this->boundaries->startExcluded();
|
||||
}
|
||||
|
||||
public function isEndIncluded(): bool
|
||||
{
|
||||
return $this->boundaries->endIncluded();
|
||||
}
|
||||
|
||||
public function isEndExcluded(): bool
|
||||
{
|
||||
return $this->boundaries->endExcluded();
|
||||
}
|
||||
|
||||
public function start(): DateTimeImmutable
|
||||
{
|
||||
return $this->start;
|
||||
}
|
||||
|
||||
public function includedStart(): DateTimeImmutable
|
||||
{
|
||||
return $this->includedStart;
|
||||
}
|
||||
|
||||
public function end(): DateTimeImmutable
|
||||
{
|
||||
return $this->end;
|
||||
}
|
||||
|
||||
public function includedEnd(): DateTimeImmutable
|
||||
{
|
||||
return $this->includedEnd;
|
||||
}
|
||||
|
||||
public function ceilingEnd(?Precision $precision = null): DateTimeImmutable
|
||||
{
|
||||
$precision ??= $this->precision;
|
||||
|
||||
if ($precision->higherThan($this->precision)) {
|
||||
throw CannotCeilLowerPrecision::precisionIsLower($this->precision, $precision);
|
||||
}
|
||||
|
||||
return $this->precision->ceilDate($this->includedEnd, $precision);
|
||||
}
|
||||
|
||||
public function length(): int
|
||||
{
|
||||
// Length of month and year are not fixed, so we can't predict the length without iterate
|
||||
// TODO: maybe we can use cal_days_in_month ?
|
||||
if ($this->precision->equals(Precision::MONTH(), Precision::YEAR())) {
|
||||
return iterator_count($this);
|
||||
}
|
||||
|
||||
if ($this->precision->equals(Precision::HOUR(), Precision::MINUTE(), Precision::SECOND())) {
|
||||
$length = abs($this->includedEnd()->getTimestamp() - $this->includedStart()->getTimestamp());
|
||||
|
||||
if ($this->precision->equals(Precision::SECOND())) {
|
||||
return $length + 1;
|
||||
}
|
||||
|
||||
$length = floor($length / 60);
|
||||
|
||||
if ($this->precision->equals(Precision::MINUTE())) {
|
||||
return $length + 1;
|
||||
}
|
||||
|
||||
return floor($length / 60) + 1;
|
||||
}
|
||||
|
||||
return $this->includedStart()->diff($this->includedEnd())->days + 1;
|
||||
}
|
||||
|
||||
public function duration(): PeriodDuration
|
||||
{
|
||||
return $this->duration;
|
||||
}
|
||||
|
||||
public function precision(): Precision
|
||||
{
|
||||
return $this->precision;
|
||||
}
|
||||
|
||||
public function boundaries(): Boundaries
|
||||
{
|
||||
return $this->boundaries;
|
||||
}
|
||||
|
||||
public function asString(): string
|
||||
{
|
||||
if (! isset($this->asString)) {
|
||||
$this->asString = $this->resolveString();
|
||||
}
|
||||
|
||||
return $this->asString;
|
||||
}
|
||||
|
||||
private function resolveString(): string
|
||||
{
|
||||
$string = '';
|
||||
|
||||
if ($this->isStartIncluded()) {
|
||||
$string .= '[';
|
||||
} else {
|
||||
$string .= '(';
|
||||
}
|
||||
|
||||
$string .= $this->start()->format($this->precision->dateFormat());
|
||||
|
||||
$string .= ',';
|
||||
|
||||
$string .= $this->end()->format($this->precision->dateFormat());
|
||||
|
||||
if ($this->isEndIncluded()) {
|
||||
$string .= ']';
|
||||
} else {
|
||||
$string .= ')';
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
use Spatie\Period\Boundaries;
|
||||
use Spatie\Period\Period;
|
||||
|
||||
it('exclude none', function () {
|
||||
$period = Period::make('2018-01-01', '2018-01-31', boundaries: Boundaries::EXCLUDE_NONE());
|
||||
|
||||
expect($period->isStartExcluded())->toBeFalse();
|
||||
expect($period->isEndExcluded())->toBeFalse();
|
||||
});
|
||||
|
||||
it('exclude start', function () {
|
||||
$period = Period::make('2018-01-01', '2018-01-31', boundaries: Boundaries::EXCLUDE_START());
|
||||
|
||||
expect($period->isStartExcluded())->toBeTrue();
|
||||
expect($period->isEndExcluded())->toBeFalse();
|
||||
});
|
||||
|
||||
it('exclude end', function () {
|
||||
$period = Period::make('2018-01-01', '2018-01-31', boundaries: Boundaries::EXCLUDE_END());
|
||||
|
||||
expect($period->isStartExcluded())->toBeFalse();
|
||||
expect($period->isEndExcluded())->toBeTrue();
|
||||
});
|
||||
|
||||
it('exclude all', function () {
|
||||
$period = Period::make('2018-01-01', '2018-01-31', boundaries: Boundaries::EXCLUDE_ALL());
|
||||
|
||||
expect($period->isStartExcluded())->toBeTrue();
|
||||
expect($period->isEndExcluded())->toBeTrue();
|
||||
});
|
||||
|
||||
it('length with boundaries', function ($expectedAmount, Period $period) {
|
||||
expect($period->length())->toEqual($expectedAmount);
|
||||
})->with('periods_with_amounts_of_included_dates');
|
||||
|
||||
it('overlap with excluded boundaries', function () {
|
||||
$a = Period::make('2018-01-01', '2018-01-05', boundaries: Boundaries::EXCLUDE_END());
|
||||
$b = Period::make('2018-01-05', '2018-01-10');
|
||||
expect($a->overlapsWith($b))->toBeFalse();
|
||||
|
||||
$a = Period::make('2018-01-01', '2018-01-05');
|
||||
$b = Period::make('2018-01-05', '2018-01-10', boundaries: Boundaries::EXCLUDE_START());
|
||||
expect($a->overlapsWith($b))->toBeFalse();
|
||||
|
||||
$a = Period::make('2018-01-01', '2018-01-05');
|
||||
$b = Period::make('2018-01-05', '2018-01-10');
|
||||
expect($a->overlapsWith($b))->toBeTrue();
|
||||
});
|
||||
|
||||
it('subtract with boundaries', function (string $period, string $subtract, string $result) {
|
||||
expect(Period::fromString($period)->subtract(Period::fromString($subtract))[0]->asString())->toEqual($result);
|
||||
})->with('boundaries_for_subtract');
|
||||
|
||||
it('overlap with boundaries', function (string $period, string $overlap, string $result) {
|
||||
expect(Period::fromString($period)->overlap(Period::fromString($overlap))->asString())->toEqual($result);
|
||||
})->with('boundaries_for_overlap');
|
||||
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Spatie\Period\Boundaries;
|
||||
use Spatie\Period\Period;
|
||||
use Spatie\Period\Precision;
|
||||
|
||||
dataset('overlapping_dates', function () {
|
||||
/*
|
||||
* A [=====]
|
||||
* B [=====]
|
||||
*/
|
||||
yield [Period::make('2018-01-01', '2018-02-01'), Period::make('2018-01-15', '2018-02-15')];
|
||||
|
||||
/*
|
||||
* A [=====]
|
||||
* B [=============]
|
||||
*/
|
||||
yield [Period::make('2018-01-01', '2018-02-01'), Period::make('2017-01-01', '2019-01-01')];
|
||||
|
||||
/*
|
||||
* A [=====]
|
||||
* B [=====]
|
||||
*/
|
||||
yield [Period::make('2018-01-01', '2018-02-01'), Period::make('2017-12-01', '2018-01-15')];
|
||||
|
||||
/*
|
||||
* A [=============]
|
||||
* B [=====]
|
||||
*/
|
||||
yield [Period::make('2017-01-01', '2019-01-01'), Period::make('2018-01-01', '2018-02-01')];
|
||||
|
||||
/*
|
||||
* A [====]
|
||||
* B [====]
|
||||
*/
|
||||
yield [Period::make('2018-01-01', '2018-02-01'), Period::make('2018-01-01', '2018-02-01')];
|
||||
});
|
||||
|
||||
dataset('no_overlapping_dates', function () {
|
||||
/*
|
||||
* A [===]
|
||||
* B [===]
|
||||
*/
|
||||
yield [Period::make('2018-01-01', '2018-01-31'), Period::make('2018-02-01', '2018-02-28')];
|
||||
|
||||
/*
|
||||
* A [===]
|
||||
* B [===]
|
||||
*/
|
||||
yield [Period::make('2018-02-01', '2018-02-28'), Period::make('2018-01-01', '2018-01-31')];
|
||||
});
|
||||
|
||||
dataset('periods_with_amounts_of_included_dates', function () {
|
||||
yield [4, Period::make('2016-01-01', '2019-02-05', Precision::YEAR(), Boundaries::EXCLUDE_NONE())];
|
||||
yield [3, Period::make('2016-01-01', '2019-02-05', Precision::YEAR(), Boundaries::EXCLUDE_START())];
|
||||
yield [3, Period::make('2016-01-01', '2019-02-05', Precision::YEAR(), Boundaries::EXCLUDE_END())];
|
||||
yield [2, Period::make('2016-01-01', '2019-02-05', Precision::YEAR(), Boundaries::EXCLUDE_ALL())];
|
||||
|
||||
yield [43, Period::make('2016-01-01', '2019-07-05', Precision::MONTH(), Boundaries::EXCLUDE_NONE())];
|
||||
yield [42, Period::make('2016-01-01', '2019-07-05', Precision::MONTH(), Boundaries::EXCLUDE_START())];
|
||||
yield [42, Period::make('2016-01-01', '2019-07-05', Precision::MONTH(), Boundaries::EXCLUDE_END())];
|
||||
yield [41, Period::make('2016-01-01', '2019-07-05', Precision::MONTH(), Boundaries::EXCLUDE_ALL())];
|
||||
|
||||
yield [31, Period::make('2018-01-01', '2018-01-31', boundaries: Boundaries::EXCLUDE_NONE())];
|
||||
yield [30, Period::make('2018-01-01', '2018-01-31', boundaries: Boundaries::EXCLUDE_START())];
|
||||
yield [30, Period::make('2018-01-01', '2018-01-31', boundaries: Boundaries::EXCLUDE_END())];
|
||||
yield [29, Period::make('2018-01-01', '2018-01-31', boundaries: Boundaries::EXCLUDE_ALL())];
|
||||
|
||||
yield [24, Period::make('2018-01-01 00:00:00', '2018-01-01 23:59:00', Precision::HOUR(), Boundaries::EXCLUDE_NONE())];
|
||||
yield [23, Period::make('2018-01-01 00:00:00', '2018-01-01 23:59:00', Precision::HOUR(), Boundaries::EXCLUDE_START())];
|
||||
yield [23, Period::make('2018-01-01 00:00:00', '2018-01-01 23:59:00', Precision::HOUR(), Boundaries::EXCLUDE_END())];
|
||||
yield [22, Period::make('2018-01-01 00:00:00', '2018-01-01 23:59:00', Precision::HOUR(), Boundaries::EXCLUDE_ALL())];
|
||||
|
||||
yield [1440, Period::make('2018-01-01 00:00:00', '2018-01-01 23:59:22', Precision::MINUTE(), Boundaries::EXCLUDE_NONE())];
|
||||
yield [1439, Period::make('2018-01-01 00:00:00', '2018-01-01 23:59:22', Precision::MINUTE(), Boundaries::EXCLUDE_START())];
|
||||
yield [1439, Period::make('2018-01-01 00:00:00', '2018-01-01 23:59:22', Precision::MINUTE(), Boundaries::EXCLUDE_END())];
|
||||
yield [1438, Period::make('2018-01-01 00:00:00', '2018-01-01 23:59:22', Precision::MINUTE(), Boundaries::EXCLUDE_ALL())];
|
||||
|
||||
yield [86363, Period::make('2018-01-01 00:00:00', '2018-01-01 23:59:22', Precision::SECOND(), Boundaries::EXCLUDE_NONE())];
|
||||
yield [86362, Period::make('2018-01-01 00:00:00', '2018-01-01 23:59:22', Precision::SECOND(), Boundaries::EXCLUDE_START())];
|
||||
yield [86362, Period::make('2018-01-01 00:00:00', '2018-01-01 23:59:22', Precision::SECOND(), Boundaries::EXCLUDE_END())];
|
||||
yield [86361, Period::make('2018-01-01 00:00:00', '2018-01-01 23:59:22', Precision::SECOND(), Boundaries::EXCLUDE_ALL())];
|
||||
});
|
||||
|
||||
dataset('ceiling_dates', function () {
|
||||
// Test inclusive Period's at same precision
|
||||
yield [
|
||||
Period::make('2018-01-01 11:30:15', '2018-01-15 11:30:15', Precision::SECOND()),
|
||||
Precision::SECOND(),
|
||||
Carbon::make('2018-01-15 11:30:15')->endOfSecond(),
|
||||
];
|
||||
|
||||
yield [
|
||||
Period::make('2018-01-01 11:30:15', '2018-01-15 11:30:15', Precision::MINUTE()),
|
||||
Precision::MINUTE(),
|
||||
Carbon::make('2018-01-15 11:30:15')->endOfMinute(),
|
||||
];
|
||||
|
||||
yield [
|
||||
Period::make('2018-01-01 11:30:15', '2018-01-15 11:30:15', Precision::HOUR()),
|
||||
Precision::HOUR(),
|
||||
Carbon::make('2018-01-15 11:30:15')->endOfHour(),
|
||||
];
|
||||
|
||||
yield [
|
||||
Period::make('2018-01-01', '2018-01-15', Precision::DAY()),
|
||||
Precision::DAY(),
|
||||
Carbon::make('2018-01-15')->endOfDay(),
|
||||
];
|
||||
|
||||
yield [
|
||||
Period::make('2018-01-01', '2018-01-15', Precision::MONTH()),
|
||||
Precision::MONTH(),
|
||||
Carbon::make('2018-01-15')->endOfMonth(),
|
||||
];
|
||||
|
||||
yield [
|
||||
Period::make('2018-01-01', '2018-01-15', Precision::YEAR()),
|
||||
Precision::YEAR(),
|
||||
Carbon::make('2018-01-15')->endOfYear(),
|
||||
];
|
||||
|
||||
// Test defaults to same precision as period
|
||||
yield [
|
||||
Period::make('2018-01-01', '2018-01-15', Precision::MONTH()),
|
||||
null,
|
||||
Carbon::make('2018-01-15')->endOfMonth(),
|
||||
];
|
||||
|
||||
// Test higher precision
|
||||
yield [
|
||||
Period::make('2018-01-01', '2018-01-15', Precision::DAY()),
|
||||
Precision::MONTH(),
|
||||
Carbon::make('2018-01-15')->endOfMonth(),
|
||||
];
|
||||
|
||||
// Test exclusive period
|
||||
yield [
|
||||
Period::make('2018-01-01', '2018-01-15', Precision::DAY(), Boundaries::EXCLUDE_END()),
|
||||
Precision::DAY(),
|
||||
Carbon::make('2018-01-15')->subDay()->endOfDay(),
|
||||
];
|
||||
});
|
||||
|
||||
dataset('rounding_dates', function () {
|
||||
return [
|
||||
[Precision::YEAR(), '2018-01-01 00:00:00', '2018-01-01 00:00:00'],
|
||||
[Precision::MONTH(), '2018-02-01 00:00:00', '2018-03-01 00:00:00'],
|
||||
[Precision::DAY(), '2018-02-05 00:00:00', '2018-03-05 00:00:00'],
|
||||
[Precision::HOUR(), '2018-02-05 11:00:00', '2018-03-05 11:00:00'],
|
||||
[Precision::MINUTE(), '2018-02-05 11:11:00', '2018-03-05 11:11:00'],
|
||||
[Precision::SECOND(), '2018-02-05 11:11:11', '2018-03-05 11:11:11'],
|
||||
];
|
||||
});
|
||||
Reference in new issue
Block a user