2025년 12월 31일이 2026년으로 출력되는 이유 (yyyy vs YYYY)

2025년 12월 31일이 2026년으로 출력되는 이유 (yyyy vs YYYY)

자바에서 날짜를 포맷팅할 때 yyyyYYYY 에 다른점에 대해 알고 계신가요?

연말에 날짜가 미래로 찍히는 황당한 버그를 마주하게 됩니다.

단,그깟 문자열 차이였어요, 대문자 소문자 차이

이번 포스팅에서는 테스트 코드를 통해 왜 이런 현상이 발생하는지, 그리고 올바른 사용법은 무엇인지 알아보겠습니다.

문제의 현상: 2025년이 2026년으로?

2025년 12월 28일은 일요일입니다. 이 날짜를 YYYYMMdd 패턴으로 포맷팅하면 어떤 결과가 나올까요? 놀랍게도 결과는 20261228이 됩니다.

실제 테스트 코드로 확인해 보겠습니다.

@Test
@DisplayName("SimpleDateFormat에서 대문자 YYYY를 사용하면 2025년 12월 28일은 2026년으로 출력된다")
void simpleDateFormatTest() {
    // Given: 2025년 12월 28일 설정 (일요일)
    Calendar cal = Calendar.getInstance();
    cal.set(2025, Calendar.DECEMBER, 28);
    Date time = cal.getTime();

    // When: 대문자 YYYY 패턴 사용
    SimpleDateFormat sdf = new SimpleDateFormat("YYYYMMdd", Locale.KOREA);
    String formatted = sdf.format(time);

    // Then: 2025년임에도 불구하고 Week Year 기준에 따라 2026으로 출력됨을 검증
    assertThat(formatted).isEqualTo("20261228");
}

처음에는 자바에 레거시 라이브러리에 문제가 인줄 알았습니다.

그래서 Java 8 이후에 등장한 DateTimeFormatter로 테스트 해봤습니다. 결과는 동일합니다.

@Test
@DisplayName("DateTimeFormatter에서도 대문자 YYYY를 사용하면 동일하게 2026년으로 출력된다")
void dateTimeFormatterTest() {
    // Given: 2025년 12월 28일 LocalDate 생성
    LocalDate date = LocalDate.of(2025, 12, 28);

    // When: 대문자 YYYY 패턴 사용
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("YYYYMMdd");
    String formatted = date.format(formatter);

    // Then: 결과는 역시 20261228
    assertThat(formatted).isEqualTo("20261228");
}

왜 이런 결과가 나오나요?

이유는 yyyyYYYY가 가리키는 의미가 다르기 때문입니다.

  • yyyy (Year): 우리가 흔히 생각하는 그해의 연도(Calendar year)를 의미합니다.
  • YYYY (Week based year): 해당 주가 속한 연도(Week-based-year)를 의미합니다.

ISO-8601 기준에 따르면 한 주의 시작은 월요일이고,

그 해의 첫 번째 주는 ‘그 해의 4일 이상이 포함된 첫 번째 주’입니다.

핵심은 특정 주가 다음 해로 넘어가는 시점에 걸쳐 있으면 YYYY는 다음 해를 반환할 수 있다는 점입니다.

2025년 12월 28일 일요일이 포함된 주간이 2026년의 첫 번째 주(Week 1)로 간주되기 때문에 YYYY를 사용하면 2026년으로 표시되는 것입니다.

해결 방법: 항상 소문자 yyyy 사용하기

대부분의 비즈니스 로직에서는 달력상의 연도가 필요합니다. 따라서 날짜 포맷팅 시에는 반드시 소문자 yyyy를 사용해야 합니다.

@Test
@DisplayName("올바른 연도 표기를 위해서는 반드시 소문자 yyyy를 사용해야 한다")
void correctYearFormatTest() {
    LocalDate date = LocalDate.of(2025, 12, 28);

    // 소문자 yyyy 사용
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
    String formatted = date.format(formatter);

    // 정상적으로 2025 출력
    assertThat(formatted).isEqualTo("20251228");
}

요약

  • yyyy연도(Year), YYYY는 **주 기준 연도(Week Year)**입니다.
  • 연말/연초 날짜 계산 오류를 방지하려면 무조건 yyyy를 사용하세요.
  • 대문자 YYYY는 특별히 주 단위 통계 등을 계산할 때만 제한적으로 사용합니다.