Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > PHP: Общие вопросы > Календарь


Автор: CyClon 3.6.2007, 19:40
Захотелось написать календарь на PHP, задача не из самых простых, ибо нужно еще и хороший код.

В общем, давайте обмениваться идеями с реализацией самого простого календарика на PHP (т.е. без HTML, важен только PHP-код).

Вот что я наварганил:

Код
<?php

$time = time(); // $time = mktime(0, 0, 0, 2, 3, 2030);

$days = (date('w', $time) > 0) ? 7 - date('w', $time) + date('j', $time) % 7 : date('j', $time) % 7;
$print = ($days != 7) ? ($days < 7) ? date('t', $time - 2419200) - $days : date('t', $time - 2419200) - $days % 7 : 1;

echo date('d/m/Y  H:i:s', $time) . PHP_EOL . PHP_EOL;
echo 'ПН ВТ СР ЧТ ПТ СБ ВС' . PHP_EOL;

for ($week = 1; $week <= 6; $week++) {
    for ($day = 1; $day <= 7; $day++) {
        printf('%02d ', $print);
        if (($week == 1 && $print == date('t', $time - 2419200)) || ($week > 4 && $print == date('t', $time))) {
            $print = 0;
        }
        $print++;
    }
    if ($week > 3 && ($print < 15 || $print == date('t', $time) + 1)) {
        break;
    }
    echo PHP_EOL;
}

?>


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

Добавлено через 1 минуту и 9 секунд
Результат работы моего скрипта:

Код
03/06/2007  20:41:38

ПН ВТ СР ЧТ ПТ СБ ВС
28 29 30 31 01 02 03 
04 05 06 07 08 09 10 
11 12 13 14 15 16 17 
18 19 20 21 22 23 24 
25 26 27 28 29 30 01 

Автор: xolod 3.6.2007, 20:21
Функция:
Код

function buildCalendar($year, $month) {
 $weekDay = JDDayOfWeek(GregorianToJD($month, 1, $year), 0);
 if ($weekDay == 0) $weekDay = 7;
 $newDay = -($weekDay - 2);
 $calendar = array();
 for ($y = 0; $y < 6; $y++) {
   $row = array();
   $testEmpty = false;
   for ($x = 0; $x < 7; $x++, $newDay++) {
     if (checkdate($month, $newDay, $year)) {
       $row[] = $newDay;
       $testEmpty = true;
     } else {
       $row[] = '';
     }
   }
   if (!$testEmpty) break;
   $calendar[] = $row;
 }
 return $calendar;
}


Вывод, на текущий месяц-год (вы как хотите, а мне удобней html):
Код

$dateNow = getdate();
$calendarNow = buildCalendar($dateNow['year'], $dateNow['mon'] - 1);
echo('<table><thead><tr><td>пн</td><td>вт</td><td>ср</td><td>чт</td><td>пт</td><td>сб</td><td>вс</td></tr></thead><tbody>');
foreach($calendarNow as $rowNow) {echo('<tr>'); foreach($rowNow as $index => $day) {echo($day ? '<td align="center">'.$day.'</td>' : '<td>&nbsp;</td>');} echo('</tr>');}
echo('</tbody></table>');
break;


Из нашей старой книги. В свое время ломал голову куда дольше. Хотя в целом задача очень простая.

Автор: CyClon 3.6.2007, 20:51
Неплохая реализация, только не выводятся числа предыдущего месяца, не очень красиво вместо них видеть квадраты пустые smile

Автор: mikla 4.6.2007, 01:37
немного криво, но тож вариант )
Код

<?

function drawCalendar ( $mm , $yy )
{
    $days = array("","Пн","Вт","Ср","Чт","Пт","Сб","Вс");    
    $nDays = array(0,31,28,31,30,31,30,31,31,30,31,30,31);
    $nDays[2] = ($yy%4==0) ? 29 : 28;    
    $a = intval ((14-$mm) / 12);
    $y = intval ($yy - $a);
    $m = intval ($mm + 12*$a - 2);
    $dayNumber = (7000 + (1 + intval($y) + intval($y/4) - intval($y/100) + intval($y/400) + intval((31*$m)/12 ))) % 7;
    $cDoWeek = ($dayNumber!=0) ? $dayNumber : 7;        
?>
    
    <table border="1" align = "center">
    <tr>
    
<?
    for ($i=1;$i<=7;$i++)
    {
        if (($i>=1)&&($i<=5)) echo "<td id = \"weekdays\" > {$days[$i]} </td> "; else echo "<td id = \"holydays\" > {$days[$i]} </td> ";
        
    }
?> 
    </tr><tr> 
<?    
    for ($i=1; $i<$cDoWeek; $i++) echo "<td id = \"empty\">&nbsp</td>";    
?>

<?    
    $i=1;    
    while ($i<=$nDays[$mm])
    {        
        $id = (($cDoWeek<=5)&&($cDoWeek>=1)) ? 'weekdays' : 'holydays'; // определяем стиль ячейки.        
        echo "<td id = \"{$id}\"><a href = '#' >{$i} </a></td>"; 
        $cDoWeek++;
        $i++;
        if ($cDoWeek>7)    
        {    
            $cDoWeek=1; 
            echo "</tr><tr>"; 
        }
    }
    
    while ($cDoWeek<=7) 
    {
        echo "<td id = \"empty\">&nbsp</td>";    
        $cDoWeek++;
    }    
    echo "</tr></table>";
}
drawCalendar(2, 2007);
?>



Автор: pento 4.6.2007, 05:23
В книге Котерова PHP5 в  подлиннике описана процедура создания календаря

Автор: CyClon 4.6.2007, 12:46
Знаем мы эти процедуры %))) Нужен самый короткий, быстрый и красивый код smile

Автор: CyClon 4.6.2007, 13:03
Немного переделал, теперь это функция и она универсальна smile)) Т.е. можно выводить несколько календарей.

Код
<?php

function buildCalendar($year, $month)
{
    $time = mktime(0, 0, 0, $month, 1, $year);
    $days = (date('w', $time) > 0) ? 7 - date('w', $time) + date('j', $time) % 7 : date('j', $time) % 7;
    $print = ($days != 7) ? ($days < 7) ? date('t', $time - 2419200) - $days : date('t', $time - 2419200) - $days % 7 : 1;

    for ($week = 0; $week < 6; $week++) {
        for ($day = 0; $day < 7; $day++) {
            $calendar[$week][] = $print;
            if (($week == 0 && $print == date('t', $time - 2419200)) || ($week > 0 && $print == date('t', $time))) {
                $print = 0;
            }
            $print++;
        }
        if ($week > 2 && ($print < 14 || $print == date('t', $time) + 1)) {
            break;
        }
    }

    return $calendar;
}

$calendar = buildCalendar(2007, 6);

echo '<pre>' . PHP_EOL;
echo 'ПН ВТ СР ЧТ ПТ СБ ВС' . PHP_EOL;

foreach ($calendar as $week) {
    foreach ($week as $day) {
        printf('%02d ', $day);
    }
    echo PHP_EOL;
}

?>

Автор: aktuba 5.6.2007, 12:41
CyClon, а можно сделать с подсветкой? Т.е., например, дни прошлого и следующего месяца серым, текущего месяца, например, синим, а праздники, которые можно указать в базе или в текстовом файле - красным?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)