개발/Java
java.util.Date
함수형 인간
2025. 3. 14. 07:03
java.util.Date는 Java 초기부터 제공된 날짜와 시간을 표현하는 클래스.
하지만 여러 문제점과 부족한 기능으로 인해 Java 8부터는 java.time 패키지의 클래스들(LocalDate, LocalDateTime, ZonedDateTime 등)을 사용하는 것이 권장됨.
java.util.Date의 특징:
- 날짜와 시간 표현: java.util.Date는 특정 시점의 날짜와 시간을 나타낸다. 내부적으로는 1970년 1월 1일 00:00:00 GMT(그리니치 표준시)부터 경과한 밀리초(milliseconds)를 long 값으로 저장한다.
- 가변성 (Mutable): java.util.Date 객체는 가변(mutable). 즉, setDate(), setMonth(), setYear() 등의 메서드를 사용하여 객체의 값을 변경할 수 있다. 이 때문에 멀티스레드 환경에서 예상치 못한 문제가 발생할 수 있다.
- 타임존: java.util.Date 자체는 타임존 정보를 가지고 있지 않는다. 하지만 toString() 메서드를 호출하면 시스템의 기본 타임존을 사용하여 날짜와 시간을 문자열로 변환. 이 때문에 타임존 관련 혼란이 발생할 수 있다.
- 월(Month)의 시작: java.util.Date에서 월(Month)은 0부터 시작합니다 (0: 1월, 1: 2월, ..., 11: 12월). 이는 직관적이지 않아서 실수를 유발할 수 있다.
- 메서드의 Deprecation: 많은 메서드들이 Deprecated (사용 중단됨) 상태. getYear(), getMonth(), getDate(), getHours(), getMinutes(), getSeconds() 등 대부분의 getter/setter 메서드들이 Deprecated 되었고, 대신 Calendar 클래스를 사용하도록 권장.
- Calendar 와의 관계: java.util.Date는 java.util.Calendar 객체로 변환하거나 Calendar 객체로부터 Date객체를 생성하는 것이 가능.
java.util.Date의 주요 메서드 (Deprecated 되지 않은 것들):
- Date(): 현재 날짜와 시간으로 초기화된 Date 객체를 생성.
- Date(long date): 1970년 1월 1일 00:00:00 GMT로부터 주어진 밀리초만큼 경과한 시점으로 초기화된 Date 객체를 생성.
- getTime(): 1970년 1월 1일 00:00:00 GMT로부터 이 Date 객체가 나타내는 시점까지의 밀리초를 반환.
- setTime(long time): 이 Date 객체를 1970년 1월 1일 00:00:00 GMT로부터 주어진 밀리초만큼 경과한 시점으로 설정.
- before(Date when): 이 Date 객체가 주어진 Date 객체보다 이전 시점인지 확인.
- after(Date when): 이 Date 객체가 주어진 Date 객체보다 이후 시점인지 확인.
- equals(Object obj): 이 Date 객체와 주어진 객체가 같은 시점을 나타내는지 비교.
- compareTo(Date anotherDate): 이 Date 객체를 주어진 Date 객체와 비교하여 순서를 정함. (이전이면 음수, 같으면 0, 이후면 양수)
- toString(): 이 Date 객체를 문자열로 변환. 시스템의 기본 타임존을 사용. (예: "Tue Oct 29 15:30:00 KST 2024")
- clone(): 이 Date 객체의 복사본을 반환.
- from(Instant instant) (Java 8 이상): java.time.Instant 객체로부터 java.util.Date 객체를 생성.
- toInstant() (Java 8 이상): 이 Date 객체를 java.time.Instant 객체로 변환.
java.util.Date 사용 예시:
Java
import java.util.Date;
import java.text.SimpleDateFormat;
public class DateExample {
public static void main(String[] args) {
// 현재 날짜와 시간으로 Date 객체 생성
Date now = new Date();
System.out.println("Current Date: " + now); // 시스템 기본 타임존으로 출력
// 1970년 1월 1일 00:00:00 GMT로부터 1000 밀리초 경과한 시점
Date past = new Date(1000);
System.out.println("Past Date: " + past);
// 특정 날짜/시간으로 Date 객체 생성 (SimpleDateFormat 사용)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
try {
Date specificDate = sdf.parse("2023-12-25 10:30:00");
System.out.println("Specific Date: " + specificDate);
} catch (java.text.ParseException e) {
System.out.println("Date parsing error: " + e.getMessage());
}
// 날짜 비교
Date date1 = new Date();
Date date2 = new Date(date1.getTime() + 1000 * 60 * 60); // 1시간 후
System.out.println("date1.before(date2): " + date1.before(date2)); // true
System.out.println("date1.after(date2): " + date1.after(date2)); // false
System.out.println("date1.equals(date2): " + date1.equals(date2)); // false
// java.time.Instant로 변환 (Java 8 이상)
java.time.Instant instant = now.toInstant();
System.out.println("Instant: " + instant);
// java.time.Instant에서 Date로 변환 (Java 8 이상)
Date fromInstant = Date.from(instant);
System.out.println("From Instant: " + fromInstant);
}
}
SimpleDateFormat을 사용한 날짜/시간 포매팅:
java.util.Date 객체를 원하는 형식의 문자열로 표현하거나, 문자열을 java.util.Date 객체로 파싱하려면 java.text.SimpleDateFormat 클래스를 사용.
Java
import java.util.Date;
import java.text.SimpleDateFormat;
public class DateFormatExample {
public static void main(String[] args) {
Date now = new Date();
// 다양한 형식으로 Date를 문자열로 변환
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat sdf2 = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
SimpleDateFormat sdf3 = new SimpleDateFormat("E, MMM dd, yyyy"); // 요일, 월, 일, 년
System.out.println("Format 1: " + sdf1.format(now));
System.out.println("Format 2: " + sdf2.format(now));
System.out.println("Format 3: " + sdf3.format(now));
// 문자열을 Date로 파싱
String dateString = "2023-11-15";
SimpleDateFormat sdf4 = new SimpleDateFormat("yyyy-MM-dd");
try {
Date parsedDate = sdf4.parse(dateString);
System.out.println("Parsed Date: " + parsedDate);
} catch (java.text.ParseException e) {
System.out.println("Parsing error: " + e.getMessage());
}
}
}
SimpleDateFormat의 주요 패턴 문자:
- yyyy: 년 (4자리)
- yy: 년 (2자리)
- MM: 월 (2자리, 01-12)
- M: 월 (1자리 또는 2자리, 1-12)
- dd: 일 (2자리, 01-31)
- d: 일 (1자리 또는 2자리, 1-31)
- HH: 시 (24시간 형식, 00-23)
- H: 시 (24시간 형식, 0-23)
- hh: 시 (12시간 형식, 01-12)
- h: 시 (12시간 형식, 1-12)
- mm: 분 (00-59)
- ss: 초 (00-59)
- SSS: 밀리초 (000-999)
- E: 요일 (짧은 형식, 예: "월")
- EEEE: 요일 (긴 형식, 예: "월요일")
- a: 오전/오후 (AM/PM)
- z: Time zone name
- Z: Time zone offset
주의사항 및 권장 사항:
- 가변성: java.util.Date는 가변 객체이므로, 멀티스레드 환경에서 사용할 때는 주의해야 한다. 여러 스레드에서 동시에 Date 객체를 변경하면 예기치 않은 결과가 발생할 수 있다. 가능하면 불변(immutable) 객체인 java.time 패키지의 클래스들을 사용하는 것이 좋다.
- 타임존: java.util.Date 자체는 타임존 정보를 갖지 않지만, toString() 메서드나 SimpleDateFormat을 사용할 때 시스템의 기본 타임존이 사용된다. 타임존을 명확하게 처리해야 하는 경우에는 java.util.Calendar나 java.time.ZonedDateTime을 사용하는 것이 좋다.
- SimpleDateFormat은 스레드 안전하지 않음: SimpleDateFormat 객체는 thread-safe하지 않다. 멀티스레드 환경에서 SimpleDateFormat 객체를 공유하면 문제가 발생할 수 있다. 각 스레드마다 별도의 SimpleDateFormat 객체를 생성하거나, ThreadLocal을 사용하거나, Java 8 이상의 java.time.format.DateTimeFormatter를 사용하는 것이 좋다.
- Java 8 이상에서는 java.time 패키지 사용: 가능하면 java.util.Date 대신 java.time 패키지의 클래스들(LocalDate, LocalDateTime, ZonedDateTime, Instant 등)을 사용하는 것이 좋다. java.time 패키지는 불변 객체, 명확한 타임존 처리, 풍부한 기능 등 여러 장점을 제공.