본문 바로가기
개발언어/Java : 자바

자바 쉽게 배우기 13 - 날짜와 시간(2)

by 개발자D 2023. 1. 30.

날짜와 시간(2)

날짜와 시간

지난 글의 Date와 Calendar 클래스에 이어 time 패키지에 대해 알아봅시다. 

Java.time패키지

Java.time패키지는 jdk1.8부터 Date, Calendar 클래스를 보완하기 위해 추가되었습니다.  time 패키지의 클래스들은  Calendar클래스와 달리 불변의 특성을 가지고 있어 멀티스레드 환경에서도 안전합니다. 

 

핵심 클래스와 인터페이스

인터페이스 구현클래스 내용
Temproal, TemporalAccesser,
TemporalAdjuster
LocalDate 날짜
  LocalTime  시간
  LocalDateTime  날짜, 시간
  ZonedDateTime  날짜, 시간, 시간대
클래스 내용
TemporalAdjusters 자주쓰는 날짜 계산 메서드들 정의
인터페이스 구현클래스 내용
TemporalAmount Period  두 날짜간의 차이
  Duration  두 시간간의 차이
인터페이스 구현클래스 내용
TemporalUnit ChronoUnit  날짜와 시간의 단위 (열거형)
TemporalField ChronoField  년, 월, 일 등 날짜와 시간의 필드를 정의 (열거형)

 


객체 생성 방법

static 메서드 now()와 of()를 사용하여 객체를 생성합니다.

  • now() : 현재 날짜와 시간을 저장하는 객체를 생성합니다.
  • of() : 해당 필드의 값을 순서대로 지정하는 객체를 생성합니다.
LocalDate today = LocalDate.now(); //오늘의 날짜
LocalTime now = LocalTime.now(); //현재 시간

static LocalDate of(int year, Month month, int dayOfMonth)
static LocalDate of(int year, int month, int dayOfMonth)

static LocalTime of(int hour, int min)
static LocalTime of(int hour, int min, int sec)
static LocalTime of(int hour, int min, int sec, int nanoOfSecond)

 

LocalDate, LocalTime

필드 값 가져오기 - get(), get###()

LocalDate형, LocalTime형 인스턴스 local
자료형마다 사용할 수 있는 Field는 다름 

local.get(ChronoField.ERA) 시대
local.get(ChronoField.YEAR)
local.get(ChronoField.YEAR_OF_ERA) 년
local.get(ChronoField.MONTH_OF_YEAR) (1~12)
local.get(ChronoField.AMPM_OF_DAY) 오전/오후 
local.get(ChronoField.HOUR_OF_DAY) 시간 (0~23)
local.get(ChronoField.CLOCK_HOUR_OF_DAY) 시간 (1~24)
local.get(ChronoField.HOUR_OF_AMPM) 시간 (0~11)
local.get(ChronoField.CLOCK_HOUR_OF_AMPM) 시간 (1~12)
local.get(ChronoField.MINUTE_OF_HOUR) 분
local.get(ChronoField.SECOND_OF_MINUTE) 초
local.get(ChronoField.MILLI_OF_SECOND) 천분의 1초 (0~999)
local.get(ChronoField.MICRO_OF_SECOND) 백만분의 1초 
local.get(ChronoField.NANO_OF_SECOND) 10억분의 1초 
local.get(ChronoField.DAY_OF_YEAR) 이 해의 몇 일
local.get(ChronoField.EPOCH_DAY) EPOCH (1970.1.1)부터 몇번째 날
local.get(ChronoField.MINUTE_OF_DAY) 그 날의 몇 번째 분 (시간을 분으로 환산)
local.get(ChronoField.SECOND_OF_DAY) 그 날의 몇 번째 초 (시간을 초로 환산)
local.get(ChronoField.MILLI_OF_DAY) 그 날의 몇 번째 분 (시간을 분으로 환산)
local.get(ChronoField.MICRO_OF_DAY) 그 날의 몇 번째 분 (시간을 분으로 환산)
local.get(ChronoField.NANO_OF_DAY) 그 날의 몇 번째 분 (시간을 분으로 환산)
local.get(ChronoField.MINUTE_OF_DAY) 그 날의 몇 번째 분 (시간을 분으로 환산)
local.get(ChronoField.ALIGNED_WEEK_OF_MONTH) 그 달의 몇 째 주(1~7일 1주...)
local.get(ChronoField.ALIGNED_WEEK_OF_YEAR) 그 해의 몇 째 주
local.get(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH) 요일 (그달의 1일을 월요일로 간주하여 계산)
local.get(ChronoField.ALIGNED_DAY_OF_WEEK_IN_YEAR) 요일 (그 해의 1월 1일을 월요일로 간주하여 계산)
local.get(ChronoField.INSTANT_SECONDS) 년월일을 초단위로 환산 Instant에만 사용가능
local.get(ChronoField.OFFSET_SECONDS) UTC와의 시차 ZoneOffset에만 사용가능
local.get(CHronoField.PROLEPTIC_MONTH) 년월을 월단위로 환산 (2015년 11월 = 2015*12+11)
//LocalDate
getYear() 년도
getMonthValue() 월 (12)
getMonth() 월 (DECEMBER)
getDayOfMonth() 일
getDayOfYear() 같은 해의 1월 1일부터 몇번째 일 (365)
getDayOfWeek() 요일
lengthOfMonth() 같은 달의 총 일수
lengthOfYear() 같은 해의 총 일수(365) 윤년이면 366
isLeepYear() 윤년여부확인
//LocalTime
getHour() 시(23)
getMinute() 분(59)
getSecond() 초(59)
getNano() 나노초

 


필드 값 변경하기 - with(), plus(), minus(), truncatedTo()

with()

LocalDate withYear(int year)
LocalDate withMonth(int month)
LocalDate withDayOfMonth(int dayOfMonth)
LocalDate withDayOfYear(int dayOfYear)

LocalTime withHour(int hour)
LocalTime withMinute(int minute)
LocalTime withSecond(int second)
LocalTime withNano(int nanoOfSecond)

LocalDate with(TemporalField field, long newValue)
//필드를 변경하는 메서드는 항상 새로운 객체를 생성해서 반환

plus(), minus()

LocalDate plusYears(long yearsToAdd)
LocalDate plusMonths(long monthsToAdd)
LocalDate plusDays(long daysToAdd)
LocalDate plusWeeks(long weeksToAdd)

LocalTime plusHours(long hoursToAdd)
LocalTime plusMinutes(long minutesToAdd)
LocalTime plusSeconds(long secondsToAdd)
LocalTime plusNanos(long nanosToAdd)

// minus도 plus와 같음

LocalTime의 truncatedTo()

//지정된 것보다 작은 단위의 필드를 0으로 만듦
12시 34분 56초 -> truncatedTo(ChronoUnit.HOURS) -> 12:00

 


날짜와 시간의 비교 - compareTo(), isAfter(), isBefore(), isEqual()

compareTo()

int result = date1.compareTo(date2);
//같으면 0, date1이 이전이면 -1, 이후면 1

isAfter(), isBefore()

boolean isAfter (ChronoLocalDate other) // other보다 이후이면 true 반환
boolean isBefore (ChronoLocalDate other) // other보다 이전이면 true 반환

equals(), isEqual()

boolean equals (ChronoLocalDate other) // 필드의 모든 값을 비교
boolean isEqual (ChronoLocalDate other) // 날짜만 비교

 


LocalDateTime과 ZonedDateTime

객체생성

LocalDateTime

LocalDate date = LocalDate.of(2023,1,3);
LocalTime time = LocalTime.of(12,34,56);

LocalDateTime dt = LocalDateTime.of(date,time);
LocalDateTime dt2 = date.atTime(time);
LocalDateTIme dt3 = time.atDate(date);
LocalDateTime dt4 = date.atTime(12,34,56);
LocalDateTime dt5 = time.atDate(LocalDate.of(2023,1,3));
LocalDateTime dt6 = date.atStartOfDay(); // time을 0, 0, 0 으로 설정
LocalDateTime dt7 = LocalDateTime.of(2023, 1, 3, 12, 34, 56);
LocalDateTime dt8 = LocalDateTime.now();
  • of()와 now()를 사용하거나 LocalDate와 LocalTime을 합치는 등 다양한 방법으로 객체를 생성할 수 있습니다.

 ZonedDateTime

ZoneId zid = ZoneId.of("Asia/Seoul");
ZoneDateTime zdt = dateTime.atZone(zid);

ZonedDateTime sdt = LocalDate.now().atStartOfDay(zid);

ZonedDateTime time = ZonedDateTime.now().withZoneSameInstant(zid);
  • ZoneId클래스를 사용하는 방법 : 일광 절약 시간을 (DST, Daylight Saving Time) 자동으로 처리해 주는 장점이 있습니다.
  • LocalDate의 atStartOfDay() 메서드를 사용하는 방법 : 0시 0분 0초로 설정합니다.
  • ZoneDateTime의 withZoneSameInstant() 메서드를 사용하는 방법 : 특정 지역의 시간으로 설정합니다.

 

LocalDateTime의 변환

// LocalDateTime 형 인스턴스 dt
LocalDate date = dt.toLocalDate(); // LocalDateTime -> LocalDate
LocalTime time = dt.toLocalTime(); // LocalDateTime -> LocalTime

 


TemporalAdjusters 

자주 쓰일만한 날짜 계산 메서드들이 정의되어 있습니다.

firstDayOfNextYear() //다음 해의 첫 날
firstDayOfNextMonth() //다음 달의 첫 날
firstDayOfYear() //올 해의 첫 날
firstDayOfMonth() //이번 달의 첫 날
lastDayOfYear() //올 해의 마지막 날
lastDayOfMonth() //이번 달의 마지막 날
firstInMonth(DayOfWeek dayOfWeek) //이번 달의 첫번째 ? 요일
lastInMonth(DayOfWeek dayOfWeek) //이번 달의 마지막 ? 요일
previous(DayOfWeek dayOfWeek) //지난 ?요일(당일 미포함)
previousOrSame(DayOfWeek dayOfWeek) //지난 ?요일(당일 포함)
next(DayOfWeek dayOfWeek) //다음 ?요일(당일 미포함)
nextOrSamte(DayOfWeek dayOfWeek) //다음 ?요일(당일 포함)
dayOfWeekInMonth(int ordinal, DayOfWeek dayOfWeek) //이번 달의 n번째 ?요일

 


Period, Duration

Period : 날짜 차이 계산

Duration : 시간 차이 계산

Period pe = Period.between(date1, date2); // static메서드, 사이의 기간
Period pe = today.until(myBirthDay); // instance메서드, ~까지의 기간

long dday = totay.until(myBirthDay, ChronoUnit.Days)  // 년,월,일이 아니라 일로만 구하고 싶을 때
long sec = LocalTime.now().until(endTime, ChronoUnit.SECONDS);

Duration du = Duration.between(time1, time2); // Duration을 반환하는 until()은 없음

//특정 필드의 값을 얻을 때 geT(), get###() 메서드를 사용
long year = pe.get(ChronoUnit.YEARS) // int getYears()
long month = pe.get(ChronoUnit.MONTHS) // int getMonths()
long day = pe.get(ChronoUnit.DAYS) // int getDays()

long sec = du.get(ChronoUnit.SECONDS) // long getSeconds()
int nano = du.get(ChronoUnit.NANOS) // int getNanos()

// Duration에는 getHours(), getMinutes()메서드가 없습니다.
// 따라서 초를 변형해서 사용하거나
// Duration을 LocalTime으로 변환한 다음에 get메서드를 사용해줍니다.
LocalTime tmpTime = LocalTime.of(0,0).plusSeconds(du.getSeconds());

of(), with()

// of() : 해당 필드의 값을 순서대로 지정
Period
of(), ofYears(), ofMonths(), ofWeeks(), ofDays()

Duration
of(), ofDays(), ofHours(), ofMinutes(), ofSeconds()

// with() : 특정 필드값 변경
pe.withYears(3);
du.withSeconds(500);

다른 단위로 변환

Period
toTotalMonths() // 년월일을 월단위로 변환 (일단위 무시)

Duration
toDays() // 일단위로
toHours() //시간단위로
toMinutes() //분단위로
toMillis() //천분의 일초 단위로
toNanos() //나노초 단위로 

길고 긴 날짜 시간 백과사전이 끝났습니다. 아직 배열을 기억하고 계시겠죠? 다음 글에서는 배열과 비슷하지만 더 자주 쓰이는 컬렉션 프레임워크에 대해 알아보겠습니다. 감사합니다.

 

자바 쉽게 배우기 14 - 컬렉션 프레임워크(1) : List

컬렉션 프레임워크 컬렉션 프레임워크는 배열처럼 다수의 데이터를 한 묶음으로 보관, 처리할 수 있는 구조를 의미합니다. 배열보다 많은 기능을 가지고 있어 자주 사용됩니다. jdk1.2에 등장했

devdharu.tistory.com