import java.util.*;
public class CalendarEx2 {
public static void main(String[] args) {
final String[] DAY_OF_WEEK = {"","일","월","화","수","목","금","토"};
Calendar date1 = Calendar.getInstance();
Calendar date2 = Calendar.getInstance();
//month의 경우 0부터 시작하기 때문에 8월인경우, 7로 지정해야 한다.
//date1.set(2015, Calendar.AUGUST, 15); 와 같이 할수 도 있다.
date1.set(2015, 7,15); // 2015년 8월 15일로 날짜를 설정한다.
System.out.println("date1은 "+toString(date1)+DAY_OF_WEEK[date1.get(Calendar.DAY_OF_WEEK)]+"요일이고, ");
System.out.println("오늘(date2)은 "+toString(date2)+DAY_OF_WEEK[date2.get(Calendar.DAY_OF_WEEK)]+"요일입니다. ");
//두 날짜간의 차이를 얻으려면, getTimeInMillis() 천분의 일초 단위로 변환해야 한다.
long difference= (date2.getTimeInMillis()-date1.getTimeInMillis())/1000;
System.out.println("그 날(date1)부터 지금 (date2)까지 "+difference +"초가 지났습니다.");
System.out.println("일(day)로 계산하면 "+difference/(24*60*60)+"일 입니다.");//1일 = 24 *60 *60
}
public static String toString(Calendar date){
return date.get(Calendar.YEAR)+"년 "+ (date.get(Calendar.MONTH)+1)+"월 "+date.get(Calendar.DATE)+"일 ";
}
}
=======================
date1은 2015년 8월 15일 토요일이고,
오늘(date2)은 2021년 7월 2일 금요일입니다.
그 날(date1)부터 지금 (date2)까지 185587200초가 지났습니다.
일(day)로 계산하면 2148일 입니다.
두 날짜간의 차이를 구하는 예제이다. 날짜와 시간을 원하는 값으로 변경하려면 set메서드를 사용하면 된다.
void set(int field, int value)
void set(int year, int month, int date)
void set(int year, int month, int date, int hourOfDay, int minute)
void set(int year, int month, int date, int hourOfDay, int minute, int second)
- clear()는 모든 필드의 값을 clear(int field)는 지정된 필드의 값을 기본값으로 초기화 한다. 각 필드의 기본값은 Java API문서에서 GreogrianCalendar를 참고하자
두 날짜간의 차이를 구하기 위해서는 두 날짜를 최소단위인 초단위로 변경한 다음 그 차이를 구하면 된다. getTimeInMillis()는 1/1000초 단위로 값을 반환하기 때문에 초 단위를 얻기 위해서는 1000으로 나눠주어야 하고, 일 단위를 얻기 위해서는 24(시간)*60(분)*60(초)*1000 으로 나누어야 한다.
예제에서는 변수 difference에 저장할 때 이미 초단위로 변경하였기 때문에 일 단위로 변경할 때 24(시가) * 60(분) * 60(초)로 나누었다.
시간상의 전후를 알고 싶을 때는 두 날짜간의 차이가 양수인지 음수인지를 판단하면 될 것이다. 아니면 간단히 boolean after(Object when)와 boolean before(Object when)를 사용해도 좋다.
import java.util.*;
public class CalendarEx3 {
public static void main(String[] args) {
final int[] TIME_UNIT = {3600, 60, 1}; //큰 단위를 앞에 놓는다.
final String[] TIME_UNIT_NAME = {"시간", "분", "초"};
Calendar time1 = Calendar.getInstance();
Calendar time2 = Calendar.getInstance();
time1.set(Calendar.HOUR_OF_DAY, 10); //time1을 10시 20분 30초로 설정
time1.set(Calendar.MINUTE, 20);
time1.set(Calendar.SECOND, 30);
time2.set(Calendar.HOUR_OF_DAY, 20); //time2을 20시 30분 10초로 설정
time2.set(Calendar.MINUTE, 30);
time2.set(Calendar.SECOND, 10);
System.out.println("time1 : "+time1.get(Calendar.HOUR_OF_DAY)+"시 "
+time1.get(Calendar.MINUTE)+"분 "+time1.get(Calendar.SECOND)+"초");
System.out.println("time2 : "+time2.get(Calendar.HOUR_OF_DAY)+"시 "
+time2.get(Calendar.MINUTE)+"분 "+time2.get(Calendar.SECOND)+"초");
long differnece = Math.abs(time2.getTimeInMillis()-time1.getTimeInMillis())/1000;
System.out.println("time1과 time2의 차이는 "+differnece+"초 입니다.");
String tmp = "";
for(int i=0; i<TIME_UNIT.length;i++){
tmp += differnece/TIME_UNIT[i] + TIME_UNIT_NAME[i];
differnece %= TIME_UNIT[i];
}
System.out.println("시분초로 변환하면 "+ tmp +" 입니다.");
}
}
====================
time1 : 10시 20분 30초
time2 : 20시 30분 10초
time1과 time2의 차이는 36580초 입니다.
시분초로 변환하면 10시간9분40초 입니다.
두 개의 시간 데이터로부터 초 단위로 차이를 구한 다음, 시분초로 바꿔 출력하는 예제이다. 가장 큰 단위인 시간 단위(3600초)로 나누고 남은 나머지를 다시 분 단위(60초)로 나누면 그 나머지는 초 단위의 값이 된다.
for(int i=0; i<TIME_UNIT.length;i++){
tmp += differnece/TIME_UNIT[i] + TIME_UNIT_NAME[i];
differnece %= TIME_UNIT[i];
}
import java.util.*;
public class CalendarEx4 {
public static void main(String[] args) {
Calendar date = Calendar.getInstance();
date.set(2015, 7,31); //2015년 8월 31일
System.out.println(toString(date));
System.out.println("= 1일 후 =");
date.add(Calendar.DATE, 1);
System.out.println(toString(date));
System.out.println("= 6달 전 =");
date.add(Calendar.MONTH,-6);
System.out.println(toString(date));
System.out.println("= 31일 후(roll) =");
date.roll(Calendar.DATE,31);
System.out.println(toString(date));
System.out.println("= 31일 후(add) =");
date.add(Calendar.DATE,31);
System.out.println(toString(date));
}
public static String toString(Calendar date){
return date.get(Calendar.YEAR)+"년 "+ (date.get(Calendar.MONTH)+1)+"월 "
+date.get(Calendar.DATE)+"일";
}
}
======================
2015년 8월 31일
= 1일 후 =
2015년 9월 1일
= 6달 전 =
2015년 3월 1일
= 31일 후(roll) =
2015년 3월 1일
= 31일 후(add) =
2015년 4월 1일
add(int field, int amount)를 사용하면 지정한 필드의 값을 원하는 만큼 증가 또는 감소시킬 수 있기 떄문에 add메서드를 이용하면 특정 날짜 또는 시간을 기점으로 해서 일정기간 전후의 날짜와 시간을 알아낼 수 있다.
roll(int field, int amount)도 지정한 필드의 값을 증가 또는 감소시킬 수 있는데, add메서드와의 차이점은 다른 필드에 영향을 미치지 않는다는 것이다. 예를 들어 add메서드로 날짜 필드 (Calendar.DATE)의 값을 31만큼 증가시켰다면 다음달로 넘어가므로 월 필드(Calendar.MONTH)의 값도 1 증가하지만, roll메서드는 같은 경우에 월 필드의 값은 변하지 않고 일 필드의 값만 바뀐다.
단, 한가지 예외가 있는데 일 필드(Calendar.DATE)가 말일 (end of month)일 때 , roll메서드를 이용해서 월 필드(Calendar.MONTH)를 변경하면 일 필드(Calendar.DATE)에 영향을 미칠 수 있다.
import java.util.*;
public class CalendarEx5 {
public static void main(String[] args) {
Calendar date = Calendar.getInstance();
date.set(2015, 0,31); // 2015년 1월 31일
System.out.println(toString(date));
date.roll(Calendar.MONTH, 1);
System.out.println(toString(date));
}
public static String toString(Calendar date){
return date.get(Calendar.YEAR)+"년 "+ (date.get(Calendar.MONTH)+1)+"월 "
+date.get(Calendar.DATE)+"일";
}
}
===================
2015년 1월 31일
2015년 2월 28일
2015년 1월 31일에 대해 roll()을 호출해서 월 필드를 1 증가 시켰을 떄, 월 필드는 2월이 되는데 2월에는 31일잉 없기 때문에 2월의 말일인 28일로 자동 변경되었다. add()는 같은 경우에 마찬가지로 자동 변경된다.
import java.util.Calendar;
public class CalendarEx6 {
public static void main(String[] args) {
if(args.length !=2 ){
System.out.println("Usage : java CalendarEx6 2015 9");
return ;
}
int year = Integer.parseInt(args[0]);
int month = Integer.parseInt(args[1]);
int START_DAY_OF_WEEK = 0;
int END_DAY = 0;
Calendar sDay =Calendar.getInstance(); //시작일
Calendar eDay =Calendar.getInstance(); //끝일
//월의 경우 0부터 11까지의 값을 가지므로 1을 뺴주어야 한다.
//예를 들어 , 2015년 11월 1일은 sDay.set(2015, 10, 1);과 같이 해줘야 한다.
sDay.set(year, month-1,1);
eDay.set(year, month,1);
//다음달의 첫날에서 하루를 빼면 현재달의 마지막 날이 된다.
//12월 1일에서 하루를 빼면 11월 30일이 된다.
eDay.add(Calendar.DATE, -1);
//첫번쨰 요일이 무슨 요일인지 알아낸다.
START_DAY_OF_WEEK = sDay.get(Calendar.DAY_OF_WEEK);
//eDay에 지정된 날짜를 얻어온다.
END_DAY = eDay.get(Calendar.DATE);
System.out.println(" "+args[0]+"년 "+args[1]+"월");
System.out.println(" SU MO TU WE TH FR SA");
//해당 월의 1일이 어느요일인지에 따라서 공백을 출력한다.
//만일 1일이 수요일이라면 공백을 세번 찍는다.(일요일부터 시작)
for(int i=1; i<START_DAY_OF_WEEK;i++){
System.out.print(" ");
}
for(int i=1, n=START_DAY_OF_WEEK; i<= END_DAY;i++, n++){
System.out.print((i<10) ?" "+i : " "+i);
if(n%7 ==0) System.out.println();
}
}
}
=========================
java CalendarEx6 2015 11
2015년 11월
SU MO TU WE TH FR SA
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
커맨드라인으로 년과 월을 입력하면 달력을 출력하는 예제이다. 특별히 설명할 것은 없고 다음 달의 1일에서 하루를 빼면 이번달의 마지막 일을 알 수 있다는 것을 기억해야 한다. 예를 들면 2월의 마지막날을 알고 싶을 때는 3월 1일에서 하루를 빼면 된다.
- getActualMaximum(Calendar.Date)를 사용해도 해당 월의 마지막 날을 알 수 있다.
import java.util.*;
public class CalendarEx7 {
public static void main(String[] args) {
if(args.length !=2){
System.out.println("Usage : java CalendarEx7 2015 11");
return;
}
int year = Integer.parseInt(args[0]);
int month = Integer.parseInt(args[1]);
Calendar sDay = Calendar.getInstance(); //시작일
Calendar eDay = Calendar.getInstance(); //끝일
//월의 경우 0부터 11까지의 값을 가지므로 1을 빼줘야 한다.
//예를 들어, 2004년 11월 1일은 sDay.set(2004, 10, 1);과 같이 해줘야 한다.
sDay.set(year, month-1,1); //입력일의 1일로 설정한다.
//입력 월의 말일로 설정한다.
eDay.set(year,month-1,sDay.getActualMaximum(Calendar.DATE));
//1일이 속한 주의 일요일로 날짜 설정
sDay.add(Calendar.DATE, -sDay.get(Calendar.DAY_OF_WEEK)+1);
//말일이 속한 주의 토요일로 날짜 설정
eDay.add(Calendar.DATE, 7-eDay.get(Calendar.DAY_OF_WEEK));
System.out.println(" "+ year+"년 "+month+"월");
System.out.println(" SU MO TU WE TH FR SA");
//시작일 부터 마지막 일까지 (sDay<=eDay) 1일씩 증가시키면서 일(Calendar.Date)을 출력
for(int n=1; sDay.before(eDay) || sDay.equals(eDay); sDay.add(Calendar.DATE, 1)){
int day = sDay.get(Calendar.DATE);
System.out.print((day <10) ? " "+day :" "+day);
if(n++%7 ==0) System.out.println();
}
}
}
================================
2015년 11월
SU MO TU WE TH FR SA
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 1 2 3 4 5
이전 예제를 첫 주와 마지막주가 이전달, 이후달과 연결되도록 변경하였다.
public class CalendarEx8 {
public static void main(String[] args) {
String date1= "201508";
String date2 = "201405";
//년과 일을 substring으로 잘라서 정수로 변환한다.
//년에 12를 곱해서 월로 변환한다음에 뺼셈을 하면 개월차를 구할 수 있다.
int month1 = Integer.parseInt(date1.substring(0,4))*12
+Integer.parseInt(date1.substring(4));
int month2 = Integer.parseInt(date2.substring(0,4))*12
+Integer.parseInt(date2.substring(4));
System.out.println(date1+"과 "+date2+"의 차이는 "+Math.abs(month1-month2)+ "개월 입니다.");
}
}
===============
201508과 201405의 차이는 15개월 입니다.
년과 월 정도의 계산이라면, 굳이 Calendar를 사용하지 않고 이처럼 간단히 처리해도 좋을 것이다.
public class CalendarEx9 {
public static void main(String[] args) {
System.out.println("2014. 5. 31 : "+getDayOfWeek(2014, 5, 31));
System.out.println("2012. 6. 1 : "+getDayOfWeek(2012, 6, 1));
System.out.println("2014. 5. 1- 2014. 4. 28 :"+dayDiff(2014, 5, 1, 2014, 4, 28));
System.out.println("2015. 6. 29 : "+convertDateToDay(2015,6,29));
System.out.println("735778 : "+converDayToDate(735778));
}
public static int[] endOfMonth = {31,28,31,30,31,30, //각 달의 마지막 달
31,31,30,31,30,31};
public static boolean isLeapYear(int year){
return ((year%4==0)&&(year%100 !=0)|| (year%400==0));
}
public static int dayDiff(int y1, int m1, int d1, int y2, int m2, int d2){
return convertDateToDay(y1, m1, d1) - convertDateToDay(y2, m2, d2);
}
public static int getDayOfWeek(int year, int month, int day){
//1~7의 값을 반환한다. 결과가 1이면 일요일이다.
return convertDateToDay(year, month, day) %7 +1;
}
public static String converDayToDate(int day){
int year =1;
int month =0;
while(true){
int aYear = isLeapYear(year) ? 366 : 365;
if(day > aYear){
day -= aYear;
year++;
}else{
break;
}
}
while(true){
int endDay = endOfMonth[month];
//윤년이고 윤달이 포함되어 있으면 1일을 더한다.
if(isLeapYear(year) && month ==1) endDay++;
if(day>endDay){
day -= endDay;
month++;
}else{
break;
}
}
return year+"-"+(month+1)+"-"+day;
}
public static int convertDateToDay(int year, int month, int day){
int numOfLeapYear =0; //윤년의 수
//전 년도까지의 윤년의 수를 구한다.
for(int i=1; i<year; i++){
if(isLeapYear(i))
numOfLeapYear++;
}
//전년도까지의 일수를 구한다.
int toLastYearDaySum=(year-1) * 365 + numOfLeapYear;
//올해의 현재 월까지의 일 수 계산
int thisYearDaySum=0;
for(int i=0; i<month-1; i++)
thisYearDaySum +=endOfMonth[i];
//윤년이고 , 2월이 포함되어 있으면 1일을 증가시킨다.
if(month >2 && isLeapYear(year))
thisYearDaySum++;
thisYearDaySum += day;
return toLastYearDaySum+thisYearDaySum;
}
}
========================
2014. 5. 31 : 7
2012. 6. 1 : 6
2014. 5. 1- 2014. 4. 28 :3
2015. 6. 29 : 735778
735778 : 2015-6-29
이 예제는 날짜 계산을 위한 몇 가지 메서드를 직접 구현해 보았다. 여기서 작성한 메서드의 기능을 요약하면 다음과 같다.
boolean isLeapYear(int year)
: 매개변수 year가 윤년이면 true를 그렇지 않으면 false를 반환한다.
int dayDiff(int y1, int m1, int d1, int y2, int m2, int d2)
: 두 날짜 간의 차이를 일단위로 반환한다.
int getDayOfWeek(int year, int month, int day)
: 지정한 날짜의 요일을 반환한다.(1~7, 1이 일요일)
String converDayToDate(int day)
: 일단위의 값을 년월일의 형태의 문자열로 변환하여 반환한다.
int converDateToDay(int year, int month, int day)
: 년월일을 입력받아서 일단위로 변환한다.
날짜를 일단위로, 일단위의 값을 날짜로 바꾸는 것을 제외하고는 간단하다. 두 날짜의 차이를 구하려면, 일단위로 변환한 다음 두 값을 서로 뺴기만 하면 된다.
요일을 구하는 것은 일단위로 바꾼 다음에 요일의 개수인 7로 나누고, 요일이 1부터 시작하기 위해서 1을 더했다. 1을 더하지 않고 요일의 범위를 0~6으로 해도 되지만, Calendar에서의 요일범위가 1~7이기 때문에 동일하게 처리했다.
- 일 단위로 변환할 때 서기 1년 1월 1일부터의 일의 수를 계산하였지만, Calendar의 경우 1970년 1월 1일을 기준으로 계산한다. 그래서 1970년 1월 1일 이전의 날짜에 대해 getTimeInMillis()를 호출하면 음수를 결과로 얻는다.
'Back-end' 카테고리의 다른 글
01 데이터 베이스 (0) | 2021.07.04 |
---|---|
10 날짜와 시간 & 형식화 (3) (0) | 2021.07.03 |
10 날짜와 시간 & 형식화(1) (0) | 2021.07.02 |
java.lang패키지와 유용한 클래스(8) (0) | 2021.07.01 |
java.lang패키지와 유용한 클래스(7) (0) | 2021.07.01 |