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?
 
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
 
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
Cloud Class® Course: Certified Penetration Testing

This CPTE Certified Penetration Testing Engineer course covers everything you need to know about becoming a Certified Penetration Testing Engineer. Career Path: Professional roles include Ethical Hackers, Security Consultants, System Administrators, and Chief Security Officers.

 
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
 
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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.