해당 게시물은 자바의 정석을 정리한 내용 입니다.
1. 날짜와 시간
1.1 Calendar와 Date
java.util.Date
- 날짜와 시간을 다룰 목적으로 만들어진 클래스(JDK1.0)
- Date의 메서드는 거의 deprecated되었지만, 여전히 쓰이고 있다.
java.util.Date
- Date클래스를 개선한 새로운 클래스(JDK1.1). 여전히 단점이 존재
java.time 패키지
- Date와 Calendar의 단점을 개선한 새로운 클래스들을 제공(JDK1.8)
1.2 Calendar 클래스
Calendar와 GregorianCalendar
- Calendar는 추상 클래스이므로 getInstance()를 통해 구현된 클래스의 인스턴스를 얻어야 한다. (직접 객체를 생성할 수 없음)
- Calendar를 상속 받아 완전히 구현한 클래스로는 GregorianCalendar와 BuddhistCalendar가 있는데 getInstance()는 시스템의 국가와 지역 설정을
확인해서 태국인 경우에는 BuddhistCalendar의 인스턴스를 반환하고, 그 외에는 GregorianCalendar의 인스턴스를 반환한다.
Calendar cal = Calendar.getInstance(); // Calendar 클래스를 구현한 클래스의 인스턴스를 반환
// 해당 인스턴스는 현재 날짜와 시간으로 설정 됨
int thisYear = cal.get(Calendar.YEAR); // 현재 날짜와 시간에서 년도를 반환
int lastDayOfMonth = cal.getActualMaximum(Calendar.DATE); // 이 달의 마지막 날짜를 반환
Date와 Calendar 간의 변화
- Calendar를 Date 또는 그 반대로 변환할 일이 생길 수 있다. 그럴 때는 다음과 같이 하자.
1. Calendar를 Date로 변환
Calendar cal = Calendar.getInstance();
. . .
Date d = new Date(cal.getTimeInMillis());
2. Date를 Calendar로 변환
Date d = new Date();
. . .
Calendar cal = Calendar.getInstance();
cal.setTime(d);
Calendar에 정의된 필드 (날짜)
필드명 |
설 명 |
YEAR |
년 |
MONTH |
월 (0부터 시작) |
WEEK_OF_YEAR |
그 해의 몇 번째 주 |
WEEK_OF_MONTH |
그 달의 몇 번째 주 |
DATE |
일 |
DAY_OF_MONTH |
그 달의 몇 번째 일 |
DAY_OF_YEAR |
그 해의 몇 번째 일 |
DAY_OF_WEEK |
요일 |
DAY_OF_WEEK_IN_MONTH |
그 달의 몇 번째 요일 |
Calendar에 정의된 필드 (시간)
필드명 |
설 명 |
HOUR |
시간(0~11) |
HOUR_OF_DAY |
시간(0~23) |
MINUTE |
분 |
SECOND |
초 |
MILLISECOND |
천분의 일초 |
ZONE_OFFSET |
GMT 기준 시차(천분의 일초 단위) |
AM_PM |
오전 / 오후 |
get()으로 날짜와 시간 필드 가져오기
class CalendarEx1 {
public static void main(String[] args)
{ // 기본적으로 현재 날짜와 시간으로 설정된다.
Calendar today = Calendar.getInstance();
System.out.println("이 해의 년도 : " + today.get(Calendar.YEAR));
System.out.println("월(0~11, 0:1월): " + today.get(Calendar.MONTH));
System.out.println("이 해의 몇 째 주: " + today.get(Calendar.WEEK_OF_YEAR));
System.out.println("이 달의 몇 째 주: " + today.get(Calendar.WEEK_OF_MONTH));
// DATE와 DAY_OF_MONTH는 같다.
System.out.println("이 달의 몇 일: " + today.get(Calendar.DATE));
System.out.println("이 달의 몇 일: " + today.get(Calendar.DAY_OF_MONTH));
System.out.println("이 해의 몇 일: " + today.get(Calendar.DAY_OF_YEAR));
// 1:일요일, 2:월요일, ... 7:토요일
System.out.println("요일(1~7, 1:일요일): " + today.get(Calendar.DAY_OF_WEEK));
System.out.println("이 달의 몇 째 요일: " + today.get(Calendar.DAY_OF_WEEK_IN_MONTH));
System.out.println("오전_오후(0:오전, 1:오후): " + today.get(Calendar.AM_PM));
System.out.println("시간(0~11): " + today.get(Calendar.HOUR));
System.out.println("시간(0~23): " + today.get(Calendar.HOUR_OF_DAY));
System.out.println("분(0~59): " + today.get(Calendar.MINUTE));
System.out.println("초(0~59): " + today.get(Calendar.SECOND));
System.out.println("1000분의 1초(0~999): " + today.get(Calendar.MILLISECOND));
// 천분의 1초를 시간으로 표시하기 위해 3600000으로 나누었다.(1시간 = 60 * 60초)
System.out.println("TimeZone(-12~+12): " + (today.get(Calendar.ZONE_OFFSET)/(60*60*1000)));
System.out.println("이 달의 마지막 날: " + today.getActualMaximum(Calendar.DATE) ); // 이 달의 마지막 일을 찾는다.
}
}
set()으로 날짜와 시간 지정 하기
- 날짜와 시간을 원하는 값으로 변경하려면 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) // 년, 월, 일 , 시, 분, 초를 설정
- 날짜 지정하는 방법.
월(MONTH)이 0부터 시작한다는 점에 주의
Calendar date1 = Calendar.getInstace();
date1.set(2017, 7, 15); // 2017년 8월 15일 (7월 아님)
// date1.set(Calendar.YEAR, 2017);
// date1.set(Calendar.MONTH, 7);
// date1.set(Calendar.DATE, 15);
- 시간 지정하는 방법
Calendar time1 = Calendar.getInstance();
time1.set(Calendar.HOUR_OF_DAY, 10); // time1을 10시 20분 30초로 설정
time1.set(Calendar.MINUTE, 20);
time1.set(Calendar.SECOND, 30);
class CalendarEx2 {
public static void main(String[] args) {
// 요일은 1부터 시작하기 때문에, DAY_OF_WEEK[0]은 비워두었다.
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) + "일 ";
}
}
아래 코드는 두 개의 시간 데이터로 부터 초 단위로 차이를 구한 다음, 시 분 초로 바꿔 출력하는 예제이다.
가장 큰 단위인 시간 단위(3600초)로 나누고 남은 나머지를 다시 분 단위(60초)로 나누면 그 나머지는 초 단위의 값이 된다.
해당 방식은 거스름돈(동전)을 구하는 문제와 유사하다.
예를 들어 2680원이 있다면 거스름돈은 아래와 같이 구할 수 있다.
2680 / 500 = 5 // 500원 짜리 5개
2680 % 500 = 180. // 180원 남음
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의 시간을 10시 20분 30초로 설정한다.
time1.set(Calendar.HOUR_OF_DAY, 10);
time1.set(Calendar.MINUTE, 20);
time1.set(Calendar.SECOND, 30);
// time2의 시간을 20시 30분 10초로 설정한다.
time2.set(Calendar.HOUR_OF_DAY, 20);
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 difference = Math.abs(time2.getTimeInMillis() - time1.getTimeInMillis())/1000;
System.out.println("time1과 time2의 차이는 "+ difference +"초 입니다.");
String tmp = "";
for(int i=0; i < TIME_UNIT.length;i++) {
tmp += difference/TIME_UNIT[i]+ TIME_UNIT_NAME[i];
difference %= TIME_UNIT[i];
}
System.out.println("시분초로 변환하면 " + tmp + "입니다.");
}
}
clear()와 clear(int field)로 Calendar객체 초기화 하기
- clear()는 Calendar객체의 모든 필드를 초기화
Calendar dt = Calendar.getInstance();
// 현재 날짜와 시간
System.out.println(new Date(dt.getTimeInMillis()));
dt.clear(); // 모든 필드를 초기화
// 1970년 1월 1일 00:00:00 으로 바뀜 (EPOCH TIME)
System.out.println(new Date(dt.getTimeInMillis()));
- clear(int field)는 Calendar객체의 특정 필드를 초기화
Calendar dt = Calendar.getInstance();
System.out.println(new Date(dt.getTimeInMillis()));
dt.clear(Calendar.SECOND); // 초를 초기화
dt.clear(Calendar.MINUTE); // 분을 초기화
dt.clear(Calendar.HOUR_OF_DAY); // 시간을 초기화
dt.clear(Calendar.HOUR); // 시간을 초기화
System.out.println(new Date(dt.getTimeInMillis()));
add() 또는 roll()로 특정 필드의 값을 증가 또는 감소
-add()는 특정 필드의 값을 증가 또는 감소 (다른 필드에 영향 O)
Calendar date = Calendar.getInstance();
date.clear(); // 모든 필드를 초기화
date.set(2020, 7, 31); // 2020년 8월 31일로 설정
date.add(Calendar.DATE, 1); // 날짜(DATE)에 1을 더한다.
date.add(Calendar.MONTH, -8); // 월(MONTH)에서 8을 뺀다.
-roll()는 특정 필드의 값을 증가 또는 감소 (다른 필드에 영향 X)
date.set(2020, 7, 31); // 2020년 8월 31일로 설정
// add()와 달리 roll()은 다른 필드에 영향을 미치지 않는다.
date.roll(Calendar.DATE, 1); // 날짜(DATE)에 1을 더한다.
date.roll(Calendar.MONTH, -8); // 월(MONTH)에서 8을 뺀다.
2. 형식화 클래스
형식화 클래스는 java.text 패키지에 포함되어 있으며 숫자, 날짜, 텍스트 데이터를 일정한 형식에 맞게 표현할 수 있는 방법을
표준화 하였다.
형식화 클래스는 형식화에 사용될 패턴을 정의하는데, 데이터를 정의된 패턴에 맞춰 형식화할 수 있을 뿐만 아니라 역으로 형식화된
데이터에서 원래의 데이터를 얻어낼 수도 있다.
2.1 DecimalFormat
숫자 → 문자열 : format()
문자열 → 숫자 : parse()
- 숫자를 형식화 할 때 사용한다. (숫자 → 형식 문자열)
Double number = 1234567.89;
DecimalFormat df = new DecimalFormat(“#.#E0”);
String result = df.format(number);
- 특정 형식의 문자열을 숫자로 변환할 때도 사용한다. (형식 문자열 → 숫자)
DecimalFormat df = new DecimalFormat(“#,###.##”);
Number num = df.parse(“1,234,567.89”); // Number : 모든 숫자 래퍼 클래스의 최고 조상
Double d = num.doubleValue();
[참고] Integer.parseInt()와 같은 메서드는 콤마(,)가 포함된 문자열을 숫자로 변환 할 수 없음
2.2 SimpleDateFormat
날짜, 시간 → 문자열 : format()
문자열 → 날짜, 시간 : parse()
- 숫자를 형식화 할 때 사용한다. (숫자. → 형식 문자열)
Date today = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
// 오늘 날짜를 yyyy-MM-dd 형태로 변환하여 반환한다.
String result = df.format(today);
- 특정 형식으로 되어 있는 문자열에서 날짜와 시간을 뽑아낼 수도 있다.
문자열 → Date → 문자열
parse() format()
DateFormat df = new SimpleDateFormat("yyyy년 MM월 dd일");
DateFormat df2 = new SimpleDateFormat("yyyy/MM/dd");
Date d = df.parse("2015년 11월 23일"); // 문자열을 Date로 변환
String result = df2.format(d); // Date를 문자열로 변환
class DateFormatEx1 {
public static void main(String[] args) {
Date today = new Date();
SimpleDateFormat sdf1, sdf2, sdf3, sdf4;
SimpleDateFormat sdf5, sdf6, sdf7, sdf8, sdf9;
sdf1 = new SimpleDateFormat("yyyy-MM-dd");
sdf2 = new SimpleDateFormat("''yy년 MMM dd일 E요일");
sdf3 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
sdf4 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss a");
sdf5 = new SimpleDateFormat("오늘은 올 해의 D번째 날입니다.");
sdf6 = new SimpleDateFormat("오늘은 이 달의 d번째 날입니다.");
sdf7 = new SimpleDateFormat("오늘은 올 해의 w번째 주입니다.");
sdf8 = new SimpleDateFormat("오늘은 이 달의 W번째 주입니다.");
sdf9 = new SimpleDateFormat("오늘은 이 달의 F번째 E요일입니다.");
System.out.println(sdf1.format(today)); // format(Date d)
System.out.println(sdf2.format(today));
System.out.println(sdf3.format(today));
System.out.println(sdf4.format(today));
System.out.println();
System.out.println(sdf5.format(today));
System.out.println(sdf6.format(today));
System.out.println(sdf7.format(today));
System.out.println(sdf8.format(today));
System.out.println(sdf9.format(today));
}
}
2.3 ChoiceFormat
- ChoiceFormat은 특정 범위에 속하는 값을 문자열로 변환해준다.
class ChoiceFormatEx1 {
public static void main(String[] args) {
double[] limits = {60, 70, 80, 90}; // 낮은 값부터 큰 값의 순서로 적어야한다.
// limits, grades간의 순서와 개수를 맞추어야 한다.
String[] grades = {"D", "C", "B", "A"};
int[] scores = { 100, 95, 88, 70, 52, 60, 70};
ChoiceFormat form = new ChoiceFormat(limits, grades);
for(int i=0;i<scores.length;i++) {
System.out.println(scores[i]+":"+form.format(scores[i]));
}
} // main
}
위의 코드에서 두 개의 배열이 사용되었는데 하나(limits)는 범위의 경계 값을 저장하는데 사용하였고, 또 하나(grades)는 범위에 포함된 값을 치환할
문자열을 저장하는데 사용되었다.
class ChoiceFormatEx2 {
public static void main(String[] args) {
String pattern = "60#D|70#C|80<B|90#A";
int[] scores = { 91, 90, 80, 88, 70, 52, 60};
ChoiceFormat form = new ChoiceFormat(pattern);
for(int i=0;i<scores.length;i++) {
System.out.println(scores[i]+":"+form.format(scores[i]));
}
} // main
}
위의 코드는 이전 예제를 패턴을 사용하도록 변경한 것이다.
패턴은 구분자로 '#'와 '<' 두 가지를 제공하는데 'limit#value'의 형태로 사용한다.
'#'는 경계 값을 범위에 포함시키지만, '<'는 포함시키지 않는다.
위의 결과에서 90은 A지만, 80은 B가 아닌, C이다.
2.4 MessageFormat
- MessageFormat은 데이터를 정해진 양식에 맞게 출력할 수 있도록 도와준다.
- 데이터가 들어갈 자리를 마련해 놓은 양식을 미리 작성하고 프로그램을 이용해서 다수의 데이터를 같은 양식으로 출력할 때 사용하면 좋다.
- MessageFormat의 parse를 이용하면 지정된 양식에서 필요한 데이터만을 추출해 낼수도 있다.
class MessageFormatEx1 {
public static void main(String[] args) {
String msg = "Name: {0} \nTel: {1} \nAge:{2} \nBirthday:{3}";
Object[] arguments = {
"이자바","02-123-1234", "27", "07-09"
};
String result = MessageFormat.format(msg, arguments);
System.out.println(result);
}
}
MessageFormat에 사용할 양식인 문자열 msg를 작성할 때 '{숫자}'로 표시된 부분이 데이터가 출력될 자리이다.
여기에 사용되는 숫자는 배열처럼 인덱스가 0 부터 시작하며 양식에 들어갈 데이터는 객체 배열인 arguments에 지정되어 있음을 알 수 있다.
3. java.time 패키지
자바의 정석 p552 참고
'Java > 객체 지향 개념 ~' 카테고리의 다른 글
자바의 정석 (Chapter 12. 제네릭, 열거형, 애노테이션) (1) | 2020.08.28 |
---|---|
자바의 정석 (Chapter 11. 컬렉션 프레임워크) (0) | 2020.08.23 |
자바의 정석 (Chapter 9. java.lang 패키지와 유용한 클래스) (0) | 2020.08.14 |
자바의 정석 (Chapter 8. 예외 처리) (1) | 2020.08.08 |
자바의 정석 (Chapter 7_3. 객체지향개념 2) (0) | 2020.08.03 |
댓글