2014-10-15 2 views
10

간단한 문제가 있습니다. 정확하게 "yyyyMMdd" 형식의 Java 문자열을 구문 분석하려고하므로 "19800229"은 유효한 날짜이지만 "19820229"은 그렇지 않습니다. 이들은 정상적인 그레고리오 달력의 AD 날짜라고 가정합니다.엄격한 날짜 구문 분석을 위해 새로운 Java 8 DateTimeFormatter 사용

이 문제를 해결하기 위해 새로운 java.time 패키지를 JDK 8에서 사용하려하지만, 기대했던 것보다 더 복잡합니다. 나의 현재 코드는 다음과 같습니다 그러나

private static final DateTimeFormatter FORMAT = DateTimeFormatter 
     .ofPattern("yyyyMMdd").withChronology(IsoChronology.INSTANCE) 
     .withResolverStyle(STRICT); 

public static LocalDate parse(String yyyyMMdd) { 
    return LocalDate.parse(yyyyMMdd, FORMAT); 
} 

, 예 : "19800228"는 이해할 수없는 오류가 나에게 무엇을 생산으로 유효한 날짜를 구문 분석 :

java.time.format.DateTimeParseException: Text '19820228' could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {MonthOfYear=2, DayOfMonth=28, YearOfEra=1982},ISO of type java.time.format.Parsed

가 어떻게 내 간단한 사용 사례를 해결하기 위해 java.time.format.DateTimeFormatter를 사용합니까 ?

답변

2

DateTimeFormatterBuilder로 만든 사용자 지정 포매터를 사용하여 어떤 종류의 문자열을 유효하게 간주할지 편집하는 중입니다.

public class DateFormmaterTest { 

    static DateTimeFormatter CUSTOM_BASIC_ISO_DATE = new DateTimeFormatterBuilder() 
      .parseCaseInsensitive().appendValue(YEAR, 4) 
      .appendValue(MONTH_OF_YEAR, 2).appendValue(DAY_OF_MONTH, 2) 
      .optionalStart().toFormatter() 
      .withResolverStyle(ResolverStyle.STRICT) 
      .withChronology(IsoChronology.INSTANCE); 

    public static void main(String[] args) { 

     LocalDate date1 = LocalDate.parse("19800228-5000", 
       CUSTOM_BASIC_ISO_DATE); 

     System.out.println(date1); 

    } 
} 

1982년 2월 29일이 잘못하고 throw하는 다음

Caused by: java.time.DateTimeException: Invalid date 'February 29' as '1982' is not a leap year 
    at java.time.LocalDate.create(LocalDate.java:429) 

가 19800228-5000의 날짜가 BASIC_ISO_DATE와 함께 일하는 것이는 선택 사항이 허용하지 않으려하는 오프셋 수 있기 때문에 . 내 CUSTOM_BASIC_ISO_DATE 포맷터가 가능하고 다음 던져하지 않습니다

Exception in thread "main" java.time.format.DateTimeParseException: Text '19800228-5000' could not be parsed, unparsed text found at index 8. 

주, 당신은 문자열 길이의 확신하는 경우를 YYYYMMDD는 당신은 항상 해결의 필요성을 부정하는 처음 8 개 문자의 문자열과 함께 일할 수 . 그러나 그것은 두 가지 다른 것들입니다. 해결사는 잘못된 날짜 형식을 입력에 플래그를 지정하고 하위 문자열은 물론 여분의 문자를 제거합니다.

+0

Thanks @Tech Trip. 죄송합니다. 두 가지 경우 모두 2/29를 의미했습니다. 이유는 내가'DateTimeFormatter.BASIC_ISO_DATE'을 피하는 이유는 선택 가능한 부분을 가지고 있기 때문에 파싱 할 수 없기 때문입니다. 옵션 파트가없는 동등한 포맷터를 만들 수 있습니까? – 0xbe5077ed

+0

나는 귀하의 마지막 코멘트를 고려하여 답을 수정했습니다. 한번보세요! – TechTrip

+0

좋으면, @Tech Trip. 그것이 내가 발견 한 것입니다. yyyyMMdd는 대소 문자 문제가 없기 때문에 불필요한 parseCaseInsensitive()를 제거 할 수 있으며, 선택 사항을 시작하지 않기 때문에'startOptional()'을 제거 할 수 있습니다. – 0xbe5077ed

1

대신 "uuuuMMdd"형식을 사용해보십시오.

12

Java 8은 yyyy이 아닌 uuuu을 사용합니다. Java 8에서 은 "BC 또는 AD"를 의미하며, MonthOfYear, DayOfMonth 및 YearOfEra는 시대를 알 수 없기 때문에 날짜를 구성하는 정보가 충분하지 않다고 오류 메시지가 표시됩니다.

수정하려면 서식 문자열에 uuuu을 사용하십시오. DateTimeFormatter.ofPattern("uuuuMMdd")

yyyy을 계속 사용하려면 기본 시대를 설정할 수 있습니다.

new DateTimeFormatterBuilder() 
     .appendPattern("yyyyMMdd") 
     .parseDefaulting(ChronoField.ERA, 1 /* era is AD */) 
     .toFormatter() 
관련 문제