본문 바로가기
프로그래밍/javacscript

[220322] 자바스크립트로 달력만들기

by 한코코 2022. 3. 23.

1. 현재 날짜를 가져오는 함수 new Date()

date 객체는 세계표준시(UTC) 1970년 1월 1일 00시 00분 00초를 기준으로 현재와 얼마나 시간 차가 얼마나 되는지 밀리초 단위로 나타낸다.

let dateToday = new Date()
console.log(dateToday)
console.log(typeof(dateToday))

//출력값
//2022-03-22T13:35:12.509Z
//object

그 외에도 원하는 시각을 넣어서 객체를 작성할 수 있다.

console.log(new Date(2021, 11, 6));
console.log(new Date('2021-12-06T03:24:00'));

//결과
//2021-12-05T15:00:00.000Z
//2021-12-05T18:24:00.000Z

Date()인자에 0을 넣으면 특정한 값이 나오므로 잘 확인하자

console.log(new Date())
console.log(new Date(2022,0)) //22년 1월 1일
console.log(new Date(2022,0,0)) //22년 12월 31일
console.log(new Date(2022,03,0)) //22년 3월 31일

 

 


 

 

2. 원하는 연/월/일/요일/시각을 가져오기

new Date()결과가 객체이므로 속성값을 통해 원하는 값을 가져올 수 있다.

이때 주의해야할 점은

월을 가져오는 getMonth()는 0~11로 열두달을 표현하기 때문에 나온 값에 1을 더해야 해당 월이 나온다.

요일을 가져오는 getDate()는 0~7로 일요일~토요일을 표현하기때문에 나온 값에 맞는 요일을 찾아야한다.

const year = dateToday.getFullYear()
const month = dateToday.getMonth()
const day = dateToday.getDate()
const date = dateToday.getDay()
const time = dateToday.getHours()

console.log('연도 : ',year)
console.log('월 : ',month) //0 ~ 11
console.log('일 : ',day) // 1 ~ 31
console.log('요일 : ',date)// 0 ~ 7 / 일 ~ 토
console.log('시 : ',time)

//결과
//연도 :  2022
//월 :  2  --> 1을 더한 3월이다
//일 :  22
//요일 :  2 --> 2에 해당하는 화요일이다
//시 :  22

 

 


 

3. 현재 연도와 월을 나타내기

<script type="text/javascript">
document.addEventListener('DOMContentLoaded',()=>{
    let now = new Date()
    
    const year_month = document.querySelector('.year_month')
    const cal = document.querySelector('.cal')

    let nowYear = now.getFullYear()   
    let nowMonth = now.getMonth()


    makeCal(now)

    function makeCal(now){
        nowYear = now.getFullYear()
        nowMonth = now.getMonth()
        year_month.innerHTML = `${nowYear}.${nowMonth+1}`
    }
</script>


<!-- #처럼 맨 처음 페이지로 이동하지 않는 새로고침 -->
<a href="javascript:;" class="prev_btn"><</a>

<!--연도.월을 출력-->
<span class="year_month"></span>
<a href="javascript:;" class="next_btn">></a>
<div class="cal"></div>


 

 

4. 이전달과 다음달을 나타내기

<을 클릭하면 이전달이 나오고,

>을 클릭하면 다음달이 나오게 만들자.

<script type="text/javascript">
document.addEventListener('DOMContentLoaded',()=>{
    let now = new Date()
    
    const prev_btn = document.querySelector('.prev_btn')
    const next_btn = document.querySelector('.next_btn')
    const year_month = document.querySelector('.year_month')
    const cal = document.querySelector('.cal')

    let nowYear = now.getFullYear()   
    let nowMonth = now.getMonth()

    makeCal(now)

    function makeCal(now){
        nowYear = now.getFullYear()//가져온 now 정보를 가져온다.
        nowMonth = now.getMonth()
        console.log(now)
        year_month.innerHTML = `${nowYear}.${nowMonth+1}`
    }
	
    //이전달로 가는 < 
    prev_btn.addEventListener('click',()=>{
        let now = new Date(nowYear, nowMonth-1) //올해, 이전달의 정보
        makeCal(now) //달력을 새로 렌더하는 함수
    })
    
    //다음달로 가는 >
    next_btn.addEventListener('click',()=>{
        let now = new Date(nowYear, nowMonth+1)
        makeCal(now)
    })
})
</script>



<!-- #처럼 맨 처음 페이지로 이동하지 않는 새로고침 -->
<a href="javascript:;" class="prev_btn"><</a>
<span class="year_month"></span>
<a href="javascript:;" class="next_btn">></a>
<div class="cal"></div>

 


 

 

5. 해당 달의 일수를 출력하기

for반복문을 사용해서 1부터 마지막 날짜까지 반복문을 돌려서 출력한다.

function makeCal(now){
    nowYear = now.getFullYear()
    nowMonth = now.getMonth()
    PrevObj = new Date(nowYear,nowMonth+1,0) //이번달의 마지막 날을 가진 객체
    nowLastDate = PrevObj.getDate() //미지막 날을 추출

    year_month.innerHTML = `${nowYear}.${nowMonth+1}`

	//1~마지막날까지 반복문을 돌려서 출력
    for(let i=1; i<=nowLastDate; i++){
        cal.innerHTML+=`${i} `
    }
}

 

하지만, 버튼을 이용해서 달을 이동하면 새로 달력이 렌더링이 되는게 아니라 그 다음에 기록이 쌓여서 나타난다.

3월, 2월, 1월, 12월까지 내용이 모두 출력이 된 화면

캘린더를 렌더하는 함수 안에 함수가 시작될때 cal.innerHTML의 내용을 비워서 초기화하는 코드를 넣어준다.

그러면 기록이 쌓이지않고 계속해서 새 달력을 렌더해서 가져온다.

function makeCal(now){
    cal.innerHTML=''
    //아래는 위 코드와 동일
}

 

 


 

 

6. css를 포함해서 해당 달의 달력을 출력하기

다른 게시물들을 보니까 달력을 7개단위로 끊어서 다른 줄로 옮기지 않았다.

1

2

3

이런식으로 한줄한줄 숫자를 div형태로 출력한 후, 전체 넓이의 7분의 1를 넓이로 준다.

한 줄이 가득차면 다음 숫자는 자동으로 다음줄로 넘어가는 형식으로 달력을 출력했다.

왜 그럴까 생각해봤는데, 수식을 만들 바에야 한 줄을 7등분으로 나누는게 훨씬 쉬우니까-가 아닐까?

숫자를 일주일 단위로 끊어도 어차피 달력을 만들려면 css에서 7등분을 해야하니까.

 

나도 css을 포함해서 달력을 만들어보겠다.

새로운 일수가 나타날때마다 새로 div를 생성해주는 코드로 수정해준다.

for(let i=1; i<=nowLastDate; i++){
    cal.innerHTML+='<div class="cal_day">'+i+'</div>'
}

 

div으로 구획을 나눈 html

css에서 display:flex;와 flex-flow:wrap;을 써서 한 줄을 넘어갈때 다음줄로 넘겨주는게 포인트다.

<div class="nav">
    <a href="javascript:;" class="prev_btn"><</a>
    <span class="year_month"></span>
    <a href="javascript:;" class="next_btn">></a>
</div>
<div class="wrap">
    <div class="days">
        <div class="day">SUN</div>
        <div class="day">MON</div>
        <div class="day">TUE</div>
        <div class="day">WED</div>
        <div class="day">THU</div>
        <div class="day">FRI</div>
        <div class="day">SAT</div>
    </div>
    <div class="dates"></div>
</div>
/* cal style sheet */
*{margin:0; padding:0;}
ul,li{list-style: none;}
a{text-decoration: none;}
input:focus{outline: none;}

.nav{
    height: 50px;
    font-size: 20px;
}

.wrap{
    width: 360px;
}

.days{
    width: 100%;
    display: flex;
    margin-bottom: 10px;
}

.day{
    width: calc(100% / 7);
    text-align: center;
}

.dates{
    display: flex;
    flex-flow:wrap;
}

.date{
    width: calc(100% / 7);
    height: 50px;
    text-align: center;
}

 

 


 

 

7. 요일에 맞게 달력을 출력하기

자, 이제 거의 다 왔다.

6번의 달력은 무조건 일요일에 1일이 출력되어서 나오지만, 현실 달력은 그렇지 않다.

요일에 맞는 달력을 출력해보자.

 

1. 현재 시점에서 시작하는 1일이 일요일인가?

일요일부터 시작하는 달력이기때문에 day값이 0인지 확인해야한다.

 

1-1. 일요일이 아닐경우, 일요일부터 현재 요일까지 지난달의 날짜를 가져와서 메꾼다

예를 들면 이번달의 1일이 목요일에 시작한다면, 지난달의 마지막날짜부터 일,월,화,수요일을 메꾸기 위해 4일치를 가져와서 메꾼다.

for문으로 작성해서 돌렸다.

 

2. 현재 시점에서 마지막 날짜가 토요일로 끝나는가?

다음줄로 넘어가지 않으려면 마지막 날짜인 토요일로 끝나야한다. 이번달의 마지막 요일이 day값 7인지 확인한다.

 

2-1. 토요일이 아닐경우, 다음달 날짜를 1일부터 가져와서 토요일로 끝나도록 메꾼다.

예를 들면 이번달이 화요일로 끝났다면, 다음달 1일부터 수,목,금,토요일을 메꾸기 위해 4일치를 가져와서 메꾼다.

for문으로 작성해서 돌렸다.

 

이 조건들을 모두 충족하는 코드를 작성했다.

지난달과 다음달 날짜로 메꾼 날짜는 구별하기 위해서 흐린 회색으로 나타나도록 css를 작성했다.

<script type="text/javascript">
document.addEventListener('DOMContentLoaded',()=>{
    let now = new Date()

    const prev_btn = document.querySelector('.prev_btn')
    const next_btn = document.querySelector('.next_btn')
    const year_month = document.querySelector('.year_month')
    const dates = document.querySelector('.dates')

    let nowYear = now.getFullYear()   
    let nowMonth = now.getMonth()

    makeCal(now)

    function makeCal(now){
        dates.innerHTML='' //날짜를 초기화하는 코드

        //현재의 연도, 달, 일
        nowYear = now.getFullYear()
        nowMonth = now.getMonth()
        nowDate = now.getDate()

        //이번달에 시작하는 요일 구하기            
        PrevObj = new Date(nowYear,nowMonth,0) //저번달의 마지막 날이 담긴 객체
        startDay = PrevObj.getDay()+1//저번달의 마지막 요일+1 = 이번달에 시작하는 요일
        startDate = PrevObj.getDate()//저번달의 마지막 일

        //이번달에 끝나는 요일 구하기
        NextObj = new Date(nowYear,nowMonth+1,0) //이번달의 마지막 날
        endDay = NextObj.getDay() //이번달의 마지막 요일
        endDate = NextObj.getDate() //이번달의 마지막 일

        year_month.innerHTML = `${nowYear}.${nowMonth+1}`
        if(startDay!==0){
            //만일 이번달에 시작하는 요일이 일요일(0)이 아닐 경우
            //0에서 모자란 수만큼 지난달의 날짜로 채운다
            for(let i=startDate-startDay; i<startDate; i++){
                dates.innerHTML+='<div class="date prev">'+i+'</div>'
            }
            for(let i=1; i<=endDate; i++){
                dates.innerHTML+='<div class="date">'+i+'</div>'
            }
            //만일 이번달이 토요일(7)에서 끝나지 않았다면
            //7일 될때까지 다음날의 날짜로 채운다
            for(let i=1; i<(endDay==7?0:7-endDay); i++){
                dates.innerHTML+='<div class="date next">'+i+'</div>'
            }
        }else{
            for(let i=1; i<=endDate; i++){
                dates.innerHTML+='<div class="date">'+i+'</div>'
            }
            //만일 이번달이 토요일(7)에서 끝나지 않았다면
            //7일 될때까지 다음날의 날짜로 채운다
            for(let i=1; i<(endDay==7?0:7-endDay); i++){
                dates.innerHTML+='<div class="date_next">'+i+'</div>'
            }
        }
    }

    prev_btn.addEventListener('click',()=>{
        let now = new Date(nowYear, nowMonth-1)
        makeCal(now)
    })
    next_btn.addEventListener('click',()=>{
        let now = new Date(nowYear, nowMonth+1)
        makeCal(now)
    })
})
</script>



<div class="nav">
    <a href="javascript:;" class="prev_btn"><</a>
    <span class="year_month"></span>
    <a href="javascript:;" class="next_btn">></a>
</div>
<div class="wrap">
    <div class="days">
        <div class="day">SUN</div>
        <div class="day">MON</div>
        <div class="day">TUE</div>
        <div class="day">WED</div>
        <div class="day">THU</div>
        <div class="day">FRI</div>
        <div class="day">SAT</div>
    </div>
    <div class="dates"></div>
</div>

댓글