Calendarクラス

投稿者 peaco 3月 11, 2012

Pearのカレンダークラスはちょっと古いとか、別にビューは自分で書くから日付計算だけしてくれればいいなとか、そもそもpear install calendar-betaって、ベータかよ!とか、そういうことを思ったので、Pearのカレンダークラスを参考に作りました。
カレンダークラス

<?php
class Calendar
{
  private $year, $month, $day;
  private $prevYear, $prevMonth;
  private $nextYear, $nextMonth;
  public $week = array();
  private $timestamp;

  public function __construct($y = null, $m = null, $d = null, $firstDay = null, $is_padding = false)
  {
    $this->year = is_null($y) ? intval(date('Y')) : (int)$y;
    $this->month = is_null($m) ? intval(date('m')) : (int)$m;
    $this->day = is_null($d) ? intval(date('d')) : (int)$d;
    $this->is_padding = (bool)$is_padding;
    if (is_null($firstDay) || $firstDay < 0 || $firstDay > 6){
      $firstDay = 0;
    }
    $this->firstDay = $firstDay;

    $this->nextYear  = mktime(0, 0, 0, $this->month, 1, $this->year+1);
    $this->nextMonth = mktime(0, 0, 0, $this->month+1, 1, $this->year);
    $this->nextDay = mktime(0, 0, 0, $this->month, $this->day+1, $this->year);
    $this->prevYear  = mktime(0, 0, 0, $this->month, 1, $this->year-1);
    $this->prevMonth = mktime(0, 0, 0, $this->month-1, 1, $this->year);
    $this->prevDay = mktime(0, 0, 0, $this->month, $this->day-1, $this->year);

    $this->init();
  }

  /**
   * generate Calendar
   */
  private function init()
  {
    $this->timestamp = mktime(0, 0, 0, $this->month, $this->day, $this->year);

    // パディング
    if (date('w', $this->timestamp) != $this->firstDay){
      $prevMonth = date('t', mktime(0, 0, 0, $this->month-1, 1, $this->year)); // 先月の最終日
      if ($this->firstDay == 0){
        $paddings = date('w', $this->timestamp); // 始まりが月曜日
      } else {
        $paddings = 7-$this->firstDay+date('w', $this->timestamp);
        if ($paddings > 7){
          $paddings = $paddings % 7;
        }
      }
      // 先月のパディングすべき日から、先月末までパディングする
      for($i = $prevMonth-$paddings+1; $i <= $prevMonth; $i++){
        $thisTime = mktime(0, 0, 0, $this->month-1, $i, $this->year);
        $firstDay = false;
        if ($i == $prevMonth-$paddings){
          $firstDay = true;
        }
        $this->week[] = new Day($thisTime, $firstDay, false, $this->is_padding, false);
      }
    }

    // 今月の日付
    $counter = 1;
    for ($i = 1; $i <= date('t', $this->timestamp); $i++){
      $thisTime = mktime(0, 0, 0, $this->month, $i, $this->year);
      $firstDay = false;
      $lastDay = false;
      if (date('w', $thisTime) == $this->firstDay){
        $firstDay = true;
        $counter = 1;
      } else {
        if (($this->firstDay == 0 && date('w', $thisTime) == 6) || $this->firstDay-1 == date('w', $thisTime)){
          $lastDay = true;
        }
        $counter++;
      }
      $this->week[] = new Day($thisTime, $firstDay, $lastDay, true, true);
    }

    // パディング
    if ($lastDay == false){
      $lastW = date('w', $thisTime);
      echo $counter;
      for ($i = 1; $i <= 7-$counter; $i++){
        $time = mktime(0, 0, 0, $this->month+1, $i, $this->year);
        $lastDay = ($i == 7-$counter) ? true : false;
        $this->week[] = new Day($time, false, $lastDay, $this->is_padding, false);
      }
    }
  }

  /**
   * getter methods
   */
  public function getYear()
  {
    return $this->year;
  }

  public function getMonth()
  {
    return $this->month;
  }

  public function getDay()
  {
    return $this->day;
  }

  public function getPrevYear()
  {
    return $this->prevYear;
  }

  public function getPrevMonth()
  {
    return $this->prevMonth;
  }

  public function getNextYear()
  {
    return $this->nextYear;
  }

  public function getNextMonth()
  {
    return $this->nextMonth;
  }
}

class Day
{
  private $timestamp = null;
  private $firstDay = false;
  private $lastDay = false;
  private $is_display = true;
  private $is_thisMonth = true;
  private $y, $m, $d, $week;

  public function __construct($timestamp = 0, $firstDay = false, $lastDay = false, $is_display = true, $is_thisMonth = true)
  {
    $this->timestamp = $timestamp;
    $this->firstDay = $firstDay;
    $this->lastDay = $lastDay;
    $this->is_display = $is_display;
    $this->is_thisMonth = $is_thisMonth;

    $this->y = date('Y', $timestamp);
    $this->m = date('n', $timestamp);
    $this->d = date('j', $timestamp);
    $this->week = date('w', $timestamp);
  }

  /**
   * return Timestamp
   */
  public function getTimestamp()
  {
    return $this->timestamp;
  }

  /**
   * 今日?
   */
  public function isToday()
  {
    if (date('Ymd', $this->timestamp) == date('Ymd')){
      return true;
    } else {
      return false;
    }
  }

  /**
   * 日曜日?
   */
  public function isSunday()
  {
    if ($this->thisWeek() == 0){
      return true;
    } else {
      return false;
    }
  }

  /**
   * 土曜日?
   */
  public function isSaturday()
  {
    if ($this->thisWeek() == 6){
      return true;
    } else {
      return false;
    }
  }

  /**
   * 日オブジェクトの年を返す
   */
  public function thisYear()
  {
    return $this->y;
  }

  /**
   * 日オブジェクトの月を返す
   */
  public function thisMonth()
  {
    return $this->m;
  }

  /**
   * 日オブジェクトの日を返す
   */
  public function thisDay()
  {
    if ($this->is_display){
      return $this->d;
    } else {
      return null;
    }
  }

  /**
   * 日オブジェクトの曜日を返す
   */
   public function thisWeek()
   {
      return $this->week;
   }

  /**
   * この日オブジェクトが今月のものか調べる
   * 先月・来月をパディングしている日オブジェクトならfalseになる
   */
  public function isThisMonth()
  {
    return $this->is_thisMonth;
  }

  /**
   * この日オブジェクトが週のはじまりか調べる
   */
  public function isFirst()
  {
    return $this->firstDay;
  }

  /**
   * この日オブジェクトが週の終わりか調べる
   */
  public function isLast()
  {
    return $this->lastDay;
  }
}

使うとき

<php?
$cal = new Calendar(date('Y'), date('m'), 0, true);
php>

  <ul>
    <li><?php echo $cal->getPrevYear() ?>年 <?php echo $cal->getPrevMonth() ?> 月</li>
    <li><?php echo $cal->getYear() ?>年 <?php echo $cal->getMonth() ?>月</li>
    <li><?php echo $cal->getNextYear() ?>年 <?php echo $cal->getNextYear() ?>月</li>
  </ul>

  <table class="table table-bordered nopadding">
    <tr>
      <th class="sun">日</th>
      <th>月</th>
      <th>火</th>
      <th>水</th>
      <th>木</th>
      <th>金</th>
      <th class="sat">土</th>
    </tr>
<?php foreach ($cal->week as $week): ?>
  <?php if($week->isFirst()): ?>
    <tr>
  <?php endif ?>

  <?php if ($week->isThisMonth()): ?>
      <td class="
        <?php echo $week->isSunday()? 'sun' : ''; ?>
        <?php echo $week->isSaturday()? 'sat' : ''; ?>
        <?php echo $week->isToday()? ' today' : ''; ?>">
        <ul class="nav nav-list">
          <li class="active"><a href="#"><?php echo $week->thisDay(); ?></a></li>
        </ul>
      </td>
  <?php else: ?>
      <td class="empty
        <?php echo $week->isSunday()? 'sun' : ''; ?>
        <?php echo $week->isSaturday()? 'sat': ''; ?>">
        <ul class="nav nav-list">
          <li class="active"><a href="#"><?php echo $week->thisDay(); ?></a></li>
        </ul>
      </td>
  <?php endif ?>

  <?php if($week->isLast()): ?>
    </tr>
  <?php endif ?>

<?php endforeach ?>
  </table>

コンストラクタ引数

第1引数:カレンダーの年。デフォルト今年。
第2引数:カレンダーの月。デフォルト今月。
第3引数:初まり曜日の指定(0=月曜、6=土曜)。デフォルト日曜日。
第4引数:初週、終週に先月・来月の数字があったとき、表示するかどうか。デフォルト非表示

カレンダークラスのメソッド

int getYear(), getMonth(), getDay():コンストラクタに渡した値から生成した、年・月・日を数字で返す。
int getPrevYear(), getPrevMonth():先月の年・月を数字で返す。
int getNextYear(), getNextMonth():来月の年・月を数字で返す。

カレンダークラスを生成すると、指定したパラメタで、カレンダーの中身であるDayクラスのインスタンスを配列にしたものを作ります。(init()で作成)
これを、foreach等でループさせることで、カレンダーを表示していきます。
foreachでループさせる、Dayクラスのメソッド

timestamp getTimestamp():その日のタイムスタンプを返す。
bool isToday():今日かどうか(今、動かしているその日か)をboolで返す。
bool isSunday(), isSaturday():それぞれ日曜日か、土曜日かをboolで返す。
int thisYear(), thisMonth(), thisDay():それぞれ年月日を返す。日については、コンストラクタの第4引数でfalse指定の場合、nullが返る(今月のカレンダーから見える先月の終わりのほうや来月のはじめのほうの日付を非表示とする、という設定だから。)
int thisWeek():その日の曜日を返す。0=日曜、6=土曜
book isThisMonth():コンストラクタで指定した月かどうか調べる。trueなら今月、falseなら来月か先月。
bool isFirst():コンストラクタで指定した始まりの曜日からして、初めの曜日であるかどうか。例えば、0(日曜)を指定していたとき、日曜ならtrue
bool isLast():コンストラクタで指定した始まりの曜日からして、最後の曜日であるかどうか。例えば、0(日曜)を指定していたとき、土曜ならtrue

ひとまず、自分が使うのはこんなところなので、こんなクラスを作ってみました。

これをsymfonyのlib/uril/Calendar.phpとかに置いといたら、きっとPEARのCalendarクラスより簡単にカレンダーを使える気がする!

スタイル等適用したら、こんなかんじになります

投稿者 peaco

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です