자바스크립트 기능 제작, 달력 (Javascript Calendar)

2015.03.27 01:28
저자 : Kurien

자바스크립트 기능 제작, 달력


오늘은 자바스크립트 달력을 만들어 왔습니다!

갑작스럽게 이런 기능을 만든 이유는 일하다가 사용할 일이 생겨서죠... ㅋ


단순하게 월 별로 이동할 수 있는 기능만 만들었습니다.


일단 스크립트를 보면서 설명 드리죠.



calendar01.zip

이 코드를 사용, 무단 배포 하는 것은 내부의 주석은 삭제하지 않았을 때만 가능합니다.


function kCalendar(id, date) {

var kCalendar = document.getElementById(id);


if( typeof( date ) !== 'undefined' ) {

date = date.split('-');

date[1] = date[1] - 1;

date = new Date(date[0], date[1], date[2]);

} else {

var date = new Date();

}

var currentYear = date.getFullYear();

//년도를 구함


var currentMonth = date.getMonth() + 1;

//연을 구함. 월은 0부터 시작하므로 +1, 12월은 11을 출력


var currentDate = date.getDate();

//오늘 일자.


date.setDate(1);

var currentDay = date.getDay();

//이번달 1일의 요일은 출력. 0은 일요일 6은 토요일


var dateString = new Array('sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat');

var lastDate = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

if( (currentYear % 4 === 0 && currentYear % 100 !== 0) || currentYear % 400 === 0 )

lastDate[1] = 29;

//각 달의 마지막 일을 계산, 윤년의 경우 년도가 4의 배수이고 100의 배수가 아닐 때 혹은 400의 배수일 때 2월달이 29일 임.


var currentLastDate = lastDate[currentMonth-1];

var week = Math.ceil( ( currentDay + currentLastDate ) / 7 );

//총 몇 주인지 구함.


if(currentMonth != 1)

var prevDate = currentYear + '-' + ( currentMonth - 1 ) + '-' + currentDate;

else

var prevDate = ( currentYear - 1 ) + '-' + 12 + '-' + currentDate;

//만약 이번달이 1월이라면 1년 전 12월로 출력.


if(currentMonth != 12) 

var nextDate = currentYear + '-' + ( currentMonth + 1 ) + '-' + currentDate;

else

var nextDate = ( currentYear + 1 ) + '-' + 1 + '-' + currentDate;

//만약 이번달이 12월이라면 1년 후 1월로 출력.



if( currentMonth < 10 )

var currentMonth = '0' + currentMonth;

//10월 이하라면 앞에 0을 붙여준다.


var calendar = '';


calendar += '<div id="header">';

calendar += ' <span><a href="#" class="button left" onclick="kCalendar(\'' +  id + '\', \'' + prevDate + '\')"><</a></span>';

calendar += ' <span id="date">' + currentYear + '년 ' + currentMonth + '월</span>';

calendar += ' <span><a href="#" class="button right" onclick="kCalendar(\'' + id + '\', \'' + nextDate + '\')">></a></span>';

calendar += ' </div>';

calendar += ' <table border="0" cellspacing="0" cellpadding="0">';

calendar += ' <caption>' + currentYear + '년 ' + currentMonth + '월 달력</caption>';

calendar += ' <thead>';

calendar += ' <tr>;

calendar += ' <th class="sun" scope="row">일</th>';

calendar += ' <th class="mon" scope="row">월</th>';

calendar += ' <th class="tue" scope="row">화</th>';

calendar += ' <th class="wed" scope="row">수</th>';

calendar += ' <th class="thu" scope="row">목</th>';

calendar += ' <th class="fri" scope="row">금</th>';

calendar += ' <th class="sat" scope="row">토</th>';

calendar += ' </tr>;

calendar += ' </thead>';

calendar += ' <tbody>';


var dateNum = 1 - currentDay;


for(var i = 0; i < week; i++) {

calendar += ' <tr>';

for(var j = 0; j < 7; j++, dateNum++) {

if( dateNum < 1 || dateNum > currentLastDate ) {

calendar += ' <td class="' + dateString[j] + '"> </td>';

continue;

}

calendar += ' <td class="' + dateString[j] + '">' + dateNum + '</td>';

}

calendar += ' </tr>';

}


calendar += ' </tbody>';

calendar += ' </table>';


kCalendar.innerHTML = calendar;

}


단순한 달력주제에 코드는 상당히 깁니다.

주석도 달아놨으니 차근차근 설명해드리겠습니다.


먼저 function kCalendar라는 사용자 정의 함수를 만들었습니다.

매개변수로는 id(달력이 들어갈 태그의 id)와 date(선택할 날짜 2015-3-27 등)이 있습니다.


kCalendar라는 변수에 매개변수로 얻은 id 값을 getElementById 메서드를 이용해서 지정해줍니다.



1)

그 다음 만약 date의 타입이 undefined가 아니라면(매개변수 date에 값이 있다면) date의 값을 -로 분리해줍니다.


date.split('-') 메서드는 date가 2015-3-27 였다면 date[0] = 2015, date[1] = 3, date[2] = 27과 같이 배열로 나눠줍니다.

이렇게 나눠진 배열에서 date[1] = date[1] - 1;을 해줍니다.


이런 연산을 하는 이유는 자바스크립트에서는 월(Month)를 0부터 시작해서 11로 끝나기 때문이죠.

즉 0 = 1월 11 = 12월과 같이 됩니다.


date를 매개변수로 입력 받을 때는 3 = 3월로 입력 받았으니 자바스크립트에서 연산을 위해 -1 을 해줍니다.


그 다음 new Date()로 새로운 date 값을 만듭니다.



2)

만약 1에서 date의 타입이 undefined 였다면 매개변수로 date가 없었던 것 이므로 new Date()를 통해서 오늘 날짜를 date 변수에 넣습니다.



그 다음은 date 변수에서 currentYear, currentMonth, currentDate에 각각 년, 월, 일의 값을 가져오는데,

아까 말했던 것처럼 Month는 기존 달 - 1의 값을 가지고 있었으므로 다시 +1을 해줍니다.


이제 달력에서 보여줄 년월일은 구했으니, 이번 달의 첫 번째 요일이 어떤 요일인지를 알아내야합니다.

요일을 알아내는 방법은 date.setDate(1)을 통해서 date 변수의 일자를 1일로 변경합니다.

만약 date 변수의 연월일 값이 2015-3-27 이였다면 2015-3-1 로 바뀌게 됩니다.


그 다음 getDay() 메서드를 통해서 현재 일자의 요일을 currentDay 변수에 넣습니다.

여기서 date.getDay()의 반환 값은 0 = 일요일, 6 = 토요일입니다.

2015-3-1의 currentDay 값은 0이 되는거죠.


그 다음은 달력을 나타낼때 사용할 배열을 선언했습니다.

먼저 dateString 배열은 각 요일에 대한 클래스를 지정하기 위해서 만든 배열로

getDay()의 반환 값이 0, 1, 2, 3, 4, 5, 6 이였던 것처럼 배열도 일요일부터 시작했습니다.


lastDate 배열은 각 월의 마지막 일자입니다.

달력의 마지막 일자는 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 순이죠.

하지만 여기서 변수가 하나 있습니다.


윤년이 있는데요.

윤년은 주로 4년마다 한번 있다고 알고 있지만 정확히는 4년에 한번이면서 100년이 아닐 때 (1904년은 윤년이지만, 1900년은 윤년이 아님.)

혹은 400년에 한번 윤년입니다. (1900년은 윤년이 아니지만 2000년은 윤년임.)


그러므로 만약 currentYear을 4로 나눴을 때의 나머지가 0이고, 100으로 나눴을 때의 나머지가 0이 아니거나

400으로 나눴을 때 0이라면 lastDate[1] (2월 달)의 값을 29로 변경해줍니다.



그리고 currentLastDate를 구해주는데 오늘 날짜가 2015-3-27 이라면 currentMonth가 3이므로

lastDate[currentMonth-1]을 해서 이번 달 마지막 일자를 구합니다.


그 다음은 이번 달이 총 몇주인지를 구해야합니다.

이후에 나올 반복문에서 사용해야하므로 먼저 구해놓는겁니다.


계산 식은 currentDay(요일 값) + currentLastDate(마지막 일자)를 7로 나눈 값을 올림 해주면 나오게 됩니다.

2015년 3월을 가지고 예를 들자면 (0 (요일 값) + 31 (마지막 일자)) / 7 = 4.42...가 나오네요.

이걸 올림 해줬으니 5라는 값이 나오구요.

이걸로 2015년 3월은 5주라는 것을 알아 냈습니다.



이번에는 이전 달, 다음 달의 날짜를 구하기 위한 연산을 합니다.

이 부분은 더 간단하게 가능할 것 같은데 일단 이렇게 만들어 뒀으니 이대로 설명하겠습니다.


이전 버튼을 눌렀을 때 이전 달의 월이 1이 아니라면 2에서 12까지의 값이라는 말이므로 currentMonth에서 1을 뺍니다.

하지만 이번 달이 1이라면 0월은 없으니 currentYear에서 1을 빼주고 월은 currentMonth 대신 12로 바꿔줬습니다.


다음 버튼도 마찬가지로 만약 다음 달의 월이 12가 아니라면 1에서 12까지의 값이니 currentMonth에 1을 더하고, 12라면 13월이 없으니 currentYear에 1을 더해주고 월을 1로 바꿔줍니다.


if( currentMonth < 10 )

var currentMonth = '0' + currentMonth;


이 부분은 자바스크립트에서 getMonth() 메서드를 통해 얻은 값은 앞에 0이 없어서(3월은 03으로 표현이 안됨) 넣어준 부분입니다.



이제 진짜로 달력을 만드는 태그를 적어줍니다.

먼저 div header에는 이전 달 버튼, 다음 달 버튼과 0000년 00월이라는 타이틀을 적어줬구요.

이전 달 버튼과 다음 달 버튼에는 위에서 만든 prevDate와 nextDate를 썼습니다.

여기 보면 처음에 봤던 id 매개변수도 존재하네요.


여러 특수 기호 때문에 정신이 없겠지만, 실제로 태그에 적히는 부분은 kCalendar('id', 'date') 입니다.


div header가 끝나면 table이 나오게됩니다.

본격적으로 달력을 입력하는데요.

th에는 각 요일을 적어주고, dateNum 변수에는 1 - currentDay (요일 값)을 적어줍니다.

왜 이렇게 되는지는 더 아래서 알 수 있을껍니다.


이제 반복문이 시작되는데요.

여기서 위에서 구했던 week 변수 (이번 달의 주)가 사용됩니다.

week 값만큼 <tr> 태그를 만들려는거죠.


아까 week는 5 였고 i = 0, i< week 이므로 여기서는 0부터 4까지 총 5번을 돌겠네요.

첫 번째 for문 내부에서 <tr>을 적어주고, 한번 더 for문을 만나게 됩니다.


여기서는 0부터 6까지 7번을 반복하게 되는데요.

특이한 점은 j++, dateNum++가 함께 있다는 점입니다.


for문이 돌고나서 바로 if문이 실행되는데, if문의 조건을 살펴봅시다.

dateNum이 1보다 작거나, currentLastDate(마지막 일자) 보다 클 경우에 <td></td>의 내부엔 공백만 들어가고, continue를 실행합니다.


이런 조건을 준 이유는 dateNum을 선언할 때 currentDay(요일 값) 만큼 빼줬기 때문입니다.

이 연산을 통해서 첫 번째 일자가 제자리(2015-3-27 기준 일요일)로 갈 수 있습니다.


만약 if문의 조건에 해당되지 않는다면 정상적인 반복문을 실행합니다.

여기서는 <td></td> 내에 dateNum 값을 갖는데, dateNum 값은 1일~마지막 일까지의 값이 들어가게 됩니다.


그리고 여기서 class 부분에 쓰인 dateString[j]은 위에서 마지막 일자를 갖는 배열을 선언하기 전에 만든 요일별 문자열 배열입니다.


이제 여기까지 calendar 변수에 모두 집어넣었으니 innerHTML을 통해서 calendar 값을 출력합니다.

그럼 지금까지 공부한 달력이 나오게됩니다.


여기까지 무지 길게 느껴진 설명을 적어봤는데요.

한번만 봐서는 이해가 잘 안될 거라 생각됩니다.


하지만 몇 번 반복 해서 생각해보면 어떤 방식으로 작동되는지 조금은 감이 올테니 여러번 읽어보세요!

어려운 점이나 수정이 필요한 점, 지적 사항 등은 댓글에 남겨주시면 감사하겠습니다^^

TAG ,
  1. 프로그래밍 꿈나무 2015.07.01 17:09 신고  댓글주소  수정/삭제  댓글쓰기

    정말이지 감사합니다! 많은 도움을 받고 갑니다!!! 복받으실거에요 ㅋ

  2. 좋은인생 2015.12.03 21:51 신고  댓글주소  수정/삭제  댓글쓰기

    소스 감사합니다!
    아주 도움이 되었습니다~~~~

  3. 스케쥴러 2015.12.11 01:21 신고  댓글주소  수정/삭제  댓글쓰기

    특정 날짜를 클릭하면 prompt로 입력 받아서 스케쥴러 처럼 등록가능하게 하고 싶은데
    이 코딩을 어느 부분에 추가하면 될까요

    • Kurien 2015.12.12 11:14 신고  댓글주소  수정/삭제

      단순히 등록 하고 새로고침 시 사라지는 정도라면 수정할게 아니라 원하는 기능을 만드셔서 추가를 하시면 되는데,
      계속 남아야 한다면 백엔드 언어를 배우셔야 할겁니다.

      위에 말한 기능은 그냥 날짜를 입력 받아서 해당 일자에 해당하는 배열을 만들고 그 날짜가 출력 될 때 배열을 읽어오면 될 것 같네요.

  4. 소녀감성 2016.01.22 16:34 신고  댓글주소  수정/삭제  댓글쓰기

    매개변수값에 꼭 id를 넣어야 하나요? 그냥 출력하면 안되나여??

    • Kurien 2016.02.03 10:30 신고  댓글주소  수정/삭제

      매개변수 값에 id가 들어가는 이유는 달력이 들어갈 위치를 ID값으로 찾기 위해서입니다.

      var kCalendar = document.getElementById(id); 이 부분의 id 값을 고정하시면 따로 id 값은 필요 없을 것 같습니다.

  5. 토마스 2016.02.03 13:46 신고  댓글주소  수정/삭제  댓글쓰기

    공휴일은 어떻게 집어 넣을 수 있을까요?? js 연습으로 온전한 달력을 만들어보고 싶은데..

    공휴일과 대체휴일을 해결 하는 방법론? 방법? 좀 알려주세요 ㅠㅠ 제머리론 한계네요.

    10년치를 하드코딩해야하는건지...? 설날과 추석은 매번 날짜가 바껴서 어렵네요 ㄷㄷ.. 나머지 공휴일은 아마 전부 요일이 지정되어 있는데 말이죠 ㅠ! 여튼 소스 감사드립니다. 사실 소스보다 설명이 감사.. 이해하는데 완전 도움됬어요. 꾸벅(__)ㅎㅎ

    • Kurien 2016.02.03 14:29 신고  댓글주소  수정/삭제

      공휴일을 넣으시려면 상당히 일이 복잡해집니다.

      단순하게 하시려면 말씀하신 것처럼 몇십년꺼를 먼저 넣어놓는 방법이 있긴한데, 좀 아니다 싶죠,

      먼저 설날, 추석같은 날을 제외한 다른 공휴일은 대부분 양력 날짜로 지정되어있기 때문에 매 년 해당 월 해당 일에만 반복된다고 생각하시면 됩니다.

      문제는 설날, 추석인데, 이 두 공휴일들은 양력이 아니라 음력1월 1일, 8월 15일이기 때문에 해당 날짜의 음력을 먼저 구하셔야 합니다.

      그런데 음력을 구하려면 또 복잡해집니다.
      참고 자료: http://onfaf.tistory.com/87

      간단히 하시려면 설날, 추석만 따로 몇십년 분의 자료를 넣는 편이 쉬울 것 같네요.

      그리고 대체 공휴일은
      https://ko.wikipedia.org/wiki/%EB%8C%80%EC%B2%B4%ED%9C%B4%EC%9D%BC%EC%A0%9C%EB%8F%84

      위의 링크에 있는 것처럼 해당 공휴일이 주말이라면, 그 다음 비 공휴일을 공휴일로 나타나게 하시면 됩니다.

      복잡한 프로그램이라서 좀 어려울 거라고 생각되네요.

  6. ㅁㄴㅇㅁㄴ 2016.02.03 16:37 신고  댓글주소  수정/삭제  댓글쓰기

    강의 잘봤습니다!
    근데 저는 여기에 셀렉트박스로 년,월을 추가하는 기능을 만들고싶은데요 셀렉트박스 값을 currentMonth에 넣으니 달력 첫번째날짜가 계속 고정되어있는데 왜이러는걸까요? ㅋ 해매고있네요 ㅎㅎ
    그리고 매개변수 date는 어디서 값을 받아오는건지도 궁금합니다 ㅎ

    • Kurien 2016.02.07 22:48 신고  댓글주소  수정/삭제

      만드신 코드를 보여주고 설명을 해주세요.
      말로만 적으시니 뭘 원하시는건지 어떤 부분이 틀리신건지를 알 수 없습니다.

  7. 초보자 2016.02.03 20:41 신고  댓글주소  수정/삭제  댓글쓰기

    궁금한점이 있는데요
    onclick="kCalendar(\'' + id + '\', \'' + prevDate + '\')">
    여기서 \'' '\' 들의 역할이 무엇인지 궁금합니다

    • Kurien 2016.02.07 22:49 신고  댓글주소  수정/삭제

      " + 변수 + "는 변수와 문자열을 구분해주는 부분입니다.
      "자바스크립트 구분자"라고 검색하시면 더 많은 정보를 얻으실 수 있을 것 같네요.

  8. 홍길동 2016.04.11 16:11 신고  댓글주소  수정/삭제  댓글쓰기

    여기서 1960년 부터 2200년까지의 날짜만 구하고 싶으면 어떻게 해야 하나요.

  9. 파이어링 2016.05.31 01:19 신고  댓글주소  수정/삭제  댓글쓰기

    혹시 body 안에 들어갈 코드도 보여주실 수 있으신가요?
    제가 이제 자바스크립트를 배우고 있어서 어렵네요ㅠㅠ

  10. osm2112 2016.07.07 22:40 신고  댓글주소  수정/삭제  댓글쓰기

    좋은 소스 감사합니다 ^^ 잘보고가요

  11. choies 2016.08.30 11:19 신고  댓글주소  수정/삭제  댓글쓰기

    한 페이지 안에서 두개가 생성이 안되는데 이부분은 어떻게 해야되는지 여쭤보고 싶습니다.

    • Kurien 2016.09.06 17:26 신고  댓글주소  수정/삭제

      제가 제작해둔 코드는 1개만을 위한 코드입니다.

      여러개까진 생각하고 만든게 아니기 때문에 변경을 위해서는 여러 부분을 수정해야할 것 같네요.

  12. 왕초보. 2016.12.23 09:47 신고  댓글주소  수정/삭제  댓글쓰기

    혹시 자바 스크립트에서 나온 데이터를 json형태로 바꿔서 그리드에 넣고싶은데 가능 할까요???

  13. 지나가던아조씨 2017.08.30 17:06 신고  댓글주소  수정/삭제  댓글쓰기

    위젯으로 달력을 넣어볼까 하다가 어떻게 접근할지 몰랐는데 덕분에 많이 배우고갑니다 대단하신듯..