공공부하자개발 · 영어 학습 노트
자바
중급객체지향과 코어 라이브러리0/9 완료
  • 01상속, 다형성, 오버라이딩
  • 02추상 클래스 vs 인터페이스
  • 03예외 처리
  • 04java.lang 심화
  • 05컬렉션 프레임워크 딥다이브
  • 06메서드 활용 패턴 (중급)
  • 07Object 메서드와 비교
  • 08java.time 실무 날짜 계산
  • 09HTTP 와 JSON 기초
사이트 소개개인정보처리방침연락처
© 2026 공부하자
홈 › 중급 › 08 / 9

java.time 실무 날짜 계산

정산일, 영업일, 월말, 시간대, DB 매핑
섹션 7진행 0 / 9
1왜 배우는가2핵심 원리3코드 예제4응용 변형 예제5자주 하는 실수 (Tip)6연습 문제7정리‹ 이전다음 ›

4. 응용 변형 예제

변형 1: 테스트 가능한 "지금" — Clock 주입

java
public class SettlementService {
    private final Clock clock;
    public SettlementService(Clock clock) { this.clock = clock; }             // 운영: Clock.systemDefaultZone() 또는 Clock.system(SEOUL)
    public YearMonth targetMonth() { return YearMonth.now(clock).minusMonths(1); }   // 전월 정산
}
// 테스트
Clock fixed = Clock.fixed(Instant.parse("2026-01-01T00:00:00Z"), ZoneId.of("Asia/Seoul"));
assert new SettlementService(fixed).targetMonth().equals(YearMonth.of(2025, 12));   // 연초 경계 검증

now() 를 코드에 직접 쓰면 "1월 1일에 전월이 12월인가" 를 테스트할 수 없습니다. Clock 을 받으면 어떤 날짜든 고정해 검증할 수 있고, Spring 에서는 Clock 을 빈으로 등록해 주입합니다.

변형 2: 기간 겹침 검사 (예약·계약 중복)

java
static boolean overlaps(LocalDate aFrom, LocalDate aTo, LocalDate bFrom, LocalDate bTo) {
    return !aFrom.isAfter(bTo) && !bFrom.isAfter(aTo);   // 양끝 포함. 한쪽이 다른 쪽 끝난 뒤 시작하면 안 겹침
}

"A 시작 ≤ B 끝 이고 B 시작 ≤ A 끝" 이면 겹칩니다. 회의실 예약, 휴가 중복, 계약 기간 충돌 검사가 전부 이 한 줄입니다. 끝 날짜를 포함하지 않는 규칙(체크아웃)이면 isAfter 를 !isBefore 로 바꿉니다.

변형 3: 월별 구간으로 쪼개기 (장기 계약의 월 청구)

java
static List<BusinessDays.Period> splitByMonth(LocalDate from, LocalDate to) {
    List<BusinessDays.Period> out = new ArrayList<>();
    for (YearMonth ym = YearMonth.from(from); !ym.isAfter(YearMonth.from(to)); ym = ym.plusMonths(1)) {
        LocalDate s = ym.equals(YearMonth.from(from)) ? from : ym.atDay(1);
        LocalDate e = ym.equals(YearMonth.from(to)) ? to : ym.atEndOfMonth();
        out.add(new BusinessDays.Period(s, e));
    }
    return out;
}
// 2026-01-15 ~ 2026-03-10 → [01-15~01-31], [02-01~02-28], [03-01~03-10]

일할 계산(첫 달과 마지막 달만 부분) 청구의 기본 단위입니다.

변형 4: 외부 API 의 시각 문자열 주고받기

java
// 보낼 때: 항상 ISO 8601 + 오프셋. 상대가 어느 시간대든 해석이 하나
String body = "{\"occurredAt\":\"" + OffsetDateTime.now(ZoneOffset.UTC).truncatedTo(ChronoUnit.SECONDS) + "\"}";   // 2026-09-09T05:30:28Z
// 받을 때: 오프셋 포함 문자열은 OffsetDateTime.parse, 없으면 상대와 시간대를 문서로 합의한 뒤 atZone
Instant when = OffsetDateTime.parse("2026-09-09T14:30:28+09:00").toInstant();

"2026-09-09 14:30:28" 처럼 시간대 없는 문자열을 주고받으면 양쪽 서버 시간대가 다를 때 9시간이 어긋납니다. Jackson 은 Instant/OffsetDateTime 을 ISO 로 직렬화하므로 DTO 에 이 타입을 쓰면 됩니다.

응용 변형 예제
  • 변형 1: 테스트 가능한 "지금" — Clock 주입
  • 변형 2: 기간 겹침 검사 (예약·계약 중복)
  • 변형 3: 월별 구간으로 쪼개기 (장기 계약의 월 청구)
  • 변형 4: 외부 API 의 시각 문자열 주고받기
이전 섹션3 코드 예제4 / 7다음 섹션5 자주 하는 실수 (Tip)