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
https://forums.phpfreaks.com/topic/92514-like-array_fill-but-a-date-range/
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.

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;
}

?>

Archived

This topic is now archived and is closed to further replies.

×
×
  • 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.