Java LocalDate Month getValue 문제 상세 해부

다들 Java 세 번째 날짜 API가 드디어 완벽할 줄 알았지. 아니었어—LocalDate의 Month.getValue()가 개발자들에게 새 인덱싱 지옥을 선사했다.

Java LocalDate Month enum 출력에서 getValue와 ordinal 간 인덱싱 불일치 표시

Key Takeaways

  • LocalDate Month.getValue()가 1 기반이라 0 기반 배열 인덱싱 전통 깨뜨림.
  • 레거시 호환은 ordinal() 고수, 아니면 getValue()에서 1 빼.
  • Java 날짜 API 진화하지만, 실용 표준이 '직관적' 변화 이김.

Java 날짜 처리라니, 이게 무슨 사가냐고. 옛날 Date 클래스가 그냥 쓸 수 있을 줄 알았지—타임스탬프만 찍고 끝. 그런데 Y2K 공포에 이상한 메서드들 때문에 터지니까 Oracle 선배들이 Calendar를 구원자로 던져줬다. 나름 솔직했지만 투박했지. 이제 java.time.LocalDate가 세 번째 만의 도전으로 등장, 완벽 해결책으로 떠받들어졌어. 그런데 완벽하지 않아. 완전하진 않다고.

이게 모든 걸 바꿀까? 그럴 리 없지. 그냥 머리 아픈 걸 다른 머리 아픈 걸로 바꿔놓고, 월 이름 뽑을 때마다 -1 빼라고 강요할 뿐이야. 이게 이득 보는 쪽은 누구? 새벽 2시에 배열 인덱스 에러 보며 멍때리는 너는 절대 아니야.

내가 Java 취재한 지 applet 전쟁 때부터—Sun, Oracle, 이제 Eclipse까지 스튜어드십 다툼 지켜본 지 20년째. 날짜 처리는 항상 Java의 아킬레스건이었어. 타임존은 정치인처럼 변덕 부리고, 윤초는 몰래 끼어들고, 매 API마다 혼돈 정복한다고 난리. LocalDate? 현대적이고 불변성 있고 ISO 친화적. 종이엔 좋네. 그런데 Month.getMonth() 들여다보니 냉소가 솟아.

Java LocalDate 월이 왜 1부터 세는 거지?

문제는 여기서 터져. LocalDate.now() 잡아봐—원래 글처럼 2026-04-07이라고 치자. getMonth().getValue() 호출하면 쾅: 4월에 4. 논리적이지? ISO 8601 맞춰 1월이 1이니까. 비개발자들 박수 치겠지. 그런데 프로그래머들은? K&R C 때부터 제로 기반으로 뇌에 새겨졌어.

월 이름 배열—0에 1월, 1에 2월—이 갑자기 안 맞아. getValue()로 인덱싱? 4월에 5월 떨어짐. 전형적인 off-by-one, 우리 업계의 전염병.

날짜: 2026-04-07 월 (val): 5월 월 (ord): 4월

원본 코드 데모 그대로 실행해본 거야. 4월 7일에 ordinal() (0 기반, 인덱스 3) 쓰면 4월 제대로 나오지. getValue()? MESES[fecha.getMonth().getValue() - 1] 이런 해킹 필요. 추하고, 이제 모든 신규 코드베이스에 박혔어.

ordinal()는 여전—다행—1월=0 고수 중. 그런데 왜 반만? 자동차 대시보드 새 걸 때 주행거리를 1km부터 시작하는 꼴. 승객에겐 직관, 정비사에겐 짜증.

근데 1 기반이 진짜 나을까?

표로 보자. 원본 빌려서 우리말로 옮김:

메서드 기반 예시 느낌
getValue() 1 1월 == 1 직관적
ordinal() 0 1월 == 0 버릇

맞는 말. 인간은 1월을 1로 세. 아이들도 그렇게 배워. 하지만 코드? C의 localtime()은 tm_mon 0부터. JavaScript Date.getMonth()? 0 기반, 출력할 때 +1. Perl, PHP—똑같아. 옛 Calendar.get(Calendar.MONTH)도 0-11이었고.

기존 Java 코드 깨질까?

간단히: java.time 마이그레이션 중이면 맞아—교묘하게. 수십 년 베껴온 월 이름 해킹? 사망. 로그에 이상한 스페인 월 이름 (영어 버전도) 튀어나와 디버깅. Jakarta EE 업그레이드하면서 2025년 2분기 Stack Overflow 폭발 예상.

아무도 안 건드린 각도: Java 5 Enum ordinal() 논쟁 재탕. 그땐 enum이 숫자 버리고 리플렉션으로 가서 난리. Oracle 아무것도 안 배움. ‘순수함’—ISO 준수—쫓다 실용 깨뜨림. 이득? 날짜 감사 컨설팅 비싼 Red Hat. Oracle HotSpot JVM? 똑같이 팔리든 말든.

코드 픽스? 사소하지만 만연. 모든 튜토리얼, 유틸 클래스—다 갈아엎기. 엔터프라이즈 Java에서 날짜가 급여·컴플라이언스 앱에 들끓으니, 청구 가능 시간. 냉소적인 나로선: 완벽. Java 경제 돌려.

역사 훑어봐. C99 struct tm: tm_mon 0-11, 출력 +1. JavaScript ECMA-262: 명시적 0. BASIC 같은 1 기반? COBOL 유물, 비웃음거리. Java는 사실상 표준 고수할 수 있었어. 대신 ‘혁신’으로 직관. 초보자 위해. 베테랑 희생.

큰 그림: 타임존은 여전 지옥

안도 마. LocalDate는 시간 피해—시간·오프셋 없음. 생일엔 좋지. ZonedDateTime 연결? 타임존 데이터 업데이트 늦고, 정부 DST 변덕. Java tzdb는 IANA 끌어오지만 JAR 부풀음. 세 번째? 여전히 물 새는 배 메우기.

Java 날짜 개편 세 번 봤어. 각자 이전 고치다 새 버그 다섯 개 낳음. 예측: Java 25까지 TimeAPI 4.0에 0 기반 월 retrofitt, GitHub 이슈 쌓여서. 내 말 새겨둬.

그래서 대처? 올드스쿨이면 ordinal(). ISO 순수 원하면 getValue() -1. 아니면 MonthUtils.toArrayIndex(month).profile() 래핑. 하지만 이미 bloated 언어에 더 부풀려.

Java는 버텨—전투 검증, 기업 마약. 하지만 이건? 불필요 트립와이어. ‘현대’ API도 어제 찌꺼기 싣고. 내일 후회까지.


🧬 관련 인사이트

자주 묻는 질문

Java의 LocalDate.getMonth().getValue()는 뭐야?

1월-12월 1-12 반환, ISO대로. 0 기반 배열엔 -1 써.

Java Month enum의 getValue()가 왜 1부터?

인간 직관과 ISO 8601 준수 때문, C/JS 프로그래머 0 기반 버릇과 충돌.

Java의 java.time API 버그 있나?

고장 안 났지만 월 인덱싱 off-by-one 함정 도입—세 번째 시도, 똑같은 싸움.

Priya Sundaram
Written by

Hardware and infrastructure reporter. Tracks GPU wars, chip design, and the compute economy.

Worth sharing?

Get the best AI stories of the week in your inbox — no noise, no spam.

Originally reported by Dev.to