HOWTO · Java

java.text.ParseException 수정: Java에서 구문 분석할 수 없는 날짜 오류

이 자습서는 java.text.ParseException: Java의 구문 분석할 수 없는 날짜 오류를 보여줍니다.

이 페이지의 내용

이 가이드에서는 Java 날짜 문자열이 파싱 패턴과 일치하지 않을 때 java.text.ParseException: Unparseable date 오류를 진단하는 방법을 설명합니다. 입력을 왼쪽부터 패턴과 대조한 다음, 파싱한 값을 형식화하기 전에 현지화된 텍스트와 시간대도 고려하세요.

Java에서 java.text.ParseException: Unparseable date 오류 수정

SimpleDateFormat는 패턴 문자에 따라 텍스트를 파싱하며, 의도한 날짜 형식을 추측하지 않습니다. 파싱에 실패하는 이유는 대개 패턴이 입력에 없는 필드나 텍스트를 예상하기 때문입니다. 예를 들어 Tue Aug 16 12:30:10 IST 2022는 요일, 영어 월 이름, 일, 시각, 시간대 약어, 연도 순으로 구성됩니다. MMM d, yyyy HH:mm:ss 같은 패턴은 구두점이 다르고 요일과 시간대가 빠져 있으므로, 적힌 그대로는 이 문자열을 모두 파싱할 수 없습니다.

구분자와 공백까지 포함해 입력 전체를 살펴보세요. 요일, 월 이름, 일, 시간 필드, 시간대, 연도를 확인합니다. ParseException은 파싱이 멈춘 위치를 나타냅니다. 그 위치의 텍스트를 패턴이 다음에 요구하는 필드와 대조하세요. 시간대 차이만으로 이 예외가 발생한다고 보아서는 안 됩니다. 시간대는 일반적으로 표현되는 시점이나 표시 방식에 영향을 줍니다.

날짜 패턴을 입력 문자열에 맞추기

패턴 문자는 대소문자를 구분합니다. MM은 월이고 mm은 분입니다. 달력 연도에는 yyyy를 사용하세요. 대문자 YYYY는 주 기준 연도를 뜻하므로 연도가 바뀌는 시점에 예상과 다른 결과가 나올 수 있습니다. 필드의 개수와 순서도 입력에 맞아야 합니다. 제공된 날짜 문자열을 파싱하려면 요일(EEE), 축약 월 이름(MMM), 두 자리 일(dd), 24시간제 시각(HH:mm:ss), 시간대(z), 연도(yyyy)를 패턴에 포함해야 합니다.

입력과 패턴을 나란히 적고 각 토큰을 순서대로 맞춰 보면 원인을 찾는 데 도움이 됩니다. 텍스트에 숫자로 된 월과 일이 있으면 같은 순서와 구분자를 사용하는 숫자 패턴을 쓰세요. 월 이름이 있다면 텍스트 월 패턴을 사용합니다. 각 문자의 의미를 확인하지 않은 채 대소문자만 바꿔 패턴을 “수정”하지 마세요.

파싱 로캘과 시간대를 명시적으로 설정하기

텍스트로 된 월 이름과 요일 이름은 로캘에 따라 달라집니다. 입력에 영어 이름이 있다면 시스템의 기본 로캘에 의존하지 말고 Locale.ENGLISH를 전달하세요. 개발자 컴퓨터와 서버의 기본 로캘은 서로 다를 수 있습니다. 텍스트를 만든 로캘을 사용하고 명시적으로 지정해 파서가 같은 월 이름과 요일 이름을 예상하도록 하세요.

시간대가 포함된 날짜 문자열에는 시각을 해석하는 데 필요한 정보가 담겨 있습니다. IST 같은 시간대 약어는 지역이나 데이터 출처에 따라 의미가 모호할 수 있습니다. 직접 관리하는 형식에는 뜻이 분명한 숫자 오프셋이나 지역 기반 시간대 식별자를 사용하세요. 기존 텍스트를 파싱한다면 해당 약어를 만든 쪽에서 어떤 의미로 사용했는지 확인합니다. 형식화할 때 시간대를 명시하면 표시 시각이 호스트 컴퓨터 설정에 따라 달라지는 일을 막을 수 있습니다. 시간대는 해석이나 표시에 영향을 주지만, 서로 맞지 않는 날짜 필드를 바로잡지는 않습니다.

전체 파싱 및 출력 형식화 예제 실행하기

패턴 MMM d, yyyy HH:mm:ss가 입력과 맞지 않는 상태에서 new SimpleDateFormat("MMM d, yyyy HH:mm:ss", Locale.ENGLISH).parse(input)으로 제공된 문자열을 파싱하면 실패합니다. 패턴은 처음에 월 이름을 예상하지만 입력은 요일로 시작하기 때문입니다. 이때 발생하는 예외는 java.text.ParseException: Unparseable date: "Tue Aug 16 12:30:10 IST 2022"입니다. 아래의 수정된 패턴은 요일, 월, 일, 시각, 시간대, 연도를 반영합니다. 영어 로캘을 사용하고 파싱한 시점을 UTC로 형식화합니다. 표시 결과를 일관되게 재현할 수 있도록 이 예제는 위에서 본 모호한 IST 대신 입력에 UTC를 사용합니다. 애플리케이션에서 입력 형식을 직접 관리한다면 의미가 명확한 시간대 표기를 사용하세요.

다음 예제를 실행해 보세요. 코드에 표시되는 오류 메시지와 날짜 출력은 영어로 유지됩니다.

import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class ParseDateExample {
    public static void main(String[] args) {
        String input = "Tue Aug 16 10:30:10 UTC 2022";
        SimpleDateFormat parser = new SimpleDateFormat(
                "EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
        ParsePosition position = new ParsePosition(0);
        Date parsed = parser.parse(input, position);
        if (parsed == null || position.getIndex() != input.length()) {
            System.out.println("Input did not match the pattern.");
            return;
        }

        SimpleDateFormat display = new SimpleDateFormat(
                "EEE MMM d, yyyy HH:mm:ss 'UTC'", Locale.ENGLISH);
        display.setTimeZone(TimeZone.getTimeZone("UTC"));
        System.out.println(display.format(parsed));
    }
}
Tue Aug 16, 2022 10:30:10 UTC

파서는 원본 텍스트를 읽고, 두 번째 포매터는 읽기 쉬운 출력 형식과 명시적인 표시 시간대를 선택합니다.