spatie / period

Complex period comparisons
https://spatie.be/open-source
MIT License
1.6k stars 72 forks source link

Carry over exclusion #75

Closed ameenross closed 3 years ago

ameenross commented 3 years ago

At first I thought this was an off by one error, but it's not quite. It's just a nasty gotcha because the boundary exclusions are not carried over. Here's code with the problem.

// Period for entire month of January.
$january = new Period(
    new DateTimeImmutable('2021-01-01'),
    new DateTimeImmutable('2021-02-01'),
    Precision::SECOND,
    Boundaries::EXCLUDE_END
);

// Remove something.
$firstPartOfJanuary = $january->diff(new Period(
    new DateTimeImmutable('2021-01-22'),
    new DateTimeImmutable('2021-02-01'),
    Precision::SECOND,
    Boundaries::EXCLUDE_END
))[0];

// Now I'm expecting end to be 2021-01-22 0:00. It isn't:
$firstPartOfJanuary->getEnd()->format('c'); // 2021-01-21T23:59:59+01:00

// That is because:
$firstPartOfJanuary->endExcluded(); // false

I'm expecting the end to be excluded, as both input periods have EXCLUDE_END...

brendt commented 3 years ago

Ah yes, good catch; thanks for reporting! Do you want to submit a bugfix yourself? Otherwise I'll look at this somewhere next week.

ameenross commented 3 years ago

I don't think I will be able to soon. However, thinking about this again, I think the way the boundaries are programmed means resulting periods should have boundary inclusion/exclusion depending on more factors. Basically, a period has 2 boundaries, and if one of a boundary is not included, it needs to be included in the period before or after that. So say We have this (standard interval notation, square bracket is inclusive, parenthesis is exclusive):

// ----------[     )------
// ----------------(-----]

Then there is really a "gap" between these periods in the form of a single moment in time. Or in other words, they nearly touch. So if you want to get the gap between two periods, here's what should happen:

// A:   ----------[     )----------
// B:   ---------------------[----)
// GAP: ----------------[----)-----

By the same token:

// A:   ----------[     ]----------
// B:   ---------------------[----]
// GAP: ----------------(----)-----
brendt commented 3 years ago

We'll continue this conversation in #80, it'll be fixed in v2.