6

I am trying to determine whether a DateTime exactly coincides with a possible occurance of a DateInterval. The intervals I'm using need to allow for 'Nth Xday of next month' type format specifications and I'm not sure such a thing is possible given those conditions.

My basic idea was to invert the DateInterval, apply it to a clone of the original DateTime, put it back as it was, apply again and then check if the two DateTime instances were equal. If so, it occurs exactly on the interval:

public static function dateFallsOnPeriod(DateTime $date, DateInterval $interval)
{
    $compare = clone $date;

    // invert the period, apply it to the date, uninvert & then reapply
    $interval->invert = 1;
    $compare->add($interval);
    $interval->invert = 0;
    $compare->add($interval);

    return $date == $compare;
}

This seemed to apply the interval twice in the same direction, and so I tried again using ->sub() and ->add(), resulting in a fatal error "DateTime::sub(): Only non-special relative time specifications are supported for subtraction". It seems like this kind of functionality isn't implemented at all.

Does anyone have better ideas, in lieu of the ugly & inefficient solution of choosing an offset well behind the start date and iterating forward until we've matched it or gone past?

thanks in advance!

pospi
  • 3,540
  • 3
  • 27
  • 26
  • 1
    `invert` performs a sub i tested it. your sub and add cancel each other out. it says as checking if $compare == $date in the beginning – DevZer0 Jul 18 '13 at 07:29
  • Could you clearify the question with an example? What confuses me is that your function name indicates that you want to see if a period coincides with a date, but you pass a DateTime and DateInteral into your function, instead of - as I would expect - DateTime and DatePeriod? – luttkens Jul 18 '13 at 20:14
  • I guess the method should be called `dateCoincidesWithInterval` then or something, sorry about that. @DevZer0: The reason adding, subtracting and comparing won't always cancel each other out is due to those special intervals PHP allows. So if your interval was specifying "first sunday of the month" and you passed a Monday as the `$date`, you'd want to know that that first date doesn't fit the interval. For more normal intervals what you are saying is true and the method isn't really needed, but I want to cover every possibility with this one. – pospi Jul 18 '13 at 22:24
  • how do you specify "first sunday of the month" to DateInterval? from what i saw it takes an absolute measurement of an interval not literal strings – DevZer0 Jul 19 '13 at 00:37
  • 1
    @pospi Ok, but then I still feel that there is a confusion around DateInterval and DatePeriod. DateInterval is only a "length" without a start and end date, as oppose to DatePeriod. Therefore it does not make sense to determine if a date coincides with an interval. But with a DatePeriod it makes sense. But I don't think you "just" want to determine if a date falls with a period? From your example "first sunday of month", I get the understanding that you want try to see if a date matches arbitrary criterias like "frist day of month", "3rd hour of the day" or second Wednesday in month".Correct? – luttkens Jul 19 '13 at 06:13
  • Correct! There is definitely more going on natively with DateInterval than is exposed to PHP. Check out [this example](http://au1.php.net/manual/en/class.dateperiod.php#92130) from the DatePeriod user-contributed docs. Such an interval used with a period will give you every last Thursday of the month between the two dates. The issue is when you use such a constructed DateInterval and your start date doesn't coincide with the interval, it still gets included in the DatePeriod anyway. You could use the 'exclude start date' flag, but then you're incorrectly discounting it when it *does* coincide. – pospi Jul 20 '13 at 05:04

2 Answers2

0

One possibility is to generate Unix timestamps from the datetime and compare the integer values.

tuxnani
  • 3,634
  • 6
  • 21
  • 33
0

I agree with tuxnani, it's much easier to convert all dates to unix format with strtotime(), then just compare numeric values with more or less operations.

Community
  • 1
  • 1
ZurabWeb
  • 1,241
  • 1
  • 12
  • 21