13

This is the function I'm trying to write:

function getWednesdays($month, $year) {
   // Returns an array of DateTimes representing all Wednesdays this month.
}

Any ideas? Thanks-

Yarin
  • 173,523
  • 149
  • 402
  • 512

11 Answers11

30

With PHP5.3

function getWednesdays($y, $m)
{
    return new DatePeriod(
        new DateTime("first wednesday of $y-$m"),
        DateInterval::createFromDateString('next wednesday'),
        new DateTime("last day of $y-$m")
    );
}

Usage:

foreach (getWednesdays(2010, 11) as $wednesday) {
    echo $wednesday->format("l, Y-m-d\n");
}

Output:

Wednesday, 2010-11-03
Wednesday, 2010-11-10
Wednesday, 2010-11-17
Wednesday, 2010-11-24

Note that this will exclude the end date, so if the last day of $y-$m happens to be a Wednesday, it won't be in the list. You have to add a day to the end date, to include it. To include it, change the relative format in the end date to

new DateTime("next month $y-$m-01")

which will then set the end date to the first day of the next month,


With PHP < 5.3

function getWednesdays($y, $m)
{
    $ts  = strtotime("first wednesday $y-$m-01");
    $end = strtotime("last wednesday $y-$m");
    $wednesdays = array();
    while($ts <= $end) {
        $wednesdays[] = $ts;
        $ts = strtotime('next wednesday', $ts);
    }
    return $wednesdays;
}

Usage:

foreach (getWednesdays(2010, 11) as $wednesday) {
    echo date("l, Y-m-d\n", $wednesday);
}

Same output as above (Run on Codepad).

Note that this does not work for any version prior to 5.3 due to changes in the relative formats parser. If you want to use this with PHP 5.3+ you have to change first Wednesday $y-$m-01 to first Wednesday of $y-$m-01 (mind the "of"). Also, just like in the DateTime version, the end date will not be included.


Further reading:

Gordon
  • 312,688
  • 75
  • 539
  • 559
  • 1
    If I return every friday in January 2014, I get 4 fridays not including the last day of the month, which is a friday. Any ideas? – lukeocodes Jul 26 '13 at 21:25
  • @LukeOliff it excludes the end date. You'll have to add a day to it, to include it. See update. – Gordon Jul 27 '13 at 06:26
  • Yes thanks. I raised a question about it here: http://stackoverflow.com/questions/17891477/php-dateinterval-not-returning-last-day-of-the-month/17891550?noredirect=1#17891550 and I only need to add a second, but used a minute just incase :) – lukeocodes Jul 29 '13 at 09:31
  • September 2015 (2015, 9), not returns last wednesday, totally it has 5 wednesday but returns 4 only. – 151291 Sep 28 '15 at 09:17
  • 2
    @15121991 mind the passage stating *"Note that this will exclude the end date, so if the last day of $y-$m happens to be a Wednesday, it won't be in the list. You have to add a day to the end date, to include it. To include it, change the relative format in the end date to `new DateTime("next month $y-$m-01")`"* – Gordon Sep 28 '15 at 09:22
  • I added that inside DatePeriod(), but showoing error message. shall i know where to config `new DateTime("next month $y-$m-01")` – 151291 Sep 28 '15 at 10:12
  • @15121991 it's really simple: replace the last DateTime argument in the DatePeriod constructor with the one from my comment. – Gordon Sep 28 '15 at 10:21
4

You can try something like this:

function getWednesdays($month, $year) {
    $base_date = strtotime($year . '-' . $month . '-01');
    $wed = strtotime('first wed of ' . date('F Y', $base_date));

    $wednesdays = array();

    do {
        $wednesdays[] = new DateTime(date('r', $wed));
        $wed = strtotime('+7 days', $wed);
    } while (date('m', $wed) == $month);

    return $wednesdays;
}
Michal M
  • 9,322
  • 8
  • 47
  • 63
3

Use this function to get any days total count in a month

    function getTotalDays($year, $month, $day){
        $from = $year."-".$month."-01";
        $t=date("t",strtotime($from));

        for($i=1; $i<$t; $i++){
           if( strtolower(date("l",strtotime($year."-".$month."-".$i)))== $day){
             $count++;
          }
      }
      return $count;
 }

use like this getTotalDays('2014', '08','monday');

will output 4

But if you want all dates in a month on a particular day then use this function

    function getTotalDatesArray($year, $month, $day){
        $date_ar=array();
        $from = $year."-".$month."-01";
        $t=date("t",strtotime($from));

        for($i=1; $i<$t; $i++){
           if( strtolower(date("l",strtotime($year."-".$month."-".$i)))== $day){
            $j= $i>9 ? $i: "0".$i;
             $date_ar[]=$year."-".$month."-".$j;
          }
      }
      return $date_ar;
 }

use like this getTotalDatesArray('2014', '08','monday');

will output Array ( [0] => 2014-08-04 [1] => 2014-08-11 [2] => 2014-08-18 [3] => 2014-08-25 )

RN Kushwaha
  • 2,081
  • 3
  • 29
  • 40
2

There's probably a more efficient way to do it, but this works:

<?php
function isWednesday($day, $month, $year)
{
    if (date('w', $date = mktime(0,0,0,$month,$day,$year)) == 3) {
        return $date;
    }
    return false;
}
function getWednesdays($month, $year)
{
    for ($day=1; $day<=7; $day++) {
        if ($date = isWednesday($day, $month, $year)) {
            break;
        }
    }
    $wednesdays = array();

    while (date('m',$date) == $month) {
        $wednesdays[] = $date;
        $day += 7;
        $date = isWednesday($day, $month, $year);
    }
    return $wednesdays;
}

You can test with this:

foreach (getWednesdays($argv[1], $argv[2]) as $date) {
    echo date("Y-m-d\n", $date);
}

$ php wednesdays.php 11 2010
2010-11-03
2010-11-10
2010-11-17
2010-11-24
$ php wednesdays.php 12 2010
2010-12-01
2010-12-08
2010-12-15
2010-12-22
2010-12-29
$ php wednesdays.php 2 2012
2012-02-01
2012-02-08
2012-02-15
2012-02-22
2012-02-29

S

scoates
  • 853
  • 7
  • 11
2
<?php
function wednesdays($month, $year)
{
  list($n,$d) = explode('-', date('t-d', strtotime("Wednesday, $year-$month")));
  $days = array();
  while ($d <= $n)
  {
    $days[] = sprintf("%04d-%02d-%02d", $year, $month, $d);
    $d += 7;
  }
  return $days;
}

var_dump(wednesdays(11, 2010));

?>

But I highly recommend getting used to PHP 5.3's date and time functions if you can use them. (See Gordon's answer.)

Matthew
  • 47,584
  • 11
  • 86
  • 98
  • Another very good answer, but you're right, Gordon is making best use of PHP's existing functions.. – Yarin Nov 27 '10 at 19:18
1

I have re-written @Gordon's solution to suit for any day

function get_dates_of_day($y, $m, $day_name)
{
    return new DatePeriod(
        new DateTime("first $day_name of $y-$m"),
        DateInterval::createFromDateString("next $day_name"),
        new DateTime("next month $y-$m-01")
        );
}

Now you can simply do get_dates_of_day('2015','08','wednesday') and use the same to get dates for any day in a given month.

Narendran Parivallal
  • 1,070
  • 1
  • 14
  • 16
1

With PHP earlier than 5.3 this solution doesn't work. Seems, First Day Time stamp is greater than the last day time stamp, which eventually terminate the loop in first go.

As PHP calculates time differences at midnight, this solution does not work when the month starts on the day in question. And for some cases does not work for the last day either.

I've sorted out these problems in following code. And this code can be used for any day of week.

The solution was created with the help of Eli's code in this question: Get the First or Last Friday in a Month

///// code starts here /////

function getWeekDates($year, $month, $day){
$tsInMonth = strtotime("$year-$month");
$monthNumber = (int)date("m",$tsInMonth);

$Names = array( 1=>"Sun", 2=>"Mon", 3=>"Tue", 4=>"Wed", 5=>"Thu", 6=>"Fri", 7=>"Sat" );

$ThisMonthTS = strtotime( date("Y-m-01", $tsInMonth ) );
$NextMonthTS = strtotime( date("Y-m-01", strtotime("next month", $tsInMonth) ) );

$weekDates = array();

for($Ord=1;$Ord<=5;$Ord++){
    $DateOfInterest = (-1 == $Ord) 
        ? strtotime( "last ".$Names[$day], $NextMonthTS ) 
        : strtotime( $Names[$day]." + ".($Ord-1)." weeks", $ThisMonthTS );

    ($Ord==5 && (int)date("m",$DateOfInterest)==(int)date("m",$NextMonthTS))
        ? false
        : $weekDates [] = $DateOfInterest;
}

return $weekDates;
}

///// Usage /////

foreach (getWeekDates("2010", "2", "2") as $day) {
    echo "<br>" . date("l, Y-m-d", $day);
}

///// End of code /////

I hope it helps someone.

Community
  • 1
  • 1
Waqas
  • 11
  • 2
0

I have written following code for this purpose ... and its working perfectly for me

function get_month_date($year, $month, $day) {
$monthdays = date('t', mktime(0, 0, 0, $month, 1, $year));
$dates = array();
for($i = 0; $i <= $monthdays; $i++ ) {
    if($day == date('l', mktime(0, 0, 0, $month, 1+$i, $year)) && $month == date('n', mktime(0, 0, 0, $month, 1+$i, $year))) {
    $dates[] = date('Y-m-d', mktime(0, 0, 0, $month, 1+$i, $year));
    }
}
return $dates; }

We can use it as :

$days = get_month_date($year, $month, 'Wednesday');

It will return array of all dates of Wednesday in given month and year

Rajen K Bhagat
  • 222
  • 3
  • 9
0

Here is the sample

function getSundays($y,$m){ 
    $date = "$y-$m-01";
    $first_day = date('N',strtotime($date));
    $first_day = 7 - $first_day + 1;
    $last_day =  date('t',strtotime($date));
    $days = array();
    for($i=$first_day; $i<=$last_day; $i=$i+7 ){
        $days[] = $i;
    }
    return  $days;
}

$days = getSundays(2016,04);
print_r($days);
Jerald
  • 335
  • 1
  • 10
0

Try This one to get all Wednesdays in current month.

$month  = date('m');
$year  = date('Y');
function getDays($year,$month){ 
 $days = cal_days_in_month(CAL_GREGORIAN, $month,$year);
 $wed = array();
 for($i = 1; $i<= $days; $i++){
 $day  = date('Y-m-'.$i);
 $result = date("D", strtotime($day));
 if($result == "Wed"){  
 $wed[] = date("Y-m-d", strtotime($day)). " ".$result."<br>";
 }  
}
 return  $wed;
}
$wed = getDays($year,$month);
print_r($wed);
-2

If DateTime is not given, you need to know the day for one date - start of unix era for example (1st Jan 1970).

Going from there, you simply locate the first wednesday, and from there find your month. Keep in mind the leap years, and you're good.

Obviously, it isn't the most efficient algorithm in the world, but it would do the job.

hummingBird
  • 2,495
  • 3
  • 23
  • 43
  • I think he is looking for all the wednesday's for the given month, specified by the month and year values. – Codemwnci Nov 27 '10 at 18:44
  • i know :) ... first part of the above algorithm is connected to process of coming to the first wed in the given month. if nothing else is given, there must be some kind of 'anchor' day to start with – hummingBird Nov 27 '10 at 18:47
  • @playcat- You misunderstood the question- see other answers – Yarin Nov 27 '10 at 19:20
  • hm... i could swear it didn't say DateTime originally... are you sure you didn't edit the question? i commented your question proposing that task is easy if DateTime is available... – hummingBird Nov 27 '10 at 19:30
  • @playcat- Question was not edited- if it was you would see it, all edits on SO are visible – Yarin Nov 27 '10 at 19:42