You need to do calculations of time-ranges. As the image shows this seems like a simple subtraction. It would be nice to just have objects that do these.
I had no code for this ready, so the following concept is a bit rough although probably not that bad.
A Range
type that represents a time from-to. Those are as DateTime
so that the benefits of these existing types can be used. I didn't use much of the benefits so far, however for the rest of the application this can make sense.
The Range
type already contains some basic comparison methods I thought were useful to do parts of the calculations.
However as an object can not divide itself into two I also created a Ranges
type which can represent one or more Range
s. This was necessary to have something that can be "divided".
I cheated a little here because I implemented the difference calculation as a member of Range
, returning an array with one or multiple Range
objects. The final calculation then is just having a shift and substract the unavailable ranges from it:
$shift = new Ranges(new DateTime('14:30:00'), new DateTime('18:30:00'));
$unavailables = new Ranges([
new Range(new DateTime('15:30:00'), new DateTime('16:30:00')),
new Range(new DateTime('17:30:00'), new DateTime('18:30:00')),
]);
$shift->subtract($unavailables);
The shift then spans:
14:30:00 - 15:30:00
16:30:00 - 17:30:00
Demo; Gist
I can not say if it is worth the abstraction, what is nice with DateTime
objects is that you can compare them with >
, <
and =
. The real benefit from these classes might shed into light when you need more calculations between Range and Ranges. Maybe the interface is not sweet yet, however the basic calculations behind are outlined in the code already.
One caveat: The difference between 14:00-15:00
and 14:00-15:00
in my code will result to 14:00-14:00
. I keep the start time to not run empty, but you can run empty, too. The Ranges object should handle it nicely.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…