SolvedPrivate

List of Fridays

Posted on 2013-07-12
6
227 Views
Last Modified: 2013-08-11
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

0
Comment
Question by:maeve100
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 2
6 Comments
 
LVL 110

Expert Comment

by:Ray Paseur
ID: 39322418
0
 
LVL 110

Expert Comment

by:Ray Paseur
ID: 39322419
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
 
LVL 110

Assisted Solution

by:Ray Paseur
Ray Paseur earned 250 total points
ID: 39322457
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
Salesforce Made Easy to Use

On-screen guidance at the moment of need enables you & your employees to focus on the core, you can now boost your adoption rates swiftly and simply with one easy tool.

 
LVL 57

Accepted Solution

by:
Julian Hansen earned 250 total points
ID: 39322969
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
 
LVL 57

Expert Comment

by:Julian Hansen
ID: 39322970
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
 
LVL 110

Expert Comment

by:Ray Paseur
ID: 39323382
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

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Password hashing is better than message digests or encryption, and you should be using it instead of message digests or encryption.  Find out why and how in this article, which supplements the original article on PHP Client Registration, Login, Logo…
Nothing in an HTTP request can be trusted, including HTTP headers and form data.  A form token is a tool that can be used to guard against request forgeries (CSRF).  This article shows an improved approach to form tokens, making it more difficult to…
Learn how to match and substitute tagged data using PHP regular expressions. Demonstrated on Windows 7, but also applies to other operating systems. Demonstrated technique applies to PHP (all versions) and Firefox, but very similar techniques will w…
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.

729 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question