Calendar 클래스
추상클래스이므로 getInstance 메서드를 통해 구현된 객체를 얻어야 한다.
새롭게 new를 사욯해서 Calendar 자료형을 선언하는 것은 불가능
Calendar를 사용해서 날짜필드 가져오기
- 아래 형식으로 가져온다.
출력값:
28
2022
Calendar ca = Calendar.getInstance();
// 캘린더 추상클래스를 선언하면 시스템의 최신 시간을 가져온다
int year = ca.get(Calendar.YEAR);
// 현재 시스템 시간 상의 최신 년도
int lastday = ca.getActualMaximum(Calendar.DATE);
// 이달의 마지막 날
System.out.println(lastday);
System.out.println(year);
Calendar 시간 차이 구하기 예시
- getTimeInMillis로 지난 시간을 1/1000으로 구한 후 초단위로 환산해서 일단위로 변환한다
- 이 때 일단위는 (24시간*60분*60초)로 나눠서 환산한다
// 두 날짜간의 시간의 차이를 알려면 전부 초로 환산한 후에 일(24시간*60분*60초)로 나눈다
military.set(2020,3,6);
long differ = (ca2.getTimeInMillis() - military.getTimeInMillis()) / 1000;
System.out.println(differ/(24*60*60));
// 681일
- 위의 예시를 좀더 심화하여 오늘 00시 기준으로 얼마나 시간이 지났는지를 표시하는 프로그램을 만들어보면 아래와 같이 나온다.
- 현재 시각을 Calendar 클래스로 받아오고 다른 Calendar 클래스에는 현재 시간을 0시 0분 0초로 맞춰놓는다.
- 현재시각 - 0시를 연산하여 1/1000으로 구한 후에 1000을 다시 곱해 총 몇초가 지났는지 체크한다
- 받아온 초를 거스름돈 구하는 알고리즘을 사용하여 시간, 분, 초로 다시 연산한 후 표시한다
- 거스름돈: 제일 큰 수로 나눈 후에 구하고 난 나머지 값을 그다음 작은 수로 나누면 다음 값이 나옴
출력문: 현재시각: 오전 6시 34분 32초
Calendar ca = Calendar.getInstance();
Calendar ca2 = Calendar.getInstance();
ca.set(Calendar.HOUR_OF_DAY, 0);
ca.set(Calendar.MINUTE, 0);
ca.set(Calendar.SECOND, 0);
long differ = Math.abs((ca2.getTimeInMillis() - ca.getTimeInMillis()) / 1000);
timecounting(differ);
}
static void timecounting(long d) {
int[] tmp = {3600,60,1};
int[] time = new int[3];
for(int i = 0; i<3; i++) {
time[i] = (int)d/tmp[i];
d%=tmp[i];
}
if(time[0]>12) {
System.out.println("현재시각: 오후 " + (time[0]-12) + "시 " + time[1] + "분 " + time[2] + "초");
}
System.out.println("현재시각: 오전 " + time[0] + "시 " + time[1] + "분 " + time[2] + "초");
Calendar 메서드
1. clear()메서드를 사용하여 전체시간을 초기화 시킬 수 있다.
- 아래처럼 clear를 공백으로 선언하면 전체시간을 초기화시켜 1970년으로 설정되고 따로 필드를 지정하여 특정 시간/날짜만 초기화 시킬 수 있다.
출력문:
초기화 전 시간: 54
초기화 후 시간: 0
Thu Jan 01 00:00:00 KST 1970
System.out.println("초기화 전 시간: " + ca3.get(Calendar.MINUTE));
ca3.clear(ca3.MINUTE);
System.out.println("초기화 후 시간: " + ca3.get(Calendar.MINUTE));
ca3.clear(); // 모든 시간 초기화
System.out.println(new Date(ca3.getTimeInMillis()));
아래의 필드를 2. get 또는 set을 사용하여 읽어오거나 설정할 수 있다.
3. roll & add
add를 사용하면 다른 필드와 지정한 필드의 숫자를 동시에 변경한다.
- roll을 사용하면 다른 필드에 영향을 미치지 않고 지정한 필드의 숫자만 변경한다.
- 예를 들어 2022년 12월 31일로 설정해놓은 Calendar 클래스에 add 메서드로 월을 1일 추가하면 2023년 1월 31일로 변경되지만 roll을 사용할 경우 2022년 1월 31일로 월만 변경되고 년은 그대로 출력된다.
- 아래의 예시 참조
*예시에서는 +만 사용했지만 -도 가능하다. 필드에 -만 붙여서 선언!
출력문:
Sat Dec 31 14:29:57 KST 2022 - 원래의 설정값
Mon Jan 31 14:29:57 KST 2022 - roll을 사용하여 월만 변경한 값, 년도는 변경되지 않음
Tue Feb 01 14:29:57 KST 2022 - add를 사용하여 date를 변경한 값 (월 & 일이 동시에 변경!)
Calendar ca3 = Calendar.getInstance();
ca3.set(2022, 11, 31);
System.out.println(new Date(ca3.getTimeInMillis()));
ca3.roll(ca3.MONTH, 1);
System.out.println(new Date(ca3.getTimeInMillis()));
ca3.add(ca3.DATE, 1);
System.out.println(new Date(ca3.getTimeInMillis()));
Calendar 메서드를 사용한 달력 출력
1. Run Configuratoin에서 출력할 문자열을 지정해 출력하였다. (예시는 2022년 2월을 예시로 두었다)
2. get(Calendar.DAY_OF_WEEK)으로 지정한 달의 시작 요일을 구하고
3. 다른 Calendar 클래스로 set()지정을 다음달, 날짜(date)에 -1을 하여 지정 달의 마지막 날을 구한다.
4. for문으로 시작 요일의 숫자만큼 공백을 달력에 출력하여 시작요일의 공백을 넣어주고
5. 다른 for문으로 시작요일의 숫자와 매개변수 i를 동시에 증가시켜 매번 시작요일이 7로 나누어 떨어질 때 마다 줄 띄어쓰기를 해준다.
출력문:
Calendar start = Calendar.getInstance();
Calendar end = Calendar.getInstance();
int year = Integer.valueOf(args[0]);
int month = Integer.valueOf(args[1]);
start.set(year, month-1, 1);
end.set(year, month, 1);
end.add(Calendar.DATE, -1);
int dayweek = start.get(Calendar.DAY_OF_WEEK);
// 지정된 요일 불러오기
// 일욜부터 1-7순 일월화수목금토
System.out.println();
System.out.printf("=========[%d월]=========\n", month);
System.out.println(" SU MO TU WE TH FR SA ");
// 시작요일이 3, 즉 화요일이기 때문에 일, 월을 2번씩 빈칸으로 두고
// 다음 for문에서 달력을 프린트한다
for(int i = 1; i<dayweek; i++) {
System.out.print(" ");
}
for(int i = 1, n = dayweek; i<=end.get(Calendar.DATE); i++, n++) {
System.out.printf("%3d", i);
if(n%7 == 0) {
System.out.println();
}
}
Calendar 클래스를 Date 클래스로 변환
거의 deprecated 되었지만 아직까지 많이 쓰고있는 방식이기 때문에 외우지는 말고 눈에만 익도록 만들자.
*원래 Calendar 클래스의 출력문은 난해하나 출력문 메서드로 가독성을 높임
public static void main(String[] args) {
Calendar ca = Calendar.getInstance();
Date d = new Date(ca.getTimeInMillis());
// Calendar 클래스를 Date클래스로 변환
System.out.println(d);
ca.setTime(d);
// Date클래스를 Calendar클래스로 변환
time(ca);
}
출력문:
Thu Feb 17 10:08:01 KST 2022
2022년 1월 17일
Calendar 클래스 Date 클래스를 활용한 응용 연습문제
문제:
어떤 회사의 월급날이 매월 21일이다. 두 날짜 사이에 월급날이 몇 번있는지 계산해서 반환하는 메서드를 작성하고 테스트 하시오.
출력문:
2020-01-01 ~ 2020-01-01:월급 받은 수 0
2020-01-21 ~ 2020-01-21:월급 받은 수 1
2020-01-01 ~ 2020-03-01:월급 받은 수 2
2020-01-01 ~ 2020-03-23:월급 받은 수 3
2020-04-23 ~ 2020-01-21:월급 받은 수 0
2021-01-22 ~ 2020-03-21:월급 받은 수 0
Calendar fromCal = Calendar.getInstance();
Calendar toCal = Calendar.getInstance();
fromCal.set(2020,0,1);
toCal.set(2020,0,1);
printResult(fromCal, toCal);
System.out.println(paycheckCount(fromCal, toCal));
fromCal.set(2020,0,21);
toCal.set(2020,0,21);
printResult(fromCal, toCal);
System.out.println(paycheckCount(fromCal, toCal));
fromCal.set(2020,0,1);
toCal.set(2020,2,1);
printResult(fromCal, toCal);
System.out.println(paycheckCount(fromCal, toCal));
fromCal.set(2020,0,1);
toCal.set(2020,2,23);
printResult(fromCal, toCal);
System.out.println(paycheckCount(fromCal, toCal));
fromCal.set(2020,3,23);
toCal.set(2020,0,21);
printResult(fromCal, toCal);
System.out.println(paycheckCount(fromCal, toCal));
fromCal.set(2021,0,22);
toCal.set(2020,2,21);
printResult(fromCal, toCal);
System.out.println(paycheckCount(fromCal, toCal));
}
static void printResult(Calendar from, Calendar to) {
Date fromDate = from.getTime();
// Calendar 클래스를 getTime으로 Date클래스로 변환
Date toDate = to.getTime();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
// SimpleDateFormat으로 기본 형식을 지정해준 후 Date 클래스를 출력한다
System.out.print(sdf.format(fromDate)+" ~ "
+sdf.format(toDate)+":");
}
static int paycheckCount(Calendar from, Calendar to) {
int count = to.get(Calendar.MONTH) - from.get(Calendar.MONTH);
// 월급을 받은 수를 count로 지정한다. 월이 다른만큼 count의 기본 개수를 지정했다.
if(from.get(Calendar.DAY_OF_MONTH)<=21){
count++;
// 만약 시작일이 21일 이전이면 count에 1을 추가한다.
if(to.get(Calendar.DAY_OF_MONTH)<21)
count--;
// 마지막날이 21일 이하이면 중복중첩을 막기위해 1을 제거한다.
}
if(to.get(Calendar.YEAR) - from.get(Calendar.YEAR) < 0 || to.get(Calendar.MONTH) - from.get(Calendar.MONTH) < 0){
return 0;
// 만약 년도의 차이가 -거나 월의 차이가 -라면 0을 반환한다.
}
return count;
}
}
'Java > 자바의정석 기초편' 카테고리의 다른 글
자바의 정석 10장 (27일차) - Collection Framework (Set/List/Map) (0) | 2022.02.18 |
---|---|
자바의 정석 10장 (26일차) - 형식화 클래스 (SimpleDateFormat, DecimalFormat) (0) | 2022.02.17 |
자바의 정석 9장 (25일차) - StringBuilder & Math (0) | 2022.02.16 |
자바의 정석 9장 (25일차) - StringBuffer 생성자 & 메서드 (0) | 2022.02.16 |
자바의 정석 9장 (25일차) - String 메서드 2 (0) | 2022.02.16 |