날짜와 시간
java.util.Data :
- 날짜와 시간을 다룰 목적으로 만들어진 클래스(JDK1.0)
- Date의 메서드는 거의 deprecated되었지만 여전히 쓰이고 있음
java.util.Calendar
- Date클래스를 개선한 새로운 클래스(JDK1,1) . 여전히 단점이 존재
java.time 패키지
- Date와 Calender의 단점을 개선한 새로운 클래스들을 제공(JDK1.8)
Data,Calendar는 날싸와 시간을 항상 같이 다루는게 단점. time은 날짜와 시간을 따로 다룰수 있게 세분화 되어있음
Calendar클래스
- 추상 클래스미으로 getInstance()를 통해 구현된 객체를 얻어야함
Calendar cal = new Calendar(); //error 추상클래스는 인스턴스를 생성할 수 없음
Calender cal = Calendar.getInstance();//getInstance()메서드는 Calendar클래스를 구현한 클래스의 인스턴스를 반환
직접 사용할 클래스를 지정해주는것보다 메서드를 통해서 상황에 맞는 객체를 반환하도록 하는게 좋음(추상화)
-get()으로 날짜와 시간 필드 가져오기(필드 일기) : int get(int field)
Calendar cal = Calendar.getInstance();//현재 날짜와 시간으로 세팅
int thisYear=cal.get(Calendar.YEAR);//올해가 몇년인지 알아냄
int lastDayOFMonth=cal.getActualMaximum(Calendar.DATE);//이 달력 마지막날
- Calendar에 정의된 필드
필드명 | 설명 |
YEAR | 년 |
MONTH | 월(0부터 시작) |
WEEK_OF_YEAR | 그해의 몇번째 주 |
WEEK_OF_MONTH | 그달의 몇번째 주 |
DATE | 일 |
DAY_OF_MONTH | 그달의 몇번째일 |
DAY_OF_YEAR | 그해의 몇번째 일 |
DAY_OF_WEEK | 요일 (1~7/ 1=일요일) |
DAY_OF_WEEK_IN_MONTH | 그 달의 몇번쨰 요일 |
HOUR | 시간(0~11) |
HOUR_OF_DAY | 시간(0~23) |
MINUTE | 분 |
SECOND | 초 |
MILLISECOND | 천분의 일초 |
ZONE_OFFSET | GMT기준 시차(천분의 일초 단위) |
AM_PM | 오전/오후 |
-현재말고 다른시간을 가져오고 싶으면 get()대신 set()을 사용하면 됨.
set()으로 날짜와 시간 정하기 (필드 변경)
void set(int field, int value)
void set(int year, int month, int data)
void set(int year, int month, int date, in hourOfDay, int minute)
void set(int year, int month, int date, int hourOfDay, int minute, int second)
- 날짜를 지정하는 방법, 월이 0부터 시작한다는 점에 주의해야함 (배열을 이용하기 때문)
Calendar date1=Calendar.getInstance();
data1.set(2017,7,15);//2017년 8월 15일
//data1.set(Calendar.YEAR,2017); 와 같이 설정 가능
-시간 지정하는 방법
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)
import java.util.*;
class Ex10_2 {
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부터 시작하기 때문에 4월인 경우, 3로 지정해야한다.
// date1.set(2019, Calendar.APRIL, 29);와 같이 할 수도 있다.
date1.set(2019, 3, 29); // 2019년 4월 29일로 날짜를 설정한다.
System.out.println("date1은 "+ toString(date1)
+ DAY_OF_WEEK[date1.get(Calendar.DAY_OF_WEEK)]+"요일이고,"); //요일이면 Calendar.DAY_OF_WEEK가 2이므로 월요일이 출력됨
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) + "일 ";
}
}
import java.util.*;
class Ex10_3 {
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 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()는 Calendar객체의 모든 필드를 초기화
-> 처음 생성되면 현재시간으로 세팅됨
- clear하면 1970년 1월1일 00:00:00 으로 세팅됨(에포크타임)
-clear(int field)는 Calendar객체의 특정 필드를 초기화함
현재시간이아니라 특정날짜 년월일의 차이, 시분초 계산할때는 전체필드를 clear하고 setting해줘야함
- add() 는 특정 필드의 값을 증가 또는 감소(다른필드에 영향O)
Calendar data = Calendar.getInstance();
data.clear(); //모든 필드 초기화
data.set(2020,7,31); // 2020년 8월 31일로 설정
data.add(Calendar.DATE,1); //날짜에 1을 더함 --> 9월 1일
data.add(Calendar.MONTH,-8) //월에서 8을 뺌 -->(9월1일에서 7을뺌)1월1일
- roll은 특정필드의 값을 증가 또는 감소 (다른 필드에 영향 X)
Calendar data = Calendar.getInstance();
data.clear();
data.set(2020,7,31); //2020년 8월 31일
data.roll(Calendar.DATE,1); //날짜에 1을 더함 --> 8월 1일
data.roll(Calendar.MONTH,-8) //월에서 8을 뺌 -->(8월1일에서 8을뺌)20년 12월 31일
import java.util.*;
class Ex10_4 {
public static void main(String[] args) {
Calendar date = Calendar.getInstance();
date.set(2019, 7, 31); // 2019년 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) + "일";
}
}
2019년 8월 31일
= 1일 후 =
2019년 9월 1일
= 6달 전 =
2019년 3월 1일
= 31일 후(roll) =
2019년 3월 1일 //월필드에 영향 X
= 31일 후(add) =
2019년 4월 1일
import java.util.*;
class Ex10_5 {
public static void main(String[] args) {
if(args.length !=2) {
System.out.println("Usage : java Ex10_5 2019 9");
return;
}
int year = Integer.parseInt(args[0]); //문자열 숫자로
int month = Integer.parseInt(args[1]);
int START_DAY_OF_WEEK = 0; //1일의 요일
int END_DAY = 0;
Calendar sDay = Calendar.getInstance(); // 시작일
Calendar eDay = Calendar.getInstance(); // 끝일
// 월의 경우 0부터 11까지의 값을 가지므로 1을 빼주어야 한다.
// 예를 들어, 2019년 11월 1일은 sDay.set(2019, 10, 1);과 같이 해줘야 한다.
sDay.set(year, month-1, 1); //달을 0부터 시작
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(" " + yesy +"년 " + month +"월");
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(); //토요일 될때마다 줄바꿈
}
}
}
달력 만들기 = 말일구하기 + 1일의 요일 구하기
Date와 Calendar간의 변화
- Data의 메서드는 대부분 deprecated되었지만 여전히 사용
1. Calendar를 Date로 변환
Calendar cal = Calendar.getInstance();
Date d = new Date(cal.getTimeInMillis()); //Date(long date)
2. Date를 Calendar로 변환
Date d = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(d)
형식화 클래스
- java.text 패키지의 DecimalFormat, SimpleDateFormat
- 숫자와 날짜를 원하는 형식으로 쉽게 출력 가능(숫자,날짜 -> 형식 문자열)
- 형식 문자열에서 숫자와 날짜를 뽑아내는기능(형식 문자열->숫자, 날짜)
DecimalFormat
- 숫자를 형식화할 때 사용(숫자 -> 형식 문자열)
- ""를 더하는 것보다 다양한 형식으로 변환 가능
double number = 1234567.89 //10진수
DecimalFormat df = new DecimalFormat("#.#E0"); //지수 형식표현
String result = df.format(number); //result="1.2E6"
(형식 패턴 = 0 : 10진수(값이 없을때 0) / #: 10진수 / E : 지수기호)
- 특정형식의 문자열을 숫자로 변환할때도 사용(형식문자열 -> 숫자)
DecimalFormat df = new DecimalFormat("#,###.##"); //문자열이 어떤 형식인지 알려줌
Number num = df.parse("1,234,567.89"); //문자열이 Number타입의 객체로 바뀜 (number은 모든 숫자 래퍼클래스의 최고조상)
double d = new.doubleValue(); //1234567.89
* Integer.parseInt(): 콤파가 포함된 문자열을 숫자로 변환 못함
import java.text.*;
class Ex10_7 {
public static void main(String[] args) {
DecimalFormat df = new DecimalFormat("#,###.##");
DecimalFormat df2 = new DecimalFormat("#.###E0");
try {
Number num = df.parse("1,234,567.89"); //문자열을 double타입으로 변경
System.out.print("1,234,567.89" + " -> ");
double d = num.doubleValue();
System.out.print(d + " -> ");
System.out.println(df2.format(num)); //지수형식의 문자열로 변경
} catch(Exception e) {}
} // main
}
-> 형식문자열에서 숫자로 바꿀때는 parse란 매서드를 사용 / 숫자를 형식문자열로 바꿀때는 format이라는 매서드 사용
SimpleDataFormat()
- 날짜와 시간을 다양한 형식으로 출력할 수 있게 해줌
- 특정 형식으로 되어 있느 문자열에서 날짜와 시간을 뽑아낼 수도 있음
- 문자열을 Date로 바꿀때는 parse라는 메서드 사용 / Date를 문자열로 바꿀떄는 format메서드 사용
import java.util.*;
import java.text.*;
class Ex10_9 {
public static void main(String[] args) {
DateFormat df = new SimpleDateFormat("yyyy년 MM월 dd일");
DateFormat df2 = new SimpleDateFormat("yyyy/MM/dd");
try {
Date d = df.parse("2019년 11월 23일"); //문자열을 Date로 바꿈(parse이용)
System.out.println(df2.format(d)); //날짜(Date)를 문자열로 바꿈(format)
} catch(Exception e) {}
} // main
}
java.time 패키지
: 날짜와 시간을 별도의 클래스로 구분
- LocalDate : 날짜
- LocalTime : 시간
- LocalDateTime : 날짜 & 시간
- ZonedDateTime : 날짜 & 시간 & 시간대(time-zone) : 시간대 정보를 포함하는 날짜와 시간정보를 나타냄 / 특정 지역 시간대와 관련된 작업을 수행할때 유용 / ex ) "2023년 11월 12일 15시 30분"을 "미국 동부 표준 시간대'와 같이 특정 지역 시간대로 표현가능
- Instant ; 에포크시간(1970년 1월 1일 00:00:00 UTC)부터 경과한 시간을 나타냄 -> 시간대와 관계없이 절대적인 시간을 나타내는데 사용/ 주로 시간 간격 및 타임 스탬프 작업에 사용됨
날짜와 시간을 초단위로 표현한 값을 타임스탬프라고 부름. 이 값은 날짜와 시간을 하나의 정수로 표현할 수 있어서 날짜와 시간의 차이를 계산하거나 순서를 비교하는데 유리 -> 데이터베이스에서 많이 사용됨
- Year, YearMonth, MonthDay 클래스로 날짜를 더 세부적으로 다룰 수 있음
- 날짜와 시간의 간격을 표현하기 위한 클래스가 존재
-- Period : 두 날짜 간의 차이 표현(날짜-날짜)
-- Duration : 시간의 차이를 표현 (시간-시간)
- static now() : 현재의 날짜와 시간을 LocalDate와 LocalTime으로 각각 변환
- static of() : 지정된 날짜와 시간으로 LocalDate와 LocalTime객체를 생성
LocalDate date = LocalDate.now(); // ex) 2023-11-10
LocalTime time = LocalTime.now(); // 21:51:01.382
LocalDateTime dateTime = LocalDateTime.now(); // 2023-11-10T21:51:01.382
ZonedDateTime dateTimeInKr = ZonedDateTime.now(); // 2023-11-10T21:51:01.382+09:00[Asia/Seoul]
/* of() */
LocalDate date = LocalDate.of(2023, 10, 10); // 2023년 11월 10일
LocalTime time = LocalTime.of(21, 51, 01); // 21시 51분 01초
LocalDateTime dateTime = LocalDateTime(date, time);
ZonedDateTime zDateTime = ZonedDateTime.of(dateTime, ZoneId.of("Asia/Seoul"));
LocalDate 클래스 메서드
EX (1999-12-31 23:59:59)
int getYear() | 년도(1999) |
int getMonthValue() | 월(12) |
Month getMonth() | 월(DECEMBER) getMonth().getValue() = 12 |
int getDayOfMonth() | 일(31) |
int getDayOfYear() | 같은 해의 1월 1일부터 N번째 일(365) |
DayOfWeek getDayOfWeek() | 요일(FRIDAY) getDayOfWeek().getValue() = 5 |
int lengthOfMonth() | 같은 달의 총 일수(31) |
int lengthOfYear() | 같은 해의 총 일수(365), 윤년이면(366) |
boolean isLeapYear() | 윤년여부 확인(false) |
LocalTime클래스 메서드
EX (1999-12-31 23:59:59)
int getHour() | 시(23) |
int getMinute() | 분(59) |
int getSecond() | 초(59) |
int getNano() | 나노초(0) |
-필드의 값 변경하기 - with(), plus(), minus()
날짜와 시간에서 특정 필드값을 변경하려면 with로 시작하는 메서드를 사용
LocalDate withYear(int year)
LocalDate withMonth(it month)
LocalDate withDayOfMonth(int dayOfMonth)
LocalDate withDayOfYear(it dayOfYear)
LocalTime withHour(int hour)
LocalTime withMinute(int minute)
LocalTime withSecond(int second)
LocalTime withNano(int nanoOfSecond)
LocalDate with(TemporalField field, long newValue)
date = date.withYear(2023); //년도를 2023년으로 변경
time = time.withHour(12); //시간을 12시로 변경
필드를 변경하는 메서드들은 항상 새로운 객체를 생성해서 반환-> 대입 연산자를 같이 사용해야 함
- 날짜와 시간의 비교 - isAfter(), isBefore(), isEqual()
LocalDate와 LocalTimedpsms compareTo()가 오버라이딩되어 있어서 compareTo()로 비교가능
하지만 더 편리하게 비교할 수 있는 메서드가 추가되어있음
boolean isAfter(ChronoLocalDate other)
boolean isBefor(ChronoLocalDate other)
boolean isEqual(ChronoLocalDate other) //LocalDate만 제공
equals()가 있는데도, isEqual()를 제공하는 이유는 연표(chronolory)가 다른 두 날짜를 비교하기 위함.
equals()는 모든 필드가 일치해야 하지만, isEqual()은 날짜만 비교
'Study > java' 카테고리의 다른 글
chapter 14 (0) | 2023.11.09 |
---|---|
chapter 13 (0) | 2023.09.09 |
chapter 12 (0) | 2023.08.31 |
chapter 9 (0) | 2023.08.12 |
chapter 11 (0) | 2023.08.07 |