Захватите все среды в определенном месяце в PHP

Это функция, которую я пытаюсь написать:

function getWednesdays($month, $year) {
   // Returns an array of DateTimes representing all Wednesdays this month.
}

Любые идеи? Спасибо -

Ответ 1

С PHP5.3

function getWednesdays($y, $m)
{
    return new DatePeriod(
        new DateTime("first wednesday of $y-$m"),
        DateInterval::createFromDateString('next wednesday'),
        new DateTime("last day of $y-$m")
    );
}

Использование:

foreach (getWednesdays(2010, 11) as $wednesday) {
    echo $wednesday->format("l, Y-m-d\n");
}

Вывод:

Wednesday, 2010-11-03
Wednesday, 2010-11-10
Wednesday, 2010-11-17
Wednesday, 2010-11-24

Обратите внимание, что это исключает дату окончания, поэтому, если в последний день $y-$m будет среда, она не будет в списке. Вы должны добавить день до даты окончания, чтобы включить его. Чтобы включить его, измените относительный формат в конце даты на

new DateTime("next month $y-$m-01")

который затем установит дату окончания в первый день следующего месяца,


С PHP < 5.3

function getWednesdays($y, $m)
{
    $ts  = strtotime("first wednesday $y-$m-01");
    $end = strtotime("last wednesday $y-$m");
    $wednesdays = array();
    while($ts <= $end) {
        $wednesdays[] = $ts;
        $ts = strtotime('next wednesday', $ts);
    }
    return $wednesdays;
}

Использование:

foreach (getWednesdays(2010, 11) as $wednesday) {
    echo date("l, Y-m-d\n", $wednesday);
}

Тот же вывод, что и выше (Run on Codepad).

Обратите внимание, что этот не работает для любой версии до 5.3 из-за изменений в парсере относительных форматов. Если вы хотите использовать это с PHP 5.3+, вам нужно изменить first Wednesday $y-$m-01 на first Wednesday of $y-$m-01 (вспомнить "из" ). Кроме того, как и в версии DateTime, дата окончания не будет включена.


Дальнейшее чтение:

Ответ 2

Вы можете попробовать что-то вроде этого:

function getWednesdays($month, $year) {
    $base_date = strtotime($year . '-' . $month . '-01');
    $wed = strtotime('first wed of ' . date('F Y', $base_date));

    $wednesdays = array();

    do {
        $wednesdays[] = new DateTime(date('r', $wed));
        $wed = strtotime('+7 days', $wed);
    } while (date('m', $wed) == $month);

    return $wednesdays;
}

Ответ 3

Используйте эту функцию, чтобы получить общее количество дней в течение месяца

    function getTotalDays($year, $month, $day){
        $from = $year."-".$month."-01";
        $t=date("t",strtotime($from));

        for($i=1; $i<$t; $i++){
           if( strtolower(date("l",strtotime($year."-".$month."-".$i)))== $day){
             $count++;
          }
      }
      return $count;
 }

используйте как getTotalDays ('2014', '08', 'monday');

выведет 4

Но если вам нужны все даты в месяц в определенный день, используйте эту функцию

    function getTotalDatesArray($year, $month, $day){
        $date_ar=array();
        $from = $year."-".$month."-01";
        $t=date("t",strtotime($from));

        for($i=1; $i<$t; $i++){
           if( strtolower(date("l",strtotime($year."-".$month."-".$i)))== $day){
            $j= $i>9 ? $i: "0".$i;
             $date_ar[]=$year."-".$month."-".$j;
          }
      }
      return $date_ar;
 }

используйте как getTotalDatesArray ('2014', '08', 'monday');

выведет Array ([0] = > 2014-08-04 [1] = > 2014-08-11 [2] = > 2014-08-18 [3] = > 2014-08-25)

Ответ 4

Вероятно, более эффективный способ сделать это, но это работает:

<?php
function isWednesday($day, $month, $year)
{
    if (date('w', $date = mktime(0,0,0,$month,$day,$year)) == 3) {
        return $date;
    }
    return false;
}
function getWednesdays($month, $year)
{
    for ($day=1; $day<=7; $day++) {
        if ($date = isWednesday($day, $month, $year)) {
            break;
        }
    }
    $wednesdays = array();

    while (date('m',$date) == $month) {
        $wednesdays[] = $date;
        $day += 7;
        $date = isWednesday($day, $month, $year);
    }
    return $wednesdays;
}

Вы можете проверить это:

foreach (getWednesdays($argv[1], $argv[2]) as $date) {
    echo date("Y-m-d\n", $date);
}

$ php wednesdays.php 11 2010
2010-11-03
2010-11-10
2010-11-17
2010-11-24
$ php wednesdays.php 12 2010
2010-12-01
2010-12-08
2010-12-15
2010-12-22
2010-12-29
$ php wednesdays.php 2 2012
2012-02-01
2012-02-08
2012-02-15
2012-02-22
2012-02-29

S

Ответ 5

<?php
function wednesdays($month, $year)
{
  list($n,$d) = explode('-', date('t-d', strtotime("Wednesday, $year-$month")));
  $days = array();
  while ($d <= $n)
  {
    $days[] = sprintf("%04d-%02d-%02d", $year, $month, $d);
    $d += 7;
  }
  return $days;
}

var_dump(wednesdays(11, 2010));

?>

Но я очень рекомендую привыкнуть к функциям даты и времени PHP 5.3, если вы можете их использовать. (См. Ответ Гордона.)

Ответ 6

С PHP раньше 5.3 это решение не работает. Кажется, штамп первого дня больше, чем штамп последнего дня, который в конечном итоге заканчивает цикл в первом проходе.

Поскольку PHP вычисляет разницу во времени в полночь, это решение не работает, когда месяц начинается в этот день. И в некоторых случаях также не работает в последний день.

Я рассмотрел эти проблемы в следующем коде. И этот код можно использовать в любой день недели.

Решение было создано с помощью кода Eli в этом вопросе: Получить первую или последнюю пятницу в месяц

///// code starts here /////

function getWeekDates($year, $month, $day){
$tsInMonth = strtotime("$year-$month");
$monthNumber = (int)date("m",$tsInMonth);

$Names = array( 1=>"Sun", 2=>"Mon", 3=>"Tue", 4=>"Wed", 5=>"Thu", 6=>"Fri", 7=>"Sat" );

$ThisMonthTS = strtotime( date("Y-m-01", $tsInMonth ) );
$NextMonthTS = strtotime( date("Y-m-01", strtotime("next month", $tsInMonth) ) );

$weekDates = array();

for($Ord=1;$Ord<=5;$Ord++){
    $DateOfInterest = (-1 == $Ord) 
        ? strtotime( "last ".$Names[$day], $NextMonthTS ) 
        : strtotime( $Names[$day]." + ".($Ord-1)." weeks", $ThisMonthTS );

    ($Ord==5 && (int)date("m",$DateOfInterest)==(int)date("m",$NextMonthTS))
        ? false
        : $weekDates [] = $DateOfInterest;
}

return $weekDates;
}

///// Usage /////

foreach (getWeekDates("2010", "2", "2") as $day) {
    echo "<br>" . date("l, Y-m-d", $day);
}

///// End of code /////

Я надеюсь, что это поможет кому-то.

Ответ 7

Я переписал решение @Gordon на любой день

function get_dates_of_day($y, $m, $day_name)
{
    return new DatePeriod(
        new DateTime("first $day_name of $y-$m"),
        DateInterval::createFromDateString("next $day_name"),
        new DateTime("next month $y-$m-01")
        );
}

Теперь вы можете просто сделать get_dates_of_day('2015','08','wednesday') и использовать то же самое, чтобы получать даты в течение любого дня в данном месяце.

Ответ 8

Я написал для этого следующий код... и он отлично работает для меня

function get_month_date($year, $month, $day) {
$monthdays = date('t', mktime(0, 0, 0, $month, 1, $year));
$dates = array();
for($i = 0; $i <= $monthdays; $i++ ) {
    if($day == date('l', mktime(0, 0, 0, $month, 1+$i, $year)) && $month == date('n', mktime(0, 0, 0, $month, 1+$i, $year))) {
    $dates[] = date('Y-m-d', mktime(0, 0, 0, $month, 1+$i, $year));
    }
}
return $dates; }

Мы можем использовать его как:

$days = get_month_date($year, $month, 'Wednesday');

Он вернет массив всех дат среды в указанный месяц и год

Ответ 9

Вот пример

function getSundays($y,$m){ 
    $date = "$y-$m-01";
    $first_day = date('N',strtotime($date));
    $first_day = 7 - $first_day + 1;
    $last_day =  date('t',strtotime($date));
    $days = array();
    for($i=$first_day; $i<=$last_day; $i=$i+7 ){
        $days[] = $i;
    }
    return  $days;
}

$days = getSundays(2016,04);
print_r($days);

Ответ 10

Попробуйте этот, чтобы получить все среды в текущем месяце.

$month  = date('m');
$year  = date('Y');
function getDays($year,$month){ 
 $days = cal_days_in_month(CAL_GREGORIAN, $month,$year);
 $wed = array();
 for($i = 1; $i<= $days; $i++){
 $day  = date('Y-m-'.$i);
 $result = date("D", strtotime($day));
 if($result == "Wed"){  
 $wed[] = date("Y-m-d", strtotime($day)). " ".$result."<br>";
 }  
}
 return  $wed;
}
$wed = getDays($year,$month);
print_r($wed);

Ответ 11

Если DateTime не указан, вам нужно знать день для одной даты - например, начало эпохи unix (1 января 1970 г.).

Отправляясь оттуда, вы просто найдете первую среду, а оттуда найдете свой месяц. Имейте в виду високосные годы, и вы хороши.

Очевидно, что это не самый эффективный алгоритм в мире, но он выполнит эту работу.