1

suppose I have an initial date whose year was prior to that of the current year and I want to repeat the event every 7 days but only in the current year.

How would I find the first occurrence in the current year?

I realize I can do it with a loop like this:

$reOccurringEvent =new DateTime('2013-12-01');
$interval = new DateInterval('P7D');
while($reOccurringEvent->format('Y') < date('Y') ){
    $reOccurringEvent->add($interval);
}
echo $reOccurringEvent->format('d m Y'); //05 01 2014

But it strikes me there should be a more efficient way to achieve this rather than repeatedly adding an interval to the date (it would happen many times if the initial date was some years ago).

I was hoping to be able to calculate the number of times the interval should be added and just do it a single time.

I was thinking something like:

$date = new DateTime();
$diff = $date->diff($reOccurringEvent)->days%7;

But obviously that doesn't work and I can't quite figure out the logic of how to do it.

andrew
  • 9,313
  • 7
  • 30
  • 61

3 Answers3

1

I think, if you are doing 7 day intervals, you can find out the Day of week of your initial date, and then get the first date of the current year with that day of week...

Find out day of week: How to find the day of week from a date using PHP?

Find out date with that day of week for this year: Getting first weekday in a month with strtotime

Putting it together:

$date=Date("2/8/2012");

//Get the day of week for the date in question
$dayOfWeek  = date('l', strtotime($date));
echo "The day of week for the given date is: $dayOfWeek <br>"; 

//Get the current year
$thisYear = date("Y");
echo "This year: $thisYear <br>"; 

//Create a date with the first occurence of the day of week of the given date for the current year
$firstOccurenceThisYear = date("m/d/y", strtotime("January " .$thisYear ." " . $dayOfWeek));
echo "The first interval of the year is: $firstOccurenceThisYear"; 

/*
Output:
This year: 2014 
The day of week for the given date is: Wednesday 
The first interval of the year is: 01/01/14
*/
Community
  • 1
  • 1
Dan
  • 876
  • 5
  • 15
  • The problem with the first method you propose, is catch 22, I don't know the second date to make the comparison that's the date I'm trying to calculate :) The second method looks promising, I'll report back – andrew Oct 21 '14 at 18:29
  • Thanks, I still need to figure out a way to do this when the period is other than 7 days, but I probably should have specified that in the question :) – andrew Oct 21 '14 at 18:43
  • @andrew posted new answer that I think solves the problem more generically – Dan Oct 21 '14 at 19:21
1

More generically, the algorithm would be to find the number of intervals between the given date and the last day of last year. Then multiplying the interval by the number of intervals + 1 to get the first interval of the current year.

$date1="12/9/2013"; 
$ts1 = strtotime($date1);
$ts2 = strtotime("12/31/" . Date("Y")-1);

//get the number of seconds between the date and first of the year    
$seconds_diff = $ts2 - $ts1;
echo "$seconds_diff <br>";

//get the number of days
$dayDiff=$seconds_diff/86400;

//how many intervals?
$intervalDays = "10";

//get the number of intervals from start date to last day of last year
$numIntervals = floor($dayDiff/$intervalDays);
echo  $numIntervals."<br>";

//now the total intervals to get into the current year is one more interval, turn this into days
$totIntervals= ($numIntervals* $intervalDays)+$intervalDays;

//Date Time date in question
$theDt = new DateTime($date1);

//Add the intervals we calculated to the date in question, and we have the first date of the interval for the current year...
$theDt->add(new DateInterval('P' . $totIntervals. 'D'));

echo "The first date of the intreval is: " . $theDt->format('Y-m-d'); 
Dan
  • 876
  • 5
  • 15
1

Here is a slightly modified version of @Dan's second answer which worked well for me.

Benchmarks shown below.

$date="1985-02-18";
$intervalDays = "5";

//original version
$benchMark = microtime(true);
$dt1 = new DateTime($date);
$interval = new DateInterval("P{$intervalDays}D");
while ($dt1->format('Y') < date('Y')) {
    $dt1->add($interval);
}
echo $dt1->format('d m Y') . '<br>';
echo microtime(true)-$benchMark.'<br>';


//new version
$benchMark = microtime(true);
$dt1 = new DateTime($date);
$dt2 = new DateTime("12/31/" . ((int) Date("Y") - 1));
$dayDiff = $dt1->diff($dt2)->days;
$numIntervals = floor($dayDiff / $intervalDays);
$totIntervals = ($numIntervals * $intervalDays) + $intervalDays;
$dt1->add(new DateInterval('P' . $totIntervals . 'D'));
echo $dt1->format('d m Y').'<br>';
echo microtime(true)-$benchMark.'<br>';
exit;

output

02 01 2014
0.0145111083984
02 01 2014
0.000123977661133
andrew
  • 9,313
  • 7
  • 30
  • 61