본문 바로가기
개발 응용/PHP

PHP - 달력(Calander)

by 륀두 2020. 5. 7.
반응형

php를 이용하여 달력을 만들어 보았다.

참고한 소스코드는 다음과 같다.

<?php
//---- 오늘 날짜
$thisyear = date('Y'); // 4자리 연도
$thismonth = date('n'); // 0을 포함하지 않는 월
$today = date('j'); // 0을 포함하지 않는 일

//------ $year, $month 값이 없으면 현재 날짜
$year = isset($_GET['year']) ? $_GET['year'] : $thisyear;
$month = isset($_GET['month']) ? $_GET['month'] : $thismonth;
$day = isset($_GET['day']) ? $_GET['day'] : $today;

$prev_month = $month - 1;
$next_month = $month + 1;
$prev_year = $next_year = $year;
if ($month == 1) {
    $prev_month = 12;
    $prev_year = $year - 1;
} else if ($month == 12) {
    $next_month = 1;
    $next_year = $year + 1;
}
$preyear = $year - 1;
$nextyear = $year + 1;

$predate = date("Y-m-d", mktime(0, 0, 0, $month - 1, 1, $year));
$nextdate = date("Y-m-d", mktime(0, 0, 0, $month + 1, 1, $year));

// 1. 총일수 구하기
$max_day = date('t', mktime(0, 0, 0, $month, 1, $year)); // 해당월의 마지막 날짜
//echo '총요일수'.$max_day.'<br />';

// 2. 시작요일 구하기
$start_week = date("w", mktime(0, 0, 0, $month, 1, $year)); // 일요일 0, 토요일 6

// 3. 총 몇 주인지 구하기
$total_week = ceil(($max_day + $start_week) / 7);

// 4. 마지막 요일 구하기
$last_week = date('w', mktime(0, 0, 0, $month, $max_day, $year));
?>

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Bootstrap Example</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">
  <style>
    font.holy {font-family: tahoma;font-size: 20px;color: #FF6C21;}
    font.blue {font-family: tahoma;font-size: 20px;color: #0000FF;}
    font.black {font-family: tahoma;font-size: 20px;color: #000000;}
  </style>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
  <script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<table class="table table-bordered table-responsive">
  <tr align="center" >
    <td>
        <a href=<?php echo 'index.php?year='.$preyear.'&month='.$month . '&day=1'; ?>>◀◀</a>
    </td>
    <td>
        <a href=<?php echo 'index.php?year='.$prev_year.'&month='.$prev_month . '&day=1'; ?>>◀</a>
    </td>
    <td height="50" bgcolor="#FFFFFF" colspan="3">
        <a href=<?php echo 'index.php?year=' . $thisyear . '&month=' . $thismonth . '&day=1'; ?>>
        <?php echo "&nbsp;&nbsp;" . $year . '년 ' . $month . '월 ' . "&nbsp;&nbsp;"; ?></a>
    </td>
    <td>
        <a href=<?php echo 'index.php?year='.$next_year.'&month='.$next_month.'&day=1'; ?>>▶</a>
    </td>
    <td>
        <a href=<?php echo 'index.php?year='.$nextyear.'&month='.$month.'&day=1'; ?>>▶▶</a>
    </td>
  </tr>
  <tr class="info">
    <th hight="30">일</td>
    <th>월</th>
    <th>화</th>
    <th>수</th>
    <th>목</th>
    <th>금</th>
    <th>토</th>
  </tr>

  <?php
    // 5. 화면에 표시할 화면의 초기값을 1로 설정
    $day=1;

    // 6. 총 주 수에 맞춰서 세로줄 만들기
    for($i=1; $i <= $total_week; $i++){?>
  <tr>
    <?php
    // 7. 총 가로칸 만들기
    for ($j = 0; $j < 7; $j++) {
        // 8. 첫번째 주이고 시작요일보다 $j가 작거나 마지막주이고 $j가 마지막 요일보다 크면 표시하지 않음
        echo '<td height="50" valign="top">';
        if (!(($i == 1 && $j < $start_week) || ($i == $total_week && $j > $last_week))) {

            if ($j == 0) {
                // 9. $j가 0이면 일요일이므로 빨간색
                $style = "holy";
            } else if ($j == 6) {
                // 10. $j가 0이면 토요일이므로 파란색
                $style = "blue";
            } else {
                // 11. 그외는 평일이므로 검정색
                $style = "black";
            }

            // 12. 오늘 날짜면 굵은 글씨
            if ($year == $thisyear && $month == $thismonth && $day == date("j")) {
                // 13. 날짜 출력
                echo '<font class='.$style.'>';
                echo $day;
                echo '</font>';
            } else {
                echo '<font class='.$style.'>';
                echo $day;
                echo '</font>';
            }
            // 14. 날짜 증가
            $day++;
        }
        echo '</td>';
    }
 ?>
  </tr>
  <?php } ?>
</table>
</div>

</body>
</html>

출처: https://link2me.tistory.com/1543 [소소한 일상 및 업무TIP 다루기]

다음은 코드를 그대로 실행했을때 화면이다.

 

 

이대로 써도 훌륭하지만 공부하는 입장에서 괜히 DateTime이라는 클래스를 사용하여 똑같이 만들어 보고 싶어졌다.

DateTime클래스에 대한 설명은 다음 링크를 참조하면 된다.

https://www.php.net/manual/en/class.datetime.php

PHP: DateTime - Manual

format($formato_final);        }        public function format(string $data, string $formato_final){            return (new DateTime($data))->format($formato_final);        }                public function add(string $data_inicio, array $add = [0,0,0,0,0,0

www.php.net

DateTime 객체는다음과 같이 사용할 수 있다.

$date = new DateTime(); //현재의 날짜와 시간 리턴

$date1 = new DateTime("2020-05-05"); //2020년 05월 05일 리턴

print_r($date);
//DateTime Object ( [date] => 2020-05-07 09:42:01.886926 [timezone_type] => 3 [timezone] => Asia/Seoul )

print_r($date1);
//DateTime Object ( [date] => 2020-05-05 00:00:00.000000 [timezone_type] => 3 [timezone] => Asia/Seoul )


 echo로 출력하려면 format 메소드를 사용하여야 한다.

echo $date->format('Y-m-d'); //2020-05-07

echo $date1->format('Y'); //2020

format에 주어지는 인자는 date()와 동일하게 작동한다.

인자는 다음을 참고하여 여러가지로 출력할 수 있다.

https://ymw0210.tistory.com/27?category=829336

PHP - 날짜와 시간 함수

1 .날짜와 시간의 형식화 date() 함수는 전달받은 형식에 맞춰 날짜와 시간 정보를 문자열로 반환합니다. date() 함수에 인수로 전달할 수 있는 날짜와 시간 표현의 형식은 다음과 같습니다. 형태 설

ymw0210.tistory.com

DateTime을 다루다가 안 사실이지만 서로 다른 날짜가 필요하면 클래스를 2개를 선언해야 한다.

예를 들어

//date()함수를 사용할 경우
$date1= date("Y-m-d", mktime(0, 0, 0, 4, 1, 2020)); //2020-04-01
$date2 = date("Y-m-d", mktime(0, 0, 0, 6, 1, 2020)); //2020-06-01

//DateTime객체를 사용할 경우
//날짜 설정
$date1 = new DateTime("2020-04-01");
$date2 = new DateTime("2020-06-01");

//출력
echo $date1->format("Y-m-d"); //2020-04-01
echo $date2->format("Y-m-d"); //2020-06-01

이와 같이 코드가 늘어나게 되어 굳이 이걸 사용해야 하나 하는 생각도 든다. 하지만 DateTime을 사용하면 날짜의 계산이나 비교가 용이하고 알아보기 쉽기 때문에 조금 번거롭더라도 DateTime 클래스를 사용해보자.

위의 달력 소스를 DateTime을 사용하여 바꿔보았다.

// 캘린더 변수
$currentDate = new DateTime();

   //---- 오늘 날짜
   $thisyear = $currentDate->format('Y'); // 4자리 연도
   $thismonth = $currentDate->format('n'); // 0을 포함하지 않는 월
   $today = $currentDate->format('j'); // 0을 포함하지 않는 일
 
   //------ $year, $month 값이 없으면 현재 날짜
   $year = isset($_GET['year']) ? $_GET['year'] : $thisyear;
   $month = isset($_GET['month']) ? $_GET['month'] : $thismonth;
   $day = isset($_GET['day']) ? $_GET['day'] : $today;

   $prev_month = $month - 1;
   $next_month = $month + 1;
   $prev_year = $next_year = $year;
     
   if ($month == 1) {
       $prev_month = 12;
       $prev_year = $year - 1;
   } elseif ($month == 12) {
       $next_month = 1;
       $next_year = $year + 1;
   }

   $preyear = $year - 1;
   $nextyear = $year + 1;
   
   $preMonthClass = new DateTime();
   $currentMonthClass = new DateTime();
   $nextMonthClass = new DateTime();
     
   $preMonthClass->setDate($year, ($month - 1), "1");
   $currentMonthClass->setDate($year, $month, "1");
   $nextMonthClass->setDate($year, ($month + 1), "1");

   $predate = $preMonthClass->format("Y-m-d");
   $nextdate = $nextMonthClass->format("Y-m-d");

   // 1. 총일수 구하기
   $max_day = $currentMonthClass->format('t'); // 해당월의 마지막 날짜
   //echo '총요일수'.$max_day.'<br />';
   
   // 2. 시작요일 구하기
   $start_week = $currentMonthClass->format("w"); // 일요일 0, 토요일 6

   // 3. 총 몇 주인지 구하기
   $total_week = ceil(($max_day + $start_week) / 7);
   
   // 4. 마지막 요일 구하기
   $lastDateClass = new DateTime();
   $lastDateClass->setDate($year, $month, $max_day);
   $last_week = $lastDateClass->format('w');

윗부분의 php소스코드만 바꿔주면 된다. 

$predate = date("Y-m-d", mktime(0, 0, 0, $month - 1, 1, $year));
$nextdate = date("Y-m-d", mktime(0, 0, 0, $month + 1, 1, $year));

이 코드가 

$preMonthClass = new DateTime();
$currentMonthClass = new DateTime();
$nextMonthClass = new DateTime();
  
$preMonthClass->setDate($year, ($month - 1), "1");
$currentMonthClass->setDate($year, $month, "1");
$nextMonthClass->setDate($year, ($month + 1), "1");

$predate = $preMonthClass->format("Y-m-d");
$nextdate = $nextMonthClass->format("Y-m-d");

이렇게 바뀌면서 좀더 줄수가 많아졌다. DateTime에서는 mktime()의 역할을 대신하는 setDate메소드를 사용하였다.

나는 mktime()함수가 눈에 잘 안들어와서 DateTime으로 짠 코드가 조금은 길더라도 가독성이 좋은듯 하다.

(mktime(시,분,초, 달, 일, 연도)순서가 머릿속에 잘 안들어온다. ㅠ)

줄수가 많아지는게 싫으신 분들은 이전처럼 date()와 mktime을 사용해도 될것같다.

아직 모든 DateTime의 기능들을 다 써보진 않았지만 이렇게 클래스로 만들어 놓은 이유가 있을것 같다. 쓰다보면 익숙해 질듯 하다.

반응형

'개발 응용 > PHP' 카테고리의 다른 글

PHP - 페이지 클래스(Pagination)  (0) 2020.04.28