Calendar 클래스로 해야할 일들은 정해져 있다. 결국 날짜를 가지고 하는 연산을 해야하고, 달력을 만들어야 한다. 달력을 만들면 스케줄 관리 같은 프로그램을 만들어서 배포할 수 있다.

 

1. 날짜 연산 add 와 roll 메소드

아래 예제는 날짜 연산 메소드이다. add는 날짜를 더하면 년,월,일도 자동으로 바뀐다. 예를들어 7월31일에 1일을 더하면 8월1일이 되고, 2020년12월31일에 1일을 더하면 2021년 1월1일로 넘어가는 방식이다.

 

roll 메소드는 그렇지 않다. 오버플로우 처럼 넘어간다. 7월31일에 1일을 더하면 다시 7월1일이 되는 방식이다.

 

Calendar 클래스의 각 요소들(년,월,일)들을 모으기가 쉽지 않으니까 toString을 오버라이드해서 사용한다. toString은 원래부터 그런 목적으로 있는 것 같다. 문자열을 편하게 다루고 싶은데 마땅한 함수이름을 짓기가 뭐할때 쓰면 좋다. 많은 개발자들의 문제 중의 하나는 함수이름 짓기라고 한다. 현대의 프로그램은 너무 방대한 크기가 되버려서,,, 머리속에 비슷한 생각을 하는 프로그래머들이 먼저 이름을 선정하려고한다. 언제든지 충돌할 일이 많으니까 내가 사용하는 영역속의 오버라이드는 어찌보면 가장 안전할 수도 있다. 적어도 뭘 바꾼지는 아니까.

 

아래 예제에서 주의할 점은 항상 MONTH는 0부터 시작한다는 것이다. 따라서 6은 7월이다. 0이 1이되는 이 비슷한 대응관계는 프로그래밍을 하다 보면 의외로 자주 맞닿들인다. 0에 대해서도 하나의 단위로 처리를 할 수 있는 컴퓨터의 속성때문에 그렇다. 0과 1이지만 실제 이진법은 1과 10이 하나, 둘이다. 인간이 인식하는 것은 1부터인데 컴퓨터는 비트가 없고 있고를 인식한다. (전류가 흐르고 안흐르고) 0을 1로 잡아 설계한 개념들이 꽤 많으니 익숙해질 필요가 있다.

 

다른 부분은 기존 예제와 비슷하다. 반복되고 있을 뿐. Swing의 JTextArea를 사용했다. add 메소드는 Calendar의 상수들을 매개변수로 받아서 어떤 연산을 해야할 지 적절하게 판단한다. 사람이 봤을 때는 코드지만 기계는 언제나 정확하다. 그래서 상수에 충분한 이름을 입힌다.

 

import java.awt.Font;
import java.util.Calendar;
import javax.swing.*;

public class CalendarEX3 extends JFrame{
	Font f1;
	
	CalendarEX3(){
		
		
		f1 = new Font("배달의민족 도현",Font.PLAIN,30);
		
		// today
		Calendar date1 = Calendar.getInstance();
		date1.set(2020, 6, 30); // 7월달이다
		
		String str1 = toString(date1); // 처음
		
		date1.add(Calendar.DATE, 1); // 1일후
		str1 += toString(date1);
		
		date1.add(Calendar.MONTH, -3); // 3개월전
		str1 += toString(date1);
		
		date1.add(Calendar.YEAR, 15); // 15년 후
		str1 += toString(date1);
		
		date1.roll(Calendar.DATE, 31); // 30일 후 월은 안바뀐다.(자리올림이 안됨)
		str1 += toString(date1);

		JTextArea tf1 = new JTextArea(str1);
		tf1.setBounds(100, 50, 500, 200);
		tf1.setFont(f1);
	
		// JFrame
		add(tf1);
		setTitle("Calendar Example");
		setSize(700,400);
		setLayout(null);
		setVisible(true);
	}

	public static String toString(Calendar date) {
		return  "날짜 : " + date.get(Calendar.YEAR) + "년 " + 
				(date.get(Calendar.MONTH)+1) + "월 " +
				date.get(Calendar.DATE) + "일 \n";
	}

	public static void main(String[] args) {
		new CalendarEX3();
	}
}

 

 

2. 캘린더(달력)만들기

Calendar 클래스는 결국 달력을 만들기 위한 것이니까 달력을 만들어 줘야한다. 두개의 Calendar 인스턴스를 가져와서 만들 수 있다.

 

아래 예제는 콘솔에서 실행한다. GUI로 하면 좋겠지만 조금더 코드가 길어지고 디자인 요소들에 관심을 가져야 한다. 여기서는 핵심을 이해하는게 중요하다. 우선 Scanner 클래스로 콘솔에 입력을 받는다 (연도,월) 그 달의 달력을 출력하려면 시작점(1일)과 끝점(말일)을 알아야 한다. 어떤 요일인지도 중요하다. 그것에 따라 달력 모습이 달라진다.

1개월의 달력을 출력하려고 생각하면 답이 나온다. 마지막 날짜가 30인지 31인지 28일인지 확인할 필요도 있다. 1일은 확실하니까 패스하면 말일은 다음달 1일의 하루 전이다. 이렇게 하면 계산할 필요도 없다. 1일에서 1을 빼면 그 달에 따라 말일이 나오니까.

 

마찬가지로 month는 +1을 더해야 한다. 이 예제에서는 7월달이 필요하면 6을 입력하도록 해놨다. 번거로운 과정을 하나라도 빼는게 처음에 이해가 쉽다. DAY_OF_WEEK는 요일에 따라 대응이 다르다. 일요일 1부터 토요일 7번까지 대응이 된다.

import java.awt.Font;
import java.util.Calendar;
import java.util.Scanner;
import javax.swing.*;

public class CalendarEX5 extends JFrame{
	Font f1;

	
	CalendarEX5(){}
	
	public static void main(String[] args) {
		
		int weekStart;
		int monthEnd;
		
		Scanner sc1 = new Scanner(System.in);
		System.out.println("연도와 월 입력");
		int year = sc1.nextInt();
		int month = sc1.nextInt();
		
		Calendar date1 = Calendar.getInstance();
		Calendar date2 = Calendar.getInstance();
		
		date1.set(Calendar.YEAR,year);
		date1.set(Calendar.MONTH,month);
		date1.set(Calendar.DATE,1);
		
		date2.set(Calendar.YEAR,year);
		date2.set(Calendar.MONTH,month+1);
		date2.set(Calendar.DATE,1);
		date2.add(Calendar.DATE,-1);
		
		System.out.print(date1.get(Calendar.YEAR) + "년 ");
		System.out.print(date1.get(Calendar.MONTH) + "월");
		System.out.print(date1.get(Calendar.DATE) + "일 ");
		System.out.println(date1.get(Calendar.DAY_OF_WEEK)+"요일 계산");
		System.out.println();

		weekStart = date1.get(Calendar.DAY_OF_WEEK);
		monthEnd = date2.get(Calendar.DATE);
		
		System.out.println("       " + date1.get(Calendar.YEAR) + "년 " +
				(date1.get(Calendar.MONTH)+1) + "월");
		System.out.println();
		
		System.out.println(" SU MO TU WE TH TR SA");
		
		for(int i =1; i < weekStart; i++)System.out.print("   ");
		for(int i=1, n = weekStart; i <= monthEnd; i++,n++ ) {
			System.out.print((i<10)?"  "+i : " "+i);
			if(n%7==0)System.out.println();
		}
	}
}

양식은 줄을 잘 맞출 수 있도록 한다. weekStart 가 요일을 말해주는 인덱스다. 토요일(7)이 되면 다음으로 넘어간다.(n%7 == 0)

 

10이상의 숫자와 이하의 숫자들은 공백크기에 차이가 있다. 10이하의 숫자는 공백을 하나 더 주면 열이 잘 맞는다.

 

달력을 만드는 알고리즘은 많이 있다. 여러가지 방법으로 해봐도 된다. 시간상 GUI로는 만들지 않았는데 여유가 생기면 GUI 달력도 만들어서 공유할 것 이다.

공유하기

facebook twitter kakaoTalk kakaostory naver band