자바를 통해 연도와 월을 입력받고, 달력을 출력하는 어플리케이션 만들기
연도, 월을 입력받는다.
int year
int month
해당 연도일 때 각 월의 최대일을 정한다. (배열 이용: 31,28,31,30...)
int dayMax
int dayData[]
-이 때, 윤년의 2월 최대일은 하루가 더해짐을 고려한다.
boolean isLeapYear
윤년은 연도가 4의 배수이면서, 100의 배수가 아닐 때 또는 400의 배수일 때이다.
해당 월의 첫번째 날(1일)이 무슨 요일인지 알아낸다.
-특정 포맷으로 입력할 경우 해당 날짜의 요일에 따른 정수값을 반환해주는 Calendar의 메소드를 이용한다.
getFirstDay(String date, String dateType)
int dayNum
첫번째 날(1일)을 기준으로 요일과 날짜가 알맞게 배치되도록 공백 출력을 설정한다.
이 때 int dayNum
은 해당 월의 첫번째 날의 요일에 대한 정수값이다.
일자 출력에는 반복문을 이용하고, 주마다 줄바꿈하도록 설정하는 데는 if문을 이용한다.
int day
-주마다 줄바꿈하는 데에는 (day+dayNum-1)%7 == 0
일 때 day가 일요일이라는 것을 이용했다.
Why?
일요일의 정수값은 7일 때, day가 일요일일 경우 day+dayNum-1 은 7의 배수가 된다.
dayNum은 1일이 요일이라는 7개의 칸 중 몇 칸을 비우는지를 알려주는 숫자이고,
비우는 칸을 고려한 숫자를 더하면 지난 일요일로부터 7일이 지난 것이 되기 때문이다.
✔ 3번의 경우, 다른 분이 블로그에 올리신 소스코드를 이용해서 필요한 방식으로 조금 수정했다.
하지만 그래서 java.util.Date이나 java.text.SimpleDateFormat 과 같이 정확히 이해하지 못하고 있는 부분도 있다. 차차 공부할 것..!!!
✔ 일반적으로 첫 주의 시작을 일요일로 하는 달력을 만들고, Calendar 자체 기능에서도 일요일이 1값으로 반환되지만 개인적으로는 월요일을 시작으로 두고 싶어서 월요일을 1값으로, 일요일을 7값으로 수정했다.
package MyCalendar;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Scanner;
public class MyCalendarApp {
public static int getFirstDay(String date, String dateType) throws Exception {
SimpleDateFormat dateFormat = new SimpleDateFormat(dateType) ;
Date nDate = dateFormat.parse(date) ;
Calendar cal = Calendar.getInstance() ;
cal.setTime(nDate);
int dayNum = cal.get(Calendar.DAY_OF_WEEK) ;
// Calndar.DAY_OF_WEEK은 일~월 순으로 1부터 값을 반환하나 편의상 월요일을 1값으로 변경하기 위해 아래 제어문을 설정함.
if (dayNum == 1) {
dayNum = 7;
} else {
dayNum -= 1;
}
return dayNum;
}
public static void main(String[] args) throws Exception {
// 요청 날짜 받기
Scanner sc = new Scanner(System.in);
System.out.print("연도를 입력하세요. ");
int year = sc.nextInt();
if (year < 0) {
System.out.print("자연수로 입력하세요. ");
year = sc.nextInt();
}
System.out.print("월을 입력하세요. ");
int month = sc.nextInt();
if (month < 0 || month > 12) {
System.out.print("12 이하의 자연수로 입력하세요. ");
month = sc.nextInt();
}
sc.close();
// 윤년 계산
int dayMax = 0;
int dayData[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
boolean isLeapYear = year%4 == 0 && (year%100 !=0 || year%400 ==0);
if (isLeapYear && month == 2) {
dayMax = dayData[month-1] + 1;
}
if ((isLeapYear && month != 2) || isLeapYear == false) {
dayMax = dayData[month-1];
}
// 요일 계산을 위한 변수 설정
int day = 1;
String yearStr = String.valueOf(year);
String monthStr = String.valueOf(month);
String dayStr = String.valueOf(day);
String inputDay = yearStr + "-" + monthStr + "-" + dayStr;
int dayNum = getFirstDay(inputDay, "yyyy-MM-dd");
// 달력 형식 텍스트 출력
// 이모지 출력:
System.out.println();
System.out.println(" ⛅⛅⛅⛅ " + yearStr + "-" + monthStr + " ⛅⛅⛅⛅");
System.out.println("MON TUE WED THU FRI SAT SUN");
// 요일의 위치에 맞게 일자가 시작되도록, 1일의 요일값(dayNum)에 따라 입력 회수를 설정하여 공백을 출력한다.
// dayNum은 DayNum.getFirstDay() 에서 월: 1 ~ 일:7 로 지정함.
for (int i = 0; i < dayNum; i++) {
if (i > 0) {
System.out.print(" ");
}
}
// 날짜 전체 출력하기
// 1~ daymax까지 반복문을 통해 출력한다.
// 이 때 일요일이 지나면 줄바꿈하도록 한다. (day+dayNum-1)%7 == 0
// 두자리 수는 공백을 한 자리만 쓰도록 한다.
for (day = 1; day <= dayMax; day++) {
if (day < 10) {
System.out.print(" " + day + " ");
} else {
System.out.print(day + " ");
}
if ((day+dayNum-1)%7 == 0) {
System.out.print("\n");
}
}
}
}
✔ 아래와 같이 연도, 월에 잘못된 수를 적으면 다시 입력하게끔 하였다.
✔ 윤년일 때 2월달의 날짜가 적용되었다.
연도를 입력하세요. -1
자연수로 입력하세요. 2012
월을 입력하세요. 13
12 이하의 자연수로 입력하세요. 2
⛅⛅⛅⛅ 2012-2 ⛅⛅⛅⛅
MON TUE WED THU FRI SAT SUN
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29
✔ 올바른 수를 입력했을 경우.
연도를 입력하세요. 2022
월을 입력하세요. 3
⛅⛅⛅⛅ 2022-3 ⛅⛅⛅⛅
MON TUE WED THU FRI SAT SUN
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31