2

I am using the following lines to calculate a 4-week interval in PHP. This uses a fixed date ($calStart) as basis for the calculation and ends the interval with the last day of the selected year ($rangeEnd / $selYear) which works well so far.

Example: If the selected year is 2015 than the first date in my range here should be 2015-01-16 as the first interval date in the selected year.

Can someone here tell me how I can set this so that $rangeDays only starts with the first interval date in the selected year instead of returning all intervals since the $calStart date (which is what it does at the moment) ?

$calStart = new DateTime('2014-01-17');
$interval = DateInterval::createFromDateString('4 weeks');
$rangeEnd = new DateTime($selYear . '-12-31');
$rangeDays = new DatePeriod($calStart, $interval, $rangeEnd);

Many thanks for any help with this, Tim.

user2571510
  • 11,167
  • 39
  • 92
  • 138
  • 1
    It's nice to see someone utilizing PHP's DatePeriod class. It is too often overlooked. – John Conde May 15 '14 at 13:22
  • Thanks - I agree. I think it's awesome and it's true you don't come across it that often. :) – user2571510 May 15 '14 at 13:23
  • I don't understand the question. "Only starts with the first interval date" -- what does "only" mean? What is the first interval *date*, considering that unqualified intervals are not and do not have dates? – Jon May 15 '14 at 13:26
  • Currently this gives me all interval dates (every 4 weeks) from $calStart until December 31 of the selected year but I only need the interval dates from January 1 to December 31 of the selected year. – user2571510 May 15 '14 at 13:28
  • Well, if you don't want the period to start from `$calStart`, don't pass `$calStart` as the first argument to the constructor! – Jon May 15 '14 at 13:31
  • @Jon: If I do this then how do I define the start date ? – user2571510 May 15 '14 at 13:33
  • @user2571510: I don't know, because I still don't understand what you are trying to do. To me it looks like you are doing `echo 42` and complaining that it prints 42. – Jon May 15 '14 at 13:35

2 Answers2

1

If you're looking to get $calStart to start in the same year as $rangeEnd this should do it for you:

$calStart = new DateTime('2014-01-17');
if ($selYear !== $calStart->format('Y')) {
    $calStart->setDate($selYear , $calStart->format('n'), $calStart->format('j'));
}
$interval = DateInterval::createFromDateString('4 weeks');
$rangeEnd = new DateTime($selYear . '-12-31');
$rangeDays = new DatePeriod($calStart, $interval, $rangeEnd);

I'm not sure how you get 2015-01-16 as the new start date so I wasn't able to address that directly.

John Conde
  • 217,595
  • 99
  • 455
  • 496
1

You can try with:

$calStart = new \DateTime('2014-01-17');
$calYear = $calStart->format('Y');
if ($selYear !== $calYear) {
    $day = (int) $calStart->format('z') + date('z', mktime(0,0,0,12,31,$calYear)) * ($selYear - $calYear);
    $calStart->setDate($selYear, 1, $day % 28);
}

Edit:

This one is more complex:

$calStart = new \DateTime('2014-01-17');
$calYear = (int) $calStart->format('Y');
if ($selYear !== $calYear) {
    $days = (int) $calStart->format('z') + 1; // get day in a year. +1 is because it starts with 0
    for ($i = $calYear; $i < $selYear; $i++) {
        $days -= (date('z', mktime(0,0,0,12,31,$i)) + 1) % 28; // remove from start day a modulo of 28 days, every year the date is lower
    }
    if ($days < 0) {
        $days += 28; // if we will finish with value under 0, just add 4 weeks
    }
    $calStart->setDate($selYear, 1, $days);
}
hsz
  • 148,279
  • 62
  • 259
  • 315