List of Fridays

Hi there,

I hack and slashed this code together a long time ago - I didn't understand it 100% then, and I still don't understand it 100% now.  All I know is that it will make a list of all the current Fridays in a year.  Can you help me understand & comment (so I will remember) whats going on in these loops to grab all the Friday dates?  How do I grab all the Sundays instead?  What is the "list($n,$d)..." line all about?  

Thank you!

function fridays($month, $year, $newsletter_list)
{ 
  // $newsletter_list is an array of exsisting newsletter dates from the database.  IE. 2012-11-04, 2012-11-25..
  $days = array();
  
  for ($month = 1; $month <= 12; $month++) {
	  list($n,$d) = explode('-', date('t-d', strtotime("Friday, $year-$month")));
	  while ($d <= $n)
	  {
		$selectedDay = sprintf("%04d-%02d-%02d", $year, $month, $d);
		$ontheList = false;
		
		for ($q = 0; $q < count($newsletter_list); $q++) {
			if ($selectedDay == $newsletter_list[$q]) {
				$ontheList = true;
			}																		
		}
		
		if ($ontheList == false) {
			$days[] = $selectedDay;
		}
		
		$d += 7;
	  }
  }
  return $days;
}

Open in new window

maeve100Asked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Ray PaseurCommented:
0
Ray PaseurCommented:
Also, please see this article.  It has useful learning resources for those who are new to PHP and want to learn more.
http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/A_11769-And-by-the-way-I-am-new-to-PHP.html
0
Ray PaseurCommented:
I have not tested this exhaustively, but it seems correct.

<?php // RAY_temp_maeve100.php
error_reporting(E_ALL);
echo '<pre>';

// ESTABLISH A FUNCTION DEFINITION FOR A GIVEN YEAR AND A GIVEN DAY OF THE WEEK
function days($year='Today', $day='Friday')
{
    // NORMALIZE THE YEAR TO 4-DIGIT
    $year = date('Y', strtotime("$year"));

    // FIND THE FIRST DAY
    $first = date('c', strtotime("$year-01 FIRST $day"));

    // THE RETURN VALUES HERE
    $arr = array();

    // COLLECT THE WEEKDAYS IN THIS YEAR
    while ($first < "$year-12-32")
    {
        $arr[] = $first;

        // INCREMENT BY ONE WEEK
        $first = date('c', strtotime($first . ' PLUS 1 WEEK'));
    }

    // RETURN THE VALUES
    return $arr;
}

// TEST THE FUNCTION
$x = days("2002-03-15", 'Monday');
var_dump($x);
$x = days();
var_dump($x);

Open in new window

HTH, ~Ray
0
Bootstrap 4: Exploring New Features

Learn how to use and navigate the new features included in Bootstrap 4, the most popular HTML, CSS, and JavaScript framework for developing responsive, mobile-first websites.

Julian HansenCommented:
To answer your question - here is your code commented
function fridays($month, $year, $newsletter_list)
{ 
  // $newsletter_list is an array of exsisting newsletter dates from the database.  IE. 2012-11-04, 2012-11-25..
  $days = array();
  
  // We are going to repeat this for all months from Jan to Dec
  for ($month = 1; $month <= 12; $month++) {
  
  // This is a complex bit of code - lets break it down
  //   1. strtotime("Friday, $year-$month")
  //      This returns the full date of the first friday in the month specified by Year-Month. The value returned is a millisecond value for the date
  //   2.  date('t-d', strtotime("Friday, $year-$month")))
  //      This takes the return value from the strtotime and extracts the Number of days for the month and the day of the month as a hyphen separated pair
  //   3. explode('-', date('t-d', strtotime("Friday, $year-$month")));
  //      This splits the returned string from date() into an array of items broken on the '-' the result will be an array with index[0] being
  //      the number of days in the specified month and index[1] being the day of the first friday in the month.
  //   4. list($n,$d) 
  //      This assigns the values of the array returned by the explode to the the $n and $d variables
    list($n,$d) = explode('-', date('t-d', strtotime("Friday, $year-$month")));
  
  // Ok so now we have the number of days in the month in $n and the day of the first Friday in $d
  // Time to loop around to process all fridays
    while ($d <= $n)
    {
  // Create a full date for the friday we are working on
    $selectedDay = sprintf("%04d-%02d-%02d", $year, $month, $d);
  
  // initialise the flag that tells us if this friday is in the newsletter list - we are assuming it
  // is not - but if we find it in th enext list we will set it to true
    $ontheList = false;

  // Loop through all the dates in the newsletter list (NB: we could have used a foreach for this as well)
    for ($q = 0; $q < count($newsletter_list); $q++) {
    // Check if the current newsletter list item matches our selected friday
      if ($selectedDay == $newsletter_list[$q]) {
      // and if so set the flag to true
    // NB: At this point we would want to exit the list because we have found the selected date
    // no use spinning the CPU's wheels checking the rest of the values in the list
    // we could either put a break statment here or modify the for loop to put a condition in the condition expression to 
    // check of $onthelist is still false
        $ontheList = true;
      }                                    
    }
    // If we get here and the flag is still false then the selected day is not on the list - so we add the selected day to our days array
    if ($ontheList == false) {
      $days[] = $selectedDay;
    }
    
  // Jump to the next Friday
    $d += 7;
    }
  }
  // And finally return the array containing all the fridays that don't appear on the newsletter list
  return $days;
}

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Julian HansenCommented:
Some other anomolies I noticed

You are passing $month to the function - but you never use this value because you immediately overwrite it in the for loop.
0
Ray PaseurCommented:
list($n,$d) = explode('-', date('t-d', strtotime("Friday, $year-$month")));

Open in new window

Any time you have code that looks like this, you have something that can lead to confusion.  The accumulation of closing parentheses is indicative of multiple function calls in a single line of code.  And in beginner programming that is almost always indicative of code that was copied from an external reference, usually without a good understanding of what the code was intended to do.

To deconstruct that line, first go to the innermost function call, which is strtotime(), and work your way out from there.  Its output is expected to be a unix timestamp (but could also be FALSE, which PHP will evaluate as if it were zero).  This value will be part of the arguments passed to date().  

The output of date() will be determined by the pattern 't-d' which will give you the number of days in the given month, followed by a dash, followed by the day of the month with a leading zero, if needed, to pad the day to 2 digits.  This will be returned in the form of a string, either 4 or 5 characters.  

This string will be passed to explode(), which will use the literal string dash '-' as a delimiter to create an array.  The zero position of the array will be the output from date('t') and the one position of the array will be the output from date('d').  

This array will be assigned to the PHP variables $n and $d by the list() statement.

That's a lot of moving parts for a single line of code.  For some reason, inexperienced programmers look at stuff like this and think, "cool."  More experienced programmers tend to avoid that kind of "cool" choosing instead to write programming that easy to read and debug, well-documented with comments, nicely formatted control structures, etc.  The computer doesn't care what you write as long as it functions properly.  But the people who read the code care, and they need to be able to understand your intent at a glance.  Those people include you, if you put the programming aside and come back to it a day, or even a few hours, later.

I have had enough bad experiences looking at incomprehensible code that I have come to believe that my own code should be easy to read and understand.  So while I tolerate a few compound statements like stacking date() and strtotime(), I generally require my code to do only one thing per line.  It's easier to test and it's easier to keep my thought processes in order when the code is laid out that way.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.