开发者

PHP create range of dates

开发者 https://www.devze.com 2023-03-08 05:29 出处:网络
Starting with a date in this format: 2011-05-01 09:00:00, how can I create an array that contains all office hours (09:00 to 17:00) for all working days of the year (so excluding all Saturday and Sund

Starting with a date in this format: 2011-05-01 09:00:00, how can I create an array that contains all office hours (09:00 to 17:00) for all working days of the year (so excluding all Saturday and Sundays). What I want to arrive to is something like this:

2011-05-01 09:00:00
2011-05-01 10:00:00
2011-05-01 11:00:00
2011-05-01 12:00:00
2011-05-01 13:00:00
2011-05-01 14:00:00
2011-05-01 15:00:00
2011-05-01 16:00:00
2011-05-01 17:00:00
//next day, starting at 09:00 and ending at 17:00
2011-05-02 09:00:00
...
2011-05-02 17:00:00
//until the last day of the year from 09:00 to 17:开发者_StackOverflow00
2011-12-31 09:00:00
...
2011-12-31 17:00:00

The start date will be the first of the current month at with 09:00 as time and the very last date (last element of the array) will always be 17:00 on the last day of the year.

Again, weekends should be excluded.

Pseudocode idea: I thought of something like strtotime($start, "+1 one hour") with a check for "if smaller than 17:00" but it doesn't seem to be that simple.


How about this:

$start = strtotime('2011-05-01');
$end = strtotime('2011-12-31');

$times = array();

for ($i = $start; $i <= $end; $i += 24 * 3600)
{
    if (date("D", $i) == "Sun" || date("D", $i) == "Sat")
    {
        continue;
    }

    for ($j = 9; $j <= 17; $j++)
    {
        $times []= date("Y-m-d $j:00:00", $i);
    }
}

The outer loop iterates through all the days in the given time period. In the outer loop, we check to see if the day is either Saturday or Sunday (a weekend), and if it is, we skip that day. If it's not a weekend, we loop through all the valid hours, adding the full date and time to the array as we go.


Some tips:

  1. date("G", $some_timestamp) gives you the hour of the day in 24-hour format
  2. date("N", $some_timestamp) gives you the day of the week, 1 (for Monday) through 7 (for Sunday)

Take a look at the php manual for date.

Edit: You can pick any start timestamp and add 3600 to add one hour, if your hour is greater than 17, you can add a bigger step to go right to the next morning, same for a weekend, and just do a while ($timestamp < $end_timestamp) {}


I'd encourage you to use the wonderful DateTime class and its related classes. Here, you can make good use of DatePeriod:

<?php

$now = new DateTime('today'); // starting time 0.00 this morning
$endOfYear = new DateTime('31 December this year 23:00'); // end time
$interval = new DateInterval('PT1H'); // frequency -- every hour

$times = array();

foreach (new DatePeriod($now, $interval, $endOfYear ) as $datetime) {
// $datetime is a DateTime object for the hour and time in question
    $dow = $datetime->format('w'); // 0 is Sunday
    if (($dow == '0') || ($dow == '6')) {
        continue; // miss Saturday and Sunday out
    }

    $time = $datetime->format('G'); // hour without leading 0
    if (($time < '9') || ($time > '17')) {
        continue;
    }

    $times[] = $datetime->format('r'); // output format
}

var_dump($times);

Obviously there are various aspects of this that you can configure, especially the output format. Depending on your purpose, you may prefer to put the DateTime objects themselves into the array.


$datetime = new DateTime(); // Set your start date here
do { // Iterate over .. dont know, a long time?
  do { // Iterate over the week ...
    $datetime->setTime(9,0,0);
    do { // Iterate over the hours ...
      echo $datetime->format('c') . PHP_EOL; // Do something with $datetime here
      $datetime->add(new DateInterval('PT1H'));
    } while ($datetime->format('G') < 18); // .. till < 18
    $datetime->add(new DateInterval('P1D')); // next day
  } while (!in_array($datetime->format('w'), array('0','6'))); // until we hit sunday or saturday
  $datetime->add(new DateInterval('P2D')); // next monday
} while (true); // replace with your "end" expression

Currently untested.

You can use the common interval-strings (like 1 hour and so on) too http://php.net/dateinterval.createfromdatestring


You could calculate your dates with two nested loops and generate the string with date().


I would just loop through all dates, incremented by hour, from now until the end of the year, as follows (pseudocode, obviously):

for n = now until end of year
    if (date(n) is between 9:00 and 17:00) AND (if date(n) is not sat or sun)
        add to array
    end if
    increment n by 1 hour
end


Here is a solution which should be reasonably fast since it uses no string comparisons and has only two function calls inside the loops:

function hours()
{
    $start = mktime(0, 0, 0, date('n'), 1, date('Y'));
    $end = mktime(0, 0, 0, 1, 1, date('Y') + 1);
    $wday = date('w', $start);
    $result = array();
    for ($t = $start; $t < $end; $t += 3600 * 24) {
        if (($wday > 0) && ($wday < 6)) {
            for ($hour = 9; $hour <= 17; $hour++) {
                $result[] = date('Y-m-d', $t) . sprintf(' %02d:00:00', $hour);
            }
        }
        $wday = ($wday + 1) % 7;
    }
    return $result;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号