Java 날짜 연산
Java 8에 추가된 날짜/시간 관련 클래스 중 LocalDate
를 사용한 간단한 날짜 연산 방법을 정리한다. LocalDate
에는 시간 정보가 포함되어 있지 않다. 날짜와 시간을 함께 다루려면 LocalDateTime
을 사용해야 한다. UTC 오프셋이나 시간대도 함께 필요한 경우는 OffsetDateTime
또는 ZonedDateTime
을 사용해야 한다.
간단한 날짜 관련 연산
// 오늘, 어제, 내일
var today = LocalDate.now();
var yesterday = today.minus(1, ChronoUnit.DAYS);
var tomorrow = today.plus(1, ChronoUnit.DAYS);
// day of week
var dayOfWeek = today.getDayOfWeek();
// day of year
var dayOfYear = today.getDayOfYear();
// week of year
var weekOfYear = today.get(ChronoField.ALIGNED_WEEK_OF_YEAR)
// 한 주 전/후
var oneWeekBefore = today.minusWeeks(1);
var oneWeekAfter = today.plusWeeks(1);
// 한 달 전/후
var oneMonthBefore = today.minusMonths(1);
var oneMonthAfter = today.plusMonths(1);
// 두 날짜 사이의 날 수
var d1 = LocalDate.of(2020, 3, 1);
var d2 = LocalDate.of(2020, 6, 1);
vat numDays = ChronoUnit.DAYS.between(d1, d2);
한 주의 첫날, 마지막 날 구하기
// 이번 주 첫 날과 마지막 날 (월요일을 한 주의 시작인 경우)
var startOfWeek = today.with(DayOfWeek.MONDAY);
var endOfWeek = today.with(DayOfWeek.SUNDAY);
우리나라나 미국 같은 일부 나라는 일요일을 한 주의 시작으로 생각한다.
// 이번 주 첫 날과 마지막 날 (일요일을 한 주의 시작인 경우)
var startOfWeek = today.with(WeekFields.of(Locale.KOREA).dayOfWeek(), 1);
var endOfWeek = today.with(WeekFields.of(Locale.KOREA).dayOfWeek(), 7);
지난주, 다음주의 첫날과 마지막 날은 today에 plusWeeks
나 minusWeeks
로 한주 전/후 날짜를 구한 다음 위 방법을 사용하면 된다.
한 달의 첫날, 마지막 날 구하기
달의 첫 날은 1일이니 구하기 쉽지만, 달의 마지막 날은 28, 29, 30, 31이 될 수 있으므로 다음과 같이 구한다.
var start = today.withDayOfMonth(1);
var end = today.with(TemporalAdjusters.lastDayOfMonth());
YearMonth
클래스를 사용하면 좀더 코드가 단순해진다.
var start = YearMonth.now().atDay(1);
var end = YearMonth.now().atEndOfMonth();
날짜 스트림
LocalDate
에 있는 datesUntil
메서드를 사용하면 두 날짜 사이의 날짜 스트림을 구할 수 있다. datesUntil
은 현재 인스턴스의 날부터 인자로 주어진 날 까지(인자 날짜는 제외) 스트림을 리턴한다.
따라서 한 주의 모든 날짜를 구하려면 그 주의 첫 날과 그 다음 주의 첫 날을 구해 datesUntil
을 호출하면 된다.
var start = today.with(DayOfWeek.MONDAY);
var dates = start.datesUntil(start.plusWeeks(1)).collect(Collectors.toList());
같은 원리로, 한 달의 모든 날짜를 구하는 것은 다음과 같이 할 수 있다.
var start = YearMonth.now().atDay(1);
var dates = start.datesUntil(start.plusMonths(1)).collect(Collectors.toList());
스트림을 리스트로 모은 것은 예시일 뿐이다. 스트림을 필요에 맞게 사용하면 된다. 예를 들어, 2020년의 모든 일요일을 구하려면 다음과 같이 할 수 있다.
var sundays = Year.of(2020).atDay(1).datesUntil(Year.of(2021).atDay(1))
.filter(d -> d.getDayOfWeek() == DayOfWeek.SUNDAY)
.collect(Collectors.toList());