Jump to content

Like array_fill() but a date range


fnairb

Recommended Posts

So here is my challenge.  I need to load an array with date strings.  That is, given a start date, end date, and frequency spit out an array of person friendly date strings. I have used epoc with some success (See Attempt 1) and strtotime() works just fine (See: Attempt 2).  However, it is just too slow.  There has to be a better way to do this.

 

Attempt 1:  Use Epoc

 

The fillEpoc() function defined below just loops through a range of epocs incrementing by the given frequency.  It worked great for quite a while but then there is a nasty little shift in time.

 

$filled = fillEpoc('2007-10-21', '2008-01-21', 86400);

print_r($filled);

 

With an output of:  (notice the unexpected shift at [14])

 

Array

(

    \[0] => 2007-10-21 00:00

    [1] => 2007-10-22 00:00

    ...

    [14] => 2007-11-04 00:00

    [15] => 2007-11-04 23:00

    [16] => 2007-11-05 23:00

    ...

)

 

Attempt 2: use strtotime()

 

The fillStrToTime() function works as expected.  However, it really seems to be overkill.  With large date ranges or small frequencies it takes too long to complete for comfort.

 

 

Sample Code:

 

function fillEpoc ($startDate, $endDate, $frequency) {

  $dates = array();

  $startEpoc = strtotime($startDate);

  $endEpoc  = strtotime($endDate);

 

  for($i = $startEpoc; $i <= $endEpoc; $i += $frequency){

    $dates[] = date('Y-m-d H:i', $i);

  }

return $dates;

}

 

 

function fillStrToTime($startDate, $endDate, $frequency) {

  $dates = array();

  $startEpoc = strtotime($startDate);

  $endEpoc  = strtotime($endDate);

 

  $steps = ($endEpoc - $startEpoc) / $frequency;

  switch(frequency) {

    case 86400: $step = 1; $step_unit = ' days'; break;

    case 3600: $step = 1; $step_unit = ' hours'; break;

    case 300: $step = 5; $step_unit = ' minutes'; break;

    default: $step = $frequency; $step_unit = ' seconds';

  }

  for($i = 0; $i <= $steps; $i++){

    $e = strtotime(($i * $step) . $step_unit, $startEpoc);

    $dates[] = date('Y-m-d H:i', $e);

  }

  return $dates;

}

 

Link to comment
Share on other sites

The results are accurate but not what I am looking for.  The goal in this particular example is to generate a series of labels not to generate a series of accurate date representations.  So while the inclusion of daylight savings time is accurate it is not helping me generate the desired output.

Link to comment
Share on other sites

Personally I would changethe function to use something other than seconds, but since you didn't specify what flexibility it needed I didn't change that.

 

<?php

function fillEpoc($startDate, $endDate, $frequency) {
  $dates = array();
  $startEpoc = strtotime($startDate);
  $endEpoc  = strtotime($endDate);

  $newdateEpoc = $startEpoc;
  $year = date('Y', $startEpoc);
  $month = date('m', $startEpoc);
  $day = date('d', $startEpoc);
  $hours = date('H', $startEpoc);
  $minutes = date('i', $startEpoc);
  $seconds = date('s', $startEpoc);

  while($newdateEpoc <= $endEpoc){
    $dates[] = date('Y-m-d H:i:s', $newdateEpoc);
    $seconds = $seconds + $frequency;
    $newdateEpoc = mktime($hours, $minutes, $seconds, $month, $day, $year);
  }
  return $dates;
}

?>

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.