자바 날짜 포맷 완벽 정리 — DateTimeFormatter 패턴·파싱·thread-safe
자바에서 날짜를 원하는 문자열로 바꾸려면 DateTimeFormatter.ofPattern("yyyy-MM-dd")로 포맷을 만들고 날짜.format(포맷)을 호출합니다. 반대로 문자열을 날짜로 바꿀 때는 LocalDate.parse("2026-07-19", 포맷)을 씁니다. 예를 들어 LocalDate.of(2026, 7, 19).format(DateTimeFormatter.ofPattern("yyyy년 MM월 dd일"))은 2026년 07월 19일을 반환합니다. Java 8부터 도입된 이 방식은 예전 SimpleDateFormat과 달리 불변(immutable)이라 여러 스레드에서 안전하게 재사용할 수 있습니다.
java.time 패키지). 본문 예제 출력은 모두 Java 21에서 직접 실행해 확인한 값입니다. 기준 날짜는 2026-07-19 09:05:03(일요일)입니다.
1. 날짜를 문자열로 바꾸기 — format()
DateTimeFormatter.ofPattern(패턴)으로 포맷을 만든 뒤, LocalDate·LocalDateTime 등의 format()에 넘기면 됩니다.
import java.time.*;
import java.time.format.DateTimeFormatter;
LocalDateTime dt = LocalDateTime.of(2026, 7, 19, 9, 5, 3);
LocalDate d = dt.toLocalDate();
dt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); // 2026-07-19 09:05:03
d.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); // 2026-07-19
dt.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")); // 20260719090503
d.format(DateTimeFormatter.ofPattern("yyyy년 MM월 dd일")); // 2026년 07월 19일
구글에서 많이 찾는 yyyymmddhhmmss 형태도 대소문자만 맞추면 됩니다. 날짜는 대문자 MM(월), 시간은 대문자 HH(24시간)·소문자 mm(분)이라는 점만 주의하세요. 소문자 mm을 월로 착각해 yyyy-mm-dd라고 쓰면 월 자리에 분이 찍힙니다.
2. 자주 쓰는 패턴 문자
패턴 문자는 대소문자를 구분합니다. 실무에서 자주 쓰는 것만 추리면 아래와 같습니다. (전체 목록은 아래 참고 출처의 공식 Javadoc)
| 문자 | 의미 | 예시 |
|---|---|---|
y | 연도 | 2026; yyyy → 2026 |
M | 월 | 7; 07; Jul; July |
d | 일(day-of-month) | 19 |
H | 시(0~23) | 9; 23 |
h | 시(1~12, 오전·오후용) | 9; 12 |
m | 분 | 05 |
s | 초 | 03 |
E | 요일 | 일; 일요일; Sun |
a | 오전/오후 | 오전; PM |
X / Z | 타임존 오프셋 | +09:00; +0900 |
3. 한글 요일·오전/오후 — Locale
요일 이름이나 오전/오후는 Locale에 따라 달라집니다. 두 번째 인자로 Locale.KOREAN을 넘기면 한글로 나옵니다.
import java.util.Locale;
LocalDate d = LocalDate.of(2026, 7, 19);
d.format(DateTimeFormatter.ofPattern("yyyy년 M월 d일 E요일", Locale.KOREAN));
// 2026년 7월 19일 일요일
d.format(DateTimeFormatter.ofPattern("EEEE, MMM d yyyy", Locale.ENGLISH));
// Sunday, Jul 19 2026
LocalDateTime.of(2026, 7, 19, 9, 5, 3)
.format(DateTimeFormatter.ofPattern("a h:mm", Locale.KOREAN));
// 오전 9:05
Locale을 생략하면 실행 환경의 기본 로케일을 따르므로, 서버·개발 PC 설정에 따라 결과가 달라질 수 있습니다. 요일·월 이름을 문자열로 내보낸다면 Locale을 명시하는 편이 안전합니다.
4. 문자열을 날짜로 바꾸기 — parse()
거꾸로 문자열을 날짜 객체로 바꿀 때는 각 타입의 parse()에 같은 포맷을 넘깁니다. 파싱한 뒤에는 자바 날짜 더하고 빼는 계산처럼 plusDays 등을 그대로 쓸 수 있습니다.
LocalDate parsed = LocalDate.parse(
"2026-07-19", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
System.out.println(parsed); // 2026-07-19
System.out.println(parsed.plusDays(1)); // 2026-07-20
LocalDateTime dt = LocalDateTime.parse(
"2026/07/19 09:05", DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm"));
System.out.println(dt); // 2026-07-19T09:05
DateTimeParseException이 발생합니다(포맷 오류 시 format()은 DateTimeException). 외부 입력을 파싱할 때는 try-catch로 감싸 잘못된 형식을 처리하세요.
5. 미리 정의된 표준 포맷 (ISO)
패턴을 직접 쓰지 않아도, 자주 쓰는 ISO-8601 형식은 상수로 제공됩니다.
LocalDate d = LocalDate.of(2026, 7, 19);
LocalDateTime dt = LocalDateTime.of(2026, 7, 19, 9, 5, 3);
d.format(DateTimeFormatter.ISO_LOCAL_DATE); // 2026-07-19
dt.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); // 2026-07-19T09:05:03
6. 타임존을 포함한 포맷
타임존 정보가 필요하면 ZonedDateTime에 X·Z 패턴을 씁니다.
ZonedDateTime z = LocalDateTime.of(2026, 7, 19, 9, 5, 3)
.atZone(ZoneId.of("Asia/Seoul"));
z.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss XXX"));
// 2026-07-19 09:05:03 +09:00
z.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ"));
// 2026-07-19T09:05:03+0900
패턴 안에서 T처럼 그대로 찍고 싶은 글자는 작은따옴표로 감싸('T') 리터럴 처리합니다.
7. SimpleDateFormat 대신 DateTimeFormatter를 쓰는 이유
예전 SimpleDateFormat은 내부에 상태를 갖고 있어 여러 스레드가 하나의 인스턴스를 공유하면 날짜가 깨집니다. 자세한 원인과 재현은 SimpleDateFormat이 thread-safe하지 않은 이유에서 다뤘습니다.
반면 DateTimeFormatter는 공식 문서가 "This class is immutable and thread-safe."라고 명시합니다. 불변이므로 하나의 인스턴스를 static final 상수로 만들어 여러 스레드에서 안심하고 재사용할 수 있습니다.
public class DateUtils {
// 불변이라 상수로 공유해도 안전 — 매번 new 하지 않아도 됨
public static final DateTimeFormatter YMD =
DateTimeFormatter.ofPattern("yyyy-MM-dd");
public static String toYmd(LocalDate d) {
return d.format(YMD);
}
}
자주 묻는 질문 (FAQ)
Q. yyyy와 YYYY는 같나요?
아닙니다. 소문자 yyyy는 일반 연도, 대문자 YYYY는 주(week) 기준 연도(week-based-year)라 연말·연초에 값이 어긋날 수 있습니다. 평소에는 소문자 yyyy를 쓰세요.
Q. 월을 소문자 mm으로 썼는데 이상한 값이 나와요.
소문자 m은 분입니다. 월은 대문자 M입니다. yyyy-MM-dd가 맞습니다.
Q. 요일이 영어로 나옵니다.
Locale을 지정하지 않으면 실행 환경 기본값을 따릅니다. ofPattern("E요일", Locale.KOREAN)처럼 로케일을 명시하세요. 요일만 필요하면 DayOfWeek로 요일 구하는 방법도 참고하세요.
마무리
정리하면, 날짜→문자열은 날짜.format(DateTimeFormatter.ofPattern(패턴)), 문자열→날짜는 타입.parse(문자열, 포맷)입니다. 패턴 문자는 대소문자(M월/m분, H24시/h12시)만 조심하면 되고, 포맷 인스턴스는 static final로 재사용하는 것이 안전하고 빠릅니다.
📚 참고 출처 (2026년 7월 19일 확인)
· Oracle Java 21 Javadoc — DateTimeFormatter
· 본문 예제 출력은 Java 21(21.0.4)에서 직접 실행해 확인했습니다.

COMMENTS