Getting the dates of specific days

I want to do this:
Suppose we have a time span…from February 1st to February 28th.
Simply put…I want to get all the dates of the Sundays and Saturdays within this time span.

Any ideas about how to achieve this?

1 Like

Try this:

  $str = '2016-02-';
  for($i2=1; $i2<30; $i2++)
  {

    // echo '<br>',
      $ddd = $str.$i2;
    // echo '',
      $date = date('Y M D d', $time = strtotime($ddd) );

    if( strpos($date, 'Sat') || strpos($date, 'Sun') )
    {
      echo '<br>' .$date;
    }
  }
 

Output:

I will leave it up to you to optimize or to wait for an alternative solution.

1 Like

very interesting…so far it seems that it does the job…I want to make some tests.
I will inform you if this after all will be the solution to the problem posed.

This example takes a different approach. It makes use of a function that builds an array of DateTime objects that span a specified date range. This array can then be filtered to find dates that you are interested in. The example shows how to obtain those that fall on a weekend and a Monday.

<?php

/**
 *  @begin    string A date/time string that can be accepted by the DateTime constructor.
 *  @end      string A date/time string that can be accepted by the DateTime constructor.
 *  @interval string An interval specification that can be accepted by the DateInterval constructor.
 *                   Defaults to P1D
 *
 *  @return   array Array of DateTime objects for the specified date range.
 */
function dateRange($begin, $end, $interval = null)
{
    $begin = new DateTime($begin);
    $end = new DateTime($end);
    // Because DatePeriod does not include the last date specified.
    $end = $end->modify('+1 day');
    $interval = new DateInterval($interval ? $interval : 'P1D');

    return iterator_to_array(new DatePeriod($begin, $interval, $end));
}

$dates = dateRange('2016-01-01', '2016-02-23');

$weekends = array_filter($dates, function ($date) {
    $day = $date->format("N");
    return $day === '6' || $day === '7';
});

foreach ($weekends as $date) {
    echo $date->format("D Y-m-d") . "\n";
}

$mondays = array_filter($dates, function ($date) {
    return $date->format("N") === '1';
});

foreach ($mondays as $date) {
    echo $date->format("D Y-m-d") . "\n";
}

I wll go for this code…it is "cleaner: and it allowς for a timeframe that varies.

I must add something though.
In my original post I said that I want to get the dates of saturdays/sundays.

**This will vary too…**It maybe any day of the week and any number of it(it might be 2 or 3 or 4 days)
The code does not take into consideration this.

A change must occur here:
$weekends = array_filter($dates, function ($date) {
$day = $date->format(“N”);
return $day === ‘6’ || $day === ‘7’;
});

For naming purposes of course weekends must be replaced with an other name…
I must say here that the days of interest will result from a query and this query will give days in this format: monday… tuesday…etc.As such I have modified the code to this

$weekends = array_filter($dates, function ($date) 
        {
    $day = $date->format("l");
    return $day === 'Saturday' || $day === 'Sunday';
});

Nonetheless this code is for a fixed number of days(2) and specific days of the week.

How to change the code so to reflect the fact that the above factors will vary?

Will the query return the number of days in an array? For example an array such as:

$days = [
 'Monday',
 'Friday',
 'Saturday'
];




YES…an array with the days will be returned.

If Mondays are to be included is there a reason why only four of the five Mondays in February are included in the original date range?

I’ve updated the code a little so that the filter can work with any number of days.

<?php

/**
 *  @begin    string A date/time string that can be accepted by the DateTime constructor.
 *  @end      string A date/time string that can be accepted by the DateTime constructor.
 *  @interval string An interval specification that can be accepted by the DateInterval constructor.
 *                   Defaults to P1D
 *
 *  @return   array Array of DateTime objects for the specified date range.
 */
function dateRange($begin, $end, $interval = null)
{
    $begin = new DateTime($begin);
    $end = new DateTime($end);
    // Because DatePeriod does not include the last date specified.
    $end = $end->modify('+1 day');
    $interval = new DateInterval($interval ? $interval : 'P1D');

    return iterator_to_array(new DatePeriod($begin, $interval, $end));
}

function dateFilter(array $daysOfTheWeek)
{
    return function ($date) use ($daysOfTheWeek) {
        return in_array($date->format('l'), $daysOfTheWeek);
    };
}

function display($date) { echo $date->format("D Y-m-d")."\n"; }

$dates = dateRange('2016-01-01', '2016-02-23');

array_walk(array_filter($dates, dateFilter(['Monday'])), 'display');
array_walk(array_filter($dates, dateFilter(['Tuesday', 'Wednesday', 'Thursday'])), 'display');
array_walk(array_filter($dates, dateFilter(['Saturday', 'Sunday'])), 'display');

@davidtsadler

Version: 002

<?php 
/**
 function: find the aDays in the time period
   usage:
    getDays($start, $duration, $aDays, $fFormat) 
 where:  
   $start = 'YYYY';   
   $iDays =  365;  // maximum  
   $aDays = ['Mon', 'Wed', 'Fri'];  //  3xchar  
*/
>
function getDays(
    $start  ='2016-12-25', 
    $iDays  = 365, 
    $aDays  = ['Sun', 'Wed', 'Sat'],
    $format = 'D, M jS Y'
) 
{
  $dStart = date('d', strtotime($start));
  $YM     = substr($start, 0, 8);

  for($i=$dStart; $i<=$iDays; $i++)
  {
    $ok   = strtotime($YM.$i);
    if($ok)
    {
      $date = date('D', $ok);
      foreach($aDays as $day)
      {
        $date = strtolower($date);         
        $day  = strtolower($day);         
        if( $date===$day )
        {
          echo '<br>' .date($format, $ok);
        }
      }//foreach 
    }//$ok
  }
}//endfunc

Usage:

getDays();

Results:
Sun, Dec 25th 2016
Wed, Dec 28th 2016
Sat, Dec 31st 2016

Usage:

getDays($str = ‘2016-02-01’, 42, $aDays = [‘Mon’,‘Thu’,‘Fri’],‘Y M D jS’);

2016 Feb Mon 1st
2016 Feb Thu 4th
2016 Feb Fri 5th
2016 Feb Mon 8th
2016 Feb Thu 11th
2016 Feb Fri 12th
2016 Feb Mon 15th
2016 Feb Thu 18th
2016 Feb Fri 19th
2016 Feb Mon 22nd
2016 Feb Thu 25th
2016 Feb Fri 26th
2016 Feb Mon 29th


[off topic] ***It took me longer to format the post than it did write the function :(***

Edit:
Added optional formatting parameter to function

I am having hard time to figure out what is the usage of use.

Notice: Only variables should be passed by reference in /home/john/www/atests/index-get-selected-days.php on line 85

To eliminate the Warning message try changing error_reporting()

KLUDGE

error_reporting(E_STRICT);
    $dates = dateRange('2016-01-01', '2016-02-23');

    array_walk( array_filter($dates, dateFilter( ['Monday'])), 'display' );
    array_walk( array_filter($dates, dateFilter( ['Tuesday', 'Wednesday', 'Thursday'])), 'display' );
    array_walk( array_filter($dates, dateFilter( ['Saturday', 'Sunday'])), 'display' );
error_reporting(-1);

Maybe this will help:

to eliminate the warning I just did this:

$d=array_filter($dates, dateFilter(['Tuesday']));

array_walk($d, 'display');

I passed array_filter to a variable and then used it to array walk.

1 Like

I tried this and was most surprised the warning was still activate:

    array_walk( $tmp=array_filter($dates, dateFilter( ['Saturday', 'Sunday'])), 'display' );

I do not know why that might be happening…I do not know the logic of the parser.

1 Like

There is an issue left though.
As the code is now a display function is called to print the data to the browser.

function display($date) { echo $date->format("D Y-m-d")."\n"; }

I want though these data to be passed to an array
I tried this function:
function create_cl_days_array($date)
{ $closed_day=array();
$day=array(“date”=>$date->format(“l Y-m-d”));
array_push($closed_day, $day);
}
And:
array_walk($closed_dts, 'create_cl_days_array');
var_dump($closed_day)

I was hoping that var dumping $closed_day would give me the array with the dates…instead I get the usual udefined variable message.

Why?

P.S Sorry for not formatting properly create_cl_days()…I tried very hard to do so…but I couldn’t

Version 003:

/* =========================================
 function: find the aDays in the time period
 usage:
   @getDays( @start, @duration, @aDays, @format, @result) 
 where:  
   @start  = 'YYYY';   
   @iDays  =  365;  // maximum  
   @aDays  = ['Mon', 'Wed', 'Fri']; # 3xchar  
   @format = 'Y M D jS',
   @result = NULL
========================================= */
function getDays(
    $start  ='2016-12-25', 
    $iDays  = 365, 
    $aDays  = ['Sun', 'Wed', 'Sat'],
    $format = 'D, M jS Y',
    $result = NULL
) 
{
  $dStart = date('d', strtotime($start));
  $YM     = substr($start, 0, 8);

  for($i=$dStart; $i<=$iDays; $i++)
  {
    $ok   = strtotime($YM.$i);
    if($ok)
    {
      $date = date('D', $ok);
      foreach($aDays as $day)
      {
        $date = strtolower($date);         
        $day  = strtolower($day);         
        if( $date===$day )
        {
          if( is_array($result) )
          {
            $result[] = date($format, $ok);
          }else{
            echo '<br>' .date($format, $ok);
          }
        }
      }//foreach 
    }//$ok
  }

  return $result;
}//endfunc

echo '<b>Defaults: (no Parameters)</b>';
  getDays();

echo '<br><br>';
echo '<b>all the Parameters:</b>';
  $result    = getDays(
      $str   = '2016-02-01', 
      $iDays = 12, 
      $aDays = ['Mon','Thu','Fri'],
      $format= 'Y M D jS',
      $aDate = []
      );

  echo '<pre>', print_r($result, true), '</pre>';

Output:

Defaults: (no Parameters)
Sun, Dec 25th 2016
Wed, Dec 28th 2016
Sat, Dec 31st 2016

all the Parameters:
Array
(
[0] => 2016 Feb Mon 1st
[1] => 2016 Feb Thu 4th
[2] => 2016 Feb Fri 5th
[3] => 2016 Feb Mon 8th
[4] => 2016 Feb Thu 11th
[5] => 2016 Feb Fri 12th
)

1 Like

I’ve added more examples of what can be done. The important thing to keep in mind is that once you have called array_filter you will be left with an array of DateTime objects for a range of dates that have meet a criteria. This array can be molded into what ever your project needs. Notice that at no point do I ever need to change how dateRange works. I just simple make use of the various array_ functions.

<?php
error_reporting(E_STRICT);

/**
 *  @begin    string A date/time string that can be accepted by the DateTime constructor.
 *  @end      string A date/time string that can be accepted by the DateTime constructor.
 *  @interval string An interval specification that can be accepted by the DateInterval constructor.
 *                   Defaults to P1D
 *
 *  @return   array Array of DateTime objects for the specified date range.
 */
function dateRange($begin, $end, $interval = null)
{
    $begin = new DateTime($begin);
    $end = new DateTime($end);
    // Because DatePeriod does not include the last date specified.
    $end = $end->modify('+1 day');
    $interval = new DateInterval($interval ? $interval : 'P1D');

    return iterator_to_array(new DatePeriod($begin, $interval, $end));
}

function dateFilter(array $daysOfTheWeek)
{
    return function ($date) use ($daysOfTheWeek) {
        return in_array($date->format('l'), $daysOfTheWeek);
    };
}

$dateRange = dateRange('2016-02-01', '2016-02-28');

$dates = array_filter($dateRange, dateFilter(['Saturday', 'Sunday']));
/**
 * Optional. Call array_values if you care about having holes in the keys of the array.
 * http://php.net/manual/en/function.array-filter.php#99358

 $dates = array_values($dates);
 */

/**
 * Since $dates is just an array we can do what ever we want with its values.
 */

/**
 * Convert to an array of strings.
 **/
$closedDates = array_map(function ($date) {
    return $date->format('l Y-m-d');
}, $dates);

print_r($closedDates);

/**
(
    [5] => Saturday 2016-02-06
    [6] => Sunday 2016-02-07
    [12] => Saturday 2016-02-13
    [13] => Sunday 2016-02-14
    [19] => Saturday 2016-02-20
    [20] => Sunday 2016-02-21
    [26] => Saturday 2016-02-27
    [27] => Sunday 2016-02-28
)
*/

/**
 * Convert to a different array.
 */
$closedDates = array_map(function ($date) {
    return ['date' => $date->format('l Y-m-d')];
}, $dates);

print_r($closedDates);

/**
Array
(
    [5] => Array
        (
            [date] => Saturday 2016-02-06
        )

    [6] => Array
        (
            [date] => Sunday 2016-02-07
        )

    [12] => Array
        (
            [date] => Saturday 2016-02-13
        )

    [13] => Array
        (
            [date] => Sunday 2016-02-14
        )

    [19] => Array
        (
            [date] => Saturday 2016-02-20
        )

    [20] => Array
        (
            [date] => Sunday 2016-02-21
        )

    [26] => Array
        (
            [date] => Saturday 2016-02-27
        )

    [27] => Array
        (
            [date] => Sunday 2016-02-28
        )

)
 */

/**
 * Group dates by their day of the week.
 */
$closedDates = array_reduce($dates, function ($carry, $date) {
    $dayOfWeek = $date->format('l');
    $carry[$dayOfWeek][] = $date->format('Y-m-d');
    return $carry;
}, []);

print_r($closedDates);

/**
Array
(
    [Saturday] => Array
        (
            [0] => 2016-02-06
            [1] => 2016-02-13
            [2] => 2016-02-20
            [3] => 2016-02-27
        )

    [Sunday] => Array
        (
            [0] => 2016-02-07
            [1] => 2016-02-14
            [2] => 2016-02-21
            [3] => 2016-02-28
        )

)
*/

/**
 * Go one step further and use generic reusable functions.
 */
function formatDate($fmt)
{
    return function ($date) use ($fmt) {
        return $date->format($fmt);
    };
}

function groupByDayOfWeek($carry, $date)
{
    $dayOfWeek = $date->format('l');
    $carry[$dayOfWeek][] = $date->format('Y-m-d');
    return $carry;
}

print_r(array_map(formatDate('l Y-m-d'), array_filter($dateRange, dateFilter(['Monday', 'Tuesday']))));

/**
Array
(
    [0] => Monday 2016-02-01
    [1] => Tuesday 2016-02-02
    [7] => Monday 2016-02-08
    [8] => Tuesday 2016-02-09
    [14] => Monday 2016-02-15
    [15] => Tuesday 2016-02-16
    [21] => Monday 2016-02-22
    [22] => Tuesday 2016-02-23
)
 */

print_r(array_map(formatDate('l jS Y F'), array_filter($dateRange, dateFilter(['Wednesday', 'Thursday']))));

/**
    [2] => Wednesday 3rd 2016 February
    [3] => Thursday 4th 2016 February
    [9] => Wednesday 10th 2016 February
    [10] => Thursday 11th 2016 February
    [16] => Wednesday 17th 2016 February
    [17] => Thursday 18th 2016 February
    [23] => Wednesday 24th 2016 February
    [24] => Thursday 25th 2016 February
 */

print_r(array_reduce(array_filter($dateRange, datefilter(['Monday', 'Friday'])), 'groupByDayOfWeek', []));

/**
Array
(
    [Monday] => Array
        (
            [0] => 2016-02-01
            [1] => 2016-02-08
            [2] => 2016-02-15
            [3] => 2016-02-22
        )

    [Friday] => Array
        (
            [0] => 2016-02-05
            [1] => 2016-02-12
            [2] => 2016-02-19
            [3] => 2016-02-26
        )

)
 */

print_r(array_reduce(array_filter($dateRange, datefilter(['Tuesday', 'Thursday'])), 'groupByDayOfWeek', []));

/**
Array
(
    [Tuesday] => Array
        (
            [0] => 2016-02-02
            [1] => 2016-02-09
            [2] => 2016-02-16
            [3] => 2016-02-23
        )

    [Thursday] => Array
        (
            [0] => 2016-02-04
            [1] => 2016-02-11
            [2] => 2016-02-18
            [3] => 2016-02-25
        )

)
*/

/**
 * For the year 2016 lets get all the days that are the 24th of each month.
 */
$year = dateRange('2016-01-01', '2016-12-31');

print_r(array_map(
    function ($date) {
        return "The 24th falls on a {$date->format('l')} in the month of {$date->format('F')}";
    },
    array_filter($year, function ($date) {
        return $date->format('j') === '24';
    })
));

/**
Array
(
    [23] => The 24th falls on a Sunday in the month of January
    [54] => The 24th falls on a Wednesday in the month of February
    [83] => The 24th falls on a Thursday in the month of March
    [114] => The 24th falls on a Sunday in the month of April
    [144] => The 24th falls on a Tuesday in the month of May
    [175] => The 24th falls on a Friday in the month of June
    [205] => The 24th falls on a Sunday in the month of July
    [236] => The 24th falls on a Wednesday in the month of August
    [267] => The 24th falls on a Saturday in the month of September
    [297] => The 24th falls on a Monday in the month of October
    [328] => The 24th falls on a Thursday in the month of November
    [358] => The 24th falls on a Saturday in the month of December
)
 */

/**
 * Do the above but lets make it a bit more dynamic in what days we are interested in.
 */

function daysFilter(array $days)
{
    return function ($date) use ($days) {
        return in_array($date->format('j'), $days);
    };
}

function fallsOn($date)
{
    return "The {$date->format('jS')} falls on a {$date->format('l')} in the month of {$date->format('F')}";
}


print_r(array_map('fallsOn', array_filter($year, daysFilter(['1']))));

/**
Array
(
    [0] => The 1st falls on a Friday in the month of January
    [31] => The 1st falls on a Monday in the month of February
    [60] => The 1st falls on a Tuesday in the month of March
    [91] => The 1st falls on a Friday in the month of April
    [121] => The 1st falls on a Sunday in the month of May
    [152] => The 1st falls on a Wednesday in the month of June
    [182] => The 1st falls on a Friday in the month of July
    [213] => The 1st falls on a Monday in the month of August
    [244] => The 1st falls on a Thursday in the month of September
    [274] => The 1st falls on a Saturday in the month of October
    [305] => The 1st falls on a Tuesday in the month of November
    [335] => The 1st falls on a Thursday in the month of December
)
*/

print_r(array_map('fallsOn', array_filter($year, daysFilter(['8', '16']))));

/**
Array
(
    [7] => The 8th falls on a Friday in the month of January
    [15] => The 16th falls on a Saturday in the month of January
    [38] => The 8th falls on a Monday in the month of February
    [46] => The 16th falls on a Tuesday in the month of February
    [67] => The 8th falls on a Tuesday in the month of March
    [75] => The 16th falls on a Wednesday in the month of March
    [98] => The 8th falls on a Friday in the month of April
    [106] => The 16th falls on a Saturday in the month of April
    [128] => The 8th falls on a Sunday in the month of May
    [136] => The 16th falls on a Monday in the month of May
    [159] => The 8th falls on a Wednesday in the month of June
    [167] => The 16th falls on a Thursday in the month of June
    [189] => The 8th falls on a Friday in the month of July
    [197] => The 16th falls on a Saturday in the month of July
    [220] => The 8th falls on a Monday in the month of August
    [228] => The 16th falls on a Tuesday in the month of August
    [251] => The 8th falls on a Thursday in the month of September
    [259] => The 16th falls on a Friday in the month of September
    [281] => The 8th falls on a Saturday in the month of October
    [289] => The 16th falls on a Sunday in the month of October
    [312] => The 8th falls on a Tuesday in the month of November
    [320] => The 16th falls on a Wednesday in the month of November
    [342] => The 8th falls on a Thursday in the month of December
    [350] => The 16th falls on a Friday in the month of December
)
*/

/**
 * Use the same range of dates with our generic functions.
 */
$days = array_filter($year, daysFilter(['1', '8', '16', '24']));

print_r(array_map('fallsOn', $days));

/**
Array
(
    [0] => The 1st falls on a Friday in the month of January
    [7] => The 8th falls on a Friday in the month of January
    [15] => The 16th falls on a Saturday in the month of January
    [23] => The 24th falls on a Sunday in the month of January
    [31] => The 1st falls on a Monday in the month of February
    [38] => The 8th falls on a Monday in the month of February
    [46] => The 16th falls on a Tuesday in the month of February
    [54] => The 24th falls on a Wednesday in the month of February
    [60] => The 1st falls on a Tuesday in the month of March
    [67] => The 8th falls on a Tuesday in the month of March
    [75] => The 16th falls on a Wednesday in the month of March
    [83] => The 24th falls on a Thursday in the month of March
    [91] => The 1st falls on a Friday in the month of April
    [98] => The 8th falls on a Friday in the month of April
    [106] => The 16th falls on a Saturday in the month of April
    [114] => The 24th falls on a Sunday in the month of April
    [121] => The 1st falls on a Sunday in the month of May
    [128] => The 8th falls on a Sunday in the month of May
    [136] => The 16th falls on a Monday in the month of May
    [144] => The 24th falls on a Tuesday in the month of May
    [152] => The 1st falls on a Wednesday in the month of June
    [159] => The 8th falls on a Wednesday in the month of June
    [167] => The 16th falls on a Thursday in the month of June
    [175] => The 24th falls on a Friday in the month of June
    [182] => The 1st falls on a Friday in the month of July
    [189] => The 8th falls on a Friday in the month of July
    [197] => The 16th falls on a Saturday in the month of July
    [205] => The 24th falls on a Sunday in the month of July
    [213] => The 1st falls on a Monday in the month of August
    [220] => The 8th falls on a Monday in the month of August
    [228] => The 16th falls on a Tuesday in the month of August
    [236] => The 24th falls on a Wednesday in the month of August
    [244] => The 1st falls on a Thursday in the month of September
    [251] => The 8th falls on a Thursday in the month of September
    [259] => The 16th falls on a Friday in the month of September
    [267] => The 24th falls on a Saturday in the month of September
    [274] => The 1st falls on a Saturday in the month of October
    [281] => The 8th falls on a Saturday in the month of October
    [289] => The 16th falls on a Sunday in the month of October
    [297] => The 24th falls on a Monday in the month of October
    [305] => The 1st falls on a Tuesday in the month of November
    [312] => The 8th falls on a Tuesday in the month of November
    [320] => The 16th falls on a Wednesday in the month of November
    [328] => The 24th falls on a Thursday in the month of November
    [335] => The 1st falls on a Thursday in the month of December
    [342] => The 8th falls on a Thursday in the month of December
    [350] => The 16th falls on a Friday in the month of December
    [358] => The 24th falls on a Saturday in the month of December
)
*/

print_r(array_map(formatDate('l Y-m-d'), $days));

/**
Array
(
    [0] => Friday 2016-01-01
    [7] => Friday 2016-01-08
    [15] => Saturday 2016-01-16
    [23] => Sunday 2016-01-24
    [31] => Monday 2016-02-01
    [38] => Monday 2016-02-08
    [46] => Tuesday 2016-02-16
    [54] => Wednesday 2016-02-24
    [60] => Tuesday 2016-03-01
    [67] => Tuesday 2016-03-08
    [75] => Wednesday 2016-03-16
    [83] => Thursday 2016-03-24
    [91] => Friday 2016-04-01
    [98] => Friday 2016-04-08
    [106] => Saturday 2016-04-16
    [114] => Sunday 2016-04-24
    [121] => Sunday 2016-05-01
    [128] => Sunday 2016-05-08
    [136] => Monday 2016-05-16
    [144] => Tuesday 2016-05-24
    [152] => Wednesday 2016-06-01
    [159] => Wednesday 2016-06-08
    [167] => Thursday 2016-06-16
    [175] => Friday 2016-06-24
    [182] => Friday 2016-07-01
    [189] => Friday 2016-07-08
    [197] => Saturday 2016-07-16
    [205] => Sunday 2016-07-24
    [213] => Monday 2016-08-01
    [220] => Monday 2016-08-08
    [228] => Tuesday 2016-08-16
    [236] => Wednesday 2016-08-24
    [244] => Thursday 2016-09-01
    [251] => Thursday 2016-09-08
    [259] => Friday 2016-09-16
    [267] => Saturday 2016-09-24
    [274] => Saturday 2016-10-01
    [281] => Saturday 2016-10-08
    [289] => Sunday 2016-10-16
    [297] => Monday 2016-10-24
    [305] => Tuesday 2016-11-01
    [312] => Tuesday 2016-11-08
    [320] => Wednesday 2016-11-16
    [328] => Thursday 2016-11-24
    [335] => Thursday 2016-12-01
    [342] => Thursday 2016-12-08
    [350] => Friday 2016-12-16
    [358] => Saturday 2016-12-24
)
*/
1 Like

thank you for devoting the time and the effort.