打印

[php] php练习代码-日历

+效果


+无题
这次给自己的练习是写个日历的代码
开始以为很简单,到后来写着写着自己都晕了。
我的思路是来自学习C语言的一个练习题
那个练习题是要求在屏幕打印出如图所示图形:
引用:
        *      
      ***      
     *****      
    *******      
思路是:获取每月第一天和最后一天是星期几,用FOR循环输出,其他的也用FOR循环输出。

虽然我写出来了,但是感觉比较繁琐,而且可读性不强,PHP函数库的丰富没有体现出来。
我想还有改进的空间,大家来指点指点吧。

+代码
复制内容到剪贴板
代码:
<?
$y=$_GET['y'];
$m=$_GET['m'];
function calendar($y,$m){
$months=array('January','February','March','April','May','June','July','August','September','October','November','December');
$days=array('31','28','31','30','31','30','31','31','30','31','30','31');
    if($y==$today['year']&&$m==$today['mon'])
    {
        $today=getdate();
    }
    else
    {
        $date="1 ".$months[$m-1]." ".$y;
        $today=getdate(strtotime($date));
    }
//print_r($today);
$wd=$today['wday'];
$md=$today['mday'];
$m=$m?$m:$today['mon'];
$y=$y?$y:$today['year'];
if(!($y%4))
{$days[1]=29;}
if($md<=7)
   {
        $mfd=$wd-($md-1);
        $mfd=$mfd>0?$mfd:($mfd+7);
   }
   else
   {
       $mfd=(8-($md-$wd)%7)%7;
    }
$mld=($days[$m-1]-(8-$mfd))%7;
$mld=$mld?$mld:7;
$plusweek=($mld+7)%7?2:1;
$weeks=($days[$m-1]-(8-$mfd)-$mld)/7+$plusweek;
$forarray=array();
array_push($forarray,$mfd."7");
if($mld==7)
    {
    $lines=$weeks-1;
    }
else
    {
$lines=$weeks-2;
    }
    for($i=0;$i<$lines;$i++)
{array_push($forarray,"17");}
array_push($forarray,"1".$mld);
$ms=1;
if($m==1)
    {
    $prey=$y-1;
    $prem=12;
    $nexy=$y;
    $nexm=(12+($m+1))%12;
    $nexm=$nexm?$nexm:0;
    }
else if($m>1&&$m<12)
    {
        $nexy=$prey=$y;
        $prem=(12+($m-1))%12;
        $prem=$prem?$prem:12;
        $nexm=(12+($m+1))%12;
        $nexm=$nexm?$nexm:0;
    }
else
    {
    $prey=$y;
    $prem=(12+($m-1))%12;
    $prem=$prem?$prem:12;
    $nexy=$y+1;
    $nexm=1;
    }
echo "<table>\n<thead><tr><th colspan='1'><a href='?y={$prey}&m={$prem}'>-</a></th><th colspan='5'> {$y} {$months[$m-1]} </th><th colspan='1'><a href='?y={$nexy}&m={$nexm}'>+</a></th></tr><thead>\n<tbody><tr><td>一</td><td>二</td><td>三</td><td>四</td><td>五</td><td>六</td><td>日</td></tr>";
for($i=0;$i<count($forarray);$i++)
{
    $s=substr($forarray[$i],0,1);
    $e=substr($forarray[$i],1,2);
    echo "<tr>";
    for($j=1;$j<=$e;$j++)
    {
        if($j<$s)
        {echo "<td></td>";}
        else
        {echo "<td>{$ms}</td>";
        $ms++;}
    }
    echo "</tr>\n";
}
//echo "</tbody></table>";
//echo "{$m}月第一天是星期{$mfd}<br />";
//echo "{$m}月最后一天是星期{$mld}<br />";
//echo "{$m}月跨度{$weeks}周".count($forarray);
//print_r($forarray);
}
calendar($y,$m);
?>
附件: 您所在的用户组无法下载或查看附件,您需要注册/登录后才能查看!
ThinkPHP->博客
这是我写的,欢迎指正
复制内容到剪贴板
代码:
$m=isset($_GET['m'])?$_GET['m']:date('n');
$y=isset($_GET['y'])?$_GET['y']:date('Y');
function calendar($m,$y){
    $mtime=mktime(0,0,0,$m,1,$y);
    $f=date('w',$mtime)-1;
    $s='<table border="0" cellpadding="2" cellspacing="1"><tr><td colspan="7"><a href="?m='.$m.'&amp;y='.(intval($y)<=1971?'1971':intval($y)-1).'">&lt;&lt;</a>&nbsp;&nbsp;<a href="?m='.(intval($m)==1?'12':intval($m)-1).'&amp;y='.(intval($m)==1?(intval($y)-1):intval($y)).'">&lt;</a> '.intval($m).'/'.$y.' <a href="?m='.(intval($m)==12?'1':intval($m)+1).'&amp;y='.(intval($m)==12?(intval($y)+1):intval($y)).'">&gt;</a>&nbsp;&nbsp;<a href="?m='.$m.'&y='.(intval($y)>=2037?'2037':intval($y)+1).'">&gt;&gt;</a></td></tr><tr><td>日</td><td>一</td><td>二</td><td>三</td><td>四</td><td>五</td><td>六</td></tr>';
    for($i=0;$i<date('t',$mtime)+$f+1;$i++){
        if($i%7==0)$s.='<tr>';
        $s.='<td>';
        if($i>$f)$s.=$i-$f;
        $s.='</td>';
        if($i%7==6)$s.='</tr>';
    }
    if($i%7<6 && $i%7>0)$s.='<td colspan="'.(7-$i%7).'"></td></tr>';
    if($i%7==6)$s.='<td></td></tr>';
    return $s.'</table>';
}
echo calendar($m,$y);
火星人滚回火星去

迷你同学录
  piscdong 的代码简炼不少啊!
后面的同学们,继续来。
珍视拥有的、遗忘失去的。

TOP

认证您的手机,获得手机认证图标, 更多手机认证的好处
君子生非异也,善假于物也
用pear里的Calendar包
http://pear.php.net/package/Calendar/download
复制内容到剪贴板
代码:
<?php
require_once('Calendar/Month/Weekdays.php');
$year  = date("Y");
$month = date("m");
$monthCalendar = new Calendar_Month_Weekdays($year, $month, 0);
$monthCalendar->build();
echo "<table >\n";
echo "    <tr><td colspan='7' style='text-align:center'>$year, $month</td></tr>\n";
echo "    <tr><td>日</td><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td>\n";
while ($day = $monthCalendar->fetch())
{
    if($day->isFirst())    
    {
        echo "    <tr>";
    }
    
    if($day->isEmpty())
    {
        echo "<td>&nbsp;</td>";
    }
    else
    {
        echo "<td>".$day->thisDay()."</td>";
    }
    if($day->isLast())
    {
        echo "</tr>\n";
    }
}
echo "</table>";
?>
BTW,PHP5里面还有个Date类,有空再用那个试试

[ 本帖最后由 Fanbin 于 2007-12-9 11:45 编辑 ]
我也来献个丑。方法跟你的差不多,也是初学的时候写的。
复制内容到剪贴板
代码:
function getdata ($month="",$year="") {
if (!$month) $month = date("n");
if (!$year) $year = date("Y");
$weekday_cn = array("日","一","二","三","四","五","六");
if ($month !=2) {
   switch ($month) {
   case 1:
       $day = 31;
       break;
   case 3:
       $day = 31;
       break;
    case 4:
       $day = 30;
       break;
    case 5:
       $day = 31;
       break;
    case 6:
       $day = 30;
       break;
    case 7:
       $day = 31;
       break;
    case 8:
       $day = 31;
       break;
    case 9:
       $day = 30;
       break;
    case 10:
       $day = 31;
       break;
    case 11:
       $day = 30;
       break;
    case 12:
       $day = 31;
       break;
       }
     }else{
     if (date('L',mktime(0,0,0,$month,0,$year))) {
         $day = 29;
         }else{
         $day = 28;
         }
    }
        
$start_day = (int)date("w",mktime(0,0,0,$month,date("j",mktime(0,0,0,$month,1,$year)),$year));
$n=1;
$today=(int)date("j");
ob_start ();
echo "<table width=\"200\" border=\"0\" cellspacing=\"1\" cellpadding=\"2\" bgcolor=\"#CCCCCC\"><tr bgcolor=\"#FFFFFF\">";
echo "<th colspan=\"7\" scope=\"col\">".$year."年".$month."月"."</th></tr>\n";
echo "<tr align=\"center\"  bgcolor=\"#CCFFCC\">";
for ($i=0;$i<count($weekday_cn);$i++) {
    echo "<th scope=\"col\">".$weekday_cn[$i]."</th>\n";
    }
    echo "</tr>";
    
//&#1249;&#1211;
echo "<tr align=\"center\" bgcolor=\"#FFFFFF\"> \n";
for ($i=0;$i<$start_day;$i++)
echo "<td> </td>\n";
for ($j=0;$j<(7-$start_day);$j++) {
      $table_td= ($today ==$n)?("<td  bgcolor=\"#006699\"><span style=\"color:#FFFFFF;font-weight: bold;\">".$n."</span></td>"):("<td>".$n."</td>");
      echo $table_td;
      $n++;
      }
echo "</tr>\n";
$m=($n-1);
for($i=0;$i<(ceil($day-$m)/7);$i++){
  echo "<tr align=\"center\" bgcolor=\"#FFFFFF\"> ";
       for ($j=0;$j<7;$j++) {
             if ($n<=$day) {
                 $table_td= ($today ==$n)?("<td bgcolor=\"#006699\"><span style=\"color:#FFFFFF;font-weight: bold;\">".$n."</span></td>"):("<td>".$n."</td>");
                 echo $table_td;
                $n++;
                }else{
                   echo "<td> </td>\n";
                   }
                }
        echo "</tr>";
    }
   
echo "</table>";
return ob_get_flush ();

TOP

------------------------------------------------------------
做这个测试,纯属好玩,没任何其他的意思。
Calendar包懒的装,所以Fanbin的就没测试了
测试文件已打包,大家有兴趣的可以拿去玩玩
------------------------------------------------------------


看到大家都很积极,对上面几段代码做了个效率测试
+测试方法
<?
$starttime=microtime();
-------------------------------
日历函数,为了看出效果,重复十遍。
-------------------------------
$endtime=microtime();
$usedtime=$endtime-$starttime;
echo "总计用时:{$usedtime}";
?>
分别存为三文件,测试十遍。
+测试结果

+测试结论:
代码的简洁是要付出效率的代价(个人意见)。
附件: 您所在的用户组无法下载或查看附件,您需要注册/登录后才能查看!
ThinkPHP->博客

TOP

咦,没尝试Pear包的啊?
珍视拥有的、遗忘失去的。

TOP

不用测,我用Pear包的基本上应该是最慢的。

TOP

楼主预先定义了很多东西,这些根本不用自己去定义的,日期这东西是固定的
date()函数结合mktime() 可以得到一切东西
我觉得灵活运用两者即可得到日历了
阿权的书房:摄影/杂记/PHP/Flash
http://AsLibra.com

TOP

感谢楼上的意见
有空再精炼精炼
ThinkPHP->博客

TOP

复制内容到剪贴板
代码:
<?php
/**
* 日历
*
* Copyright(c) 2007 by 陈毅鑫(深空). All rights reserved
* To contact the author write to {@link mailto:shenkong@php.net}
* @author 陈毅鑫(深空)
*/
if (function_exists('date_default_timezone_set')) {
    date_default_timezone_set('Asia/Chongqing');
}
$date = isset($_GET['date']) ? $_GET['date'] : date('Y-m-d');
$date = getdate(strtotime($date));
$end = getdate(mktime(0, 0, 0, $date['mon'] + 1, 1, $date['year']) - 1);
$start = getdate(mktime(0, 0, 0, $date['mon'], 1, $date['year']));
$pre = date('Y-m-d', $start[0] - 1);
$next = date('Y-m-d', $end[0] + 86400);
$html = '<table border="1">';
$html .= '<tr>';
$html .= '<td><a href="' . $PHP_SELF . '?date=' . $pre . '">-</a></td>';
$html .= '<td colspan="5">' . $date['year'] . ';' . $date['month'] . '</td>';
$html .= '<td><a href="' . $PHP_SELF . '?date=' . $next . '">+</a></td>';
$html .= '</tr>';
$arr_tpl = array(0 => '', 1 => '', 2 => '', 3 => '', 4 => '', 5 => '', 6 => '');
$date_arr = array();
$j = 0;
for ($i = 0; $i < $end['mday']; $i++) {
    if (!isset($date_arr[$j])) {
        $date_arr[$j] = $arr_tpl;
    }
    $date_arr[$j][($i+$start['wday'])%7] = $i+1;
    if ($date_arr[$j][6]) {
        $j++;
    }
}
foreach ($date_arr as $value) {
    $html .= '<tr>';
    foreach ($value as $v) {
        if ($v) {
            if ($v == $date['mday']) {
                $html .= '<td><b>' . $v . '</b></td>';
            } else {
                $html .= '<td>' . $v . '</td>';
            }
        } else {
            $html .= '<td>&nbsp;</td>';
        }
    }
    $html .= '</tr>';
}
$html .= '</table>';
echo $html;
?>
抽空写了个,比较简单的^_^

[ 本帖最后由 深空 于 2007-12-22 13:05 编辑 ]

TOP