Как узнать количество понедельников или вторников между двумя датами? - PullRequest
13 голосов
/ 31 октября 2009

У меня есть даты начала и окончания.

Мне нужно узнать день, который является воскресеньем или понедельником и т. Д., Зависит от того, щелкнул ли пользователь по флажку.

Как я могу найти / рассчитать это в PHP?

Ответы [ 10 ]

9 голосов
/ 28 сентября 2010

Ответ от w35I3y был почти правильным, но я получал ошибки при использовании этой функции. Эта функция правильно рассчитывает количество понедельников или любого конкретного дня между двумя указанными датами:

/** 
* Counts the number occurrences of a certain day of the week between a start and end date
* The $start and $end variables must be in UTC format or you will get the wrong number 
* of days  when crossing daylight savings time
* @param - $day - the day of the week such as "Monday", "Tuesday"...
* @param - $start - a UTC timestamp representing the start date
* @param - $end - a UTC timestamp representing the end date
* @return Number of occurences of $day between $start and $end
*/
function countDays($day, $start, $end)
{        
    //get the day of the week for start and end dates (0-6)
    $w = array(date('w', $start), date('w', $end));

    //get partial week day count
    if ($w[0] < $w[1])
    {            
        $partialWeekCount = ($day >= $w[0] && $day <= $w[1]);
    }else if ($w[0] == $w[1])
    {
        $partialWeekCount = $w[0] == $day;
    }else
    {
        $partialWeekCount = ($day >= $w[0] || $day <= $w[1]);
    }

    //first count the number of complete weeks, then add 1 if $day falls in a partial week.
    return floor( ( $end-$start )/60/60/24/7) + $partialWeekCount;
}

Пример использования:

$start = strtotime("tuesday UTC");    
$end = strtotime("3 tuesday UTC");       
echo date("m/d/Y", $start). " - ".date("m/d/Y", $end). " has ". countDays(0, $start, $end). " Sundays";

Выводит что-то вроде: 28.09.2010 - 19.10.2010, 3 воскресенья.

8 голосов
/ 31 октября 2009

без петель и без рекурсивности

<?php
define('ONE_WEEK', 604800); // 7 * 24 * 60 * 60

function number_of_days($days, $start, $end) {
    $w = array(date('w', $start), date('w', $end));
    $x = floor(($end-$start)/ONE_WEEK);
    $sum = 0;

    for ($day = 0;$day < 7;++$day) {
        if ($days & pow(2, $day)) {
            $sum += $x + ($w[0] > $w[1]?$w[0] <= $day || $day <= $w[1] : $w[0] <= $day && $day <= $w[1]);
        }
    }

    return $sum;
}

//$start = $end = time();

// 0x10 == pow(2, 4) == 1 << 4 // THURSDAY
// 0x20 == pow(2, 5) == 1 << 5 // FRIDAY
echo number_of_days(0x01, $start, $end); // SUNDAY
echo number_of_days(pow(2, 0), $start, $end); // SUNDAY
echo number_of_days(0x02, $start, $end); // MONDAY
echo number_of_days(pow(2, 1), $start, $end); // MONDAY
echo number_of_days(0x04, $start, $end); // TUESDAY
echo number_of_days(1 << 2, $start, $end); // TUESDAY
echo number_of_days(0x08, $start, $end); // WEDNESDAY
echo number_of_days(1 << 3, $start, $end); // WEDNESDAY
echo number_of_days(0x10, $start, $end); // THURSDAY
echo number_of_days(0x20, $start, $end); // FRIDAY
echo number_of_days(0x40, $start, $end); // SATURDAY
echo number_of_days(0x01 | 0x40, $start, $end); // WEEKENDS : SUNDAY | SATURDAY
echo number_of_days(0x3E, $start, $end); // WORKDAYS : MONDAY | TUESDAY | WEDNESDAY | THURSDAY | FRIDAY
?>
7 голосов
/ 08 августа 2013

Этот вопрос только требует обновленного ответа, который использует классы PHP DateTime , поэтому вот оно: -

/**
 * @param String $dayName eg 'Mon', 'Tue' etc
 * @param DateTimeInterface $start
 * @param DateTimeInterface $end
 * @return int
 */
function countDaysByName($dayName, \DateTimeInterface $start, \DateTimeInterface $end)
{
    $count = 0;
    $interval = new \DateInterval('P1D');
    $period = new \DatePeriod($start, $interval, $end);

    foreach($period as $day){
        if($day->format('D') === ucfirst(substr($dayName, 0, 3))){
            $count ++;
        }
    }
    return $count;
}
6 голосов
/ 31 октября 2009

Вы можете создать функцию, которая рекурсивно использует strtotime () для подсчета количества дней. Так как strtotime("next monday"); работает просто отлично.

function daycount($day, $startdate, $counter)
{
    if($startdate >= time())
    {
        return $counter;
    }
    else
    {
        return daycount($day, strtotime("next ".$day, $startdate), ++$counter);
    }
}

echo daycount("monday", strtotime("01.01.2009"), 0);

Надеюсь, это то, что вы ищете :)

2 голосов
/ 30 декабря 2014

Для подсчета общей пятницы между двумя датами ##

$from_date=(2015-01-01);

$to_date=(2015-01-20);

while(strtotime($from_date) <= strtotime($to_date)){

    //5 for count Friday, 6 for Saturday , 7 for Sunday

    if(date("N",strtotime($from_date))==5){
        $counter++;
    }
    $from_date = date ("Y-m-d", strtotime("+1 day", strtotime($from_date)));

}

echo $counter;
2 голосов
/ 08 апреля 2011
<?php
$date = strtotime('2009-01-01');
$dateMax = strtotime('2009-02-23');

$nbr = 0;
while ($date < $dateMax) {
  var_dump(date('Y-m-d', $date));
  $nbr++;
  $date += 7 * 24 * 3600;
}
echo "<pre>";
 var_dump($nbr);
?>
0 голосов
/ 18 апреля 2018

Правильный счетчик дней. Это будет считать все дни с понедельника по воскресенье между 2 заданной датой

 <?php

    $startdate='2018-04-01';
    $enddate='2018-04-20';

    $mondayCount = 0;
    $tuesday = 0;
    $wednesday = 0;
    $thursday = 0;

    $friday = 0;
    $saturday = 0;
    $sunday = 0;

    $begin = new DateTime($startdate );
    $end = new DateTime( $enddate );
    $end = $end->modify( '+1 day' );

    $interval = new DateInterval('P1D');
    $daterange = new DatePeriod($begin, $interval ,$end);
    // looping each days from FROM and TO dates

    foreach($daterange as $date) {
        //$eachDate = $date->format("d-m-Y");
        echo $eachDateName = $date->format("l");
        switch ($eachDateName)
        {
            case 'Monday' :
                $mondayCount++;break;
            case 'Tuesday' :
                $tuesday++;break;
            case 'Wednesday' :
                $wednesday++;break;
            case 'Thursday' :
                $thursday++;break;
            case 'Friday' :
                $friday++;break;
            case 'Saturday' :
                $saturday++;break;
            case 'Sunday' :
                $sunday++;break;
        }

    }
    echo $mondayCount;echo "---";
    echo $tuesday;echo "---";
    echo $wednesday;echo "---";
    echo $thursday;echo "---";
    echo $friday;echo "----";
    echo $saturday;echo "---";
    echo $sunday;
?>

Надеюсь, это кому-нибудь поможет

0 голосов
/ 03 февраля 2013

w35l3y, кажется, работает хорошо, поэтому я проголосовал за него. Тем не менее, я предпочел что-то более легкое, с меньшим количеством математики и циклов (хотя не уверен, что это важно с точки зрения производительности). Я думаю, что я рассмотрел все возможные сценарии ... Вот что я придумал:

function numDays($sday, $eday, $i, $cnt) {
    if (($sday < $eday && $i >= $sday && $i <= $eday) || ($sday > $eday && ($i >= $sday || $i <= $eday))) {
        // partial week (implied by $sday != $eday), so $i (day iteration) may have occurred one more time
        // a) end day is ahead of start day; $i is within start/end of week range
        // b) start day is ahead of end day (i.e., Tue start, Sun end); $i is either in back half of first week or front half of second week
        $cnt++;
    } elseif ($sday == $eday && $i == $sday) {
        // start day and end day are the same, and $i is that day, i.e., Tue occurs twice from Tue-Tue (1 wk, so $wks = $cnt)
        $cnt++;
    }

    return $cnt;    // # of complete weeks + partial week, if applicable
}

Примечания: $ sday и $ eday - номера дней, соответствующие началу и концу проверяемого диапазона, а $ i - подсчитываемый номер дня (он у меня в цикле 0-6). Я переместил $ wks за пределы функции, так как бессмысленно каждый раз пересчитывать ее.

$wks = floor(($endstamp - $startstamp)/7*24*60*60);
$numDays = numDays($sday, $eday, $i, $wks);

Убедитесь, что начальные / конечные временные метки, которые вы сравниваете, имеют одинаковую настройку часового пояса, если таковая имеется, в противном случае вы всегда будете немного отключены с $ cnt и $ wks. (Я столкнулся с этим при подсчете от нескорректированного первого года до скорректированного дня / времени X.)

0 голосов
/ 10 апреля 2012
function daycount($day, $startdate, $enddate, $counter) {
    if($startdate >= $enddate) {
        return $counter-1;  // A hack to make this function return the correct number of days.
    } else {
        return $this->daycount($day, strtotime("next ".$day, $startdate), $enddate, ++$counter);
    }
}

Это другая версия первого ответа, которая принимает начальную и конечную точку и работает для меня. Кажется, что все примеры, приведенные на этой странице, возвращают ответ плюс дополнительный день по какой-то причине.

0 голосов
/ 31 октября 2009

Я получил ответ. Он работает только в воскресенье. Но я не знаю, как сделать это в течение других дней

<?php

// Define a constant of 1 day in seconds
define(ONE_DAY, 86400); 
date_default_timezone_set('America/New_York'); 

// Accepts two timestamps, start and end 
// Returns an array of timestamps that fall on a sunday 
function sundays_in_range($start, $end) {    
    echo date('N', $start);
    echo "<br/>";                     
    $days_until_sunday = date('w', $start) > 0 ? 7 - date('w', $start) : 0; 

    $date = $start + (ONE_DAY * $days_until_sunday); 
    $sundays = array(); 
    while ($date <= $end) { 
        array_push($sundays, $date); 
        $date += (7 * ONE_DAY); 
    } 
    return $sundays; 
} 

// Calculate some example dates. Today, and 30 days from now 
$start = time($start); 
$end = time($end) + (30 * ONE_DAY); 
echo ONE_DAY;
echo "<br/>";
 $count=0;
// Loop and output Y-m-d 
foreach (sundays_in_range($start, $end) as $sunday)
{
print "<option>".date("Y-m-d", $sunday)."</option><br/>";
 $count++;
 }

echo  $count;
?> 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...