2014-12-15 1 views
2

이 질문은 How to parse ZonedDateTime with default zone?과 유사하지만 추가 조건이 있습니다.시간이없는 문자열을 ZonedDateTime의 로컬 형식으로 구문 분석하는 방법은 무엇입니까?

영국 형식의 날짜 인 "3/6/09"를 나타내는 문자열 매개 변수가 있습니다. 시간이없고 날짜 만 포함되어 있습니다. 하지만 시간대가 포함될 수 있습니다. 그리고 저는 이것을 ZonedDateTime으로 파싱하고 싶습니다.

public static ZonedDateTime parse(String value) { 
    DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(SHORT).withLocale(Locale.UK).withZone(ZoneId.systemDefault()); 
    TemporalAccessor temporalAccessor = formatter.parseBest(value, ZonedDateTime::from, LocalDateTime::from, LocalDate::from); 
    if (temporalAccessor instanceof ZonedDateTime) { 
     return ((ZonedDateTime) temporalAccessor); 
    } 
    if (temporalAccessor instanceof LocalDateTime) { 
     return ((LocalDateTime) temporalAccessor).atZone(ZoneId.systemDefault()); 
    } 
    return ((LocalDate) temporalAccessor).atStartOfDay(ZoneId.systemDefault()); 
} 

는하지만, 그것은 예외와 함께 실패합니다

java.time.format.DateTimeParseException: Text '3/6/2009' could not be parsed at index 6 

그것은 나를 위해 버그, 또는하지?

+2

홈페이지 이의이다 : 당신은'DateTimeFormatter를 사용합니다. ofLocalizedDateTime (...) '입력에 적어도 시간 또는 시간 구성 요소가 있어야합니다. 또 다른 관찰 :'DateTimeFormatter.ofLocalizedDate (...)'가 실패하는 동안 old pre8-code'Date d = DateFormat.getDateInstance (DateFormat.SHORT, Locale.UK) .parse (input); 어쩌면 오라클이 Threeten 라이브러리의 SHORT 형식을 변경했을 수도 있습니다. 당신은 아마도 명백한 패턴을 선호하고 다시 시도해야합니다. 그건 그렇고, instanceof - 표현과 같은 코드는 오히려 내 눈을 아프게 (죄송합니다). –

+1

과거의 긍정적 인 경험 만하지는 않았지만 입력의 선택적 부분을 보완하기 위해'DateTimeFormatterBuilder.parseDefaulting()'및/또는 선택 섹션을 실험 해 볼 수도 있습니다. –

답변

2

제 생각에는 버그가 아닙니다. 귀하의 접근법에 결함이 있습니다.

먼저 String에 전체 날짜, 시간 및 영역 정보가 포함될 것으로 예상되므로 ZonedDateTime을 반환합니다. 문자열 "3/6/09"는 LocalDate로 구문 분석되어야합니다.

둘째, 라이브러리의 형식에 대한 런타임 감지를 위임합니다. 다시 말하지만, 예상 포맷을 파싱/포맷팅해야합니다. 귀하의 응용 프로그램은 전체 날짜 & 시간 또는 부분 (날짜 또는 시간 만)을 기다리고 있음을 알아야합니다.

어쨌든 형식을 감지 한 다음 다른 구문 분석 방법을 사용하면 더 많은 행운을 얻게됩니다.

로컬 날짜 :

DateTimeFormatter 
    .ofLocalizedDate(FormatStyle.SHORT) 
    .parse(value, LocalDate::from)` 

지대로 나뉨 날짜와 시간 :

DateTimeFormatter 
    .ofLocalizedDateTime(FormatStyle.SHORT, FormatStyle.SHORT) 
    .parse(value, ZonedDateTime::from)` 
1

사용되는 포맷은 getLocalizedDateTimePattern() 방법을 사용하여 알 수있다 :

String fmt = DateTimeFormatterBuilder.getLocalizedDateTimePattern(
    FormatStyle.SHORT, FormatStyle.SHORT, IsoChronology.INSTANCE, Locale.UK); 

결과 "dd/MM/yy HH:mm"이다.

이와 같이 형식은 날짜와 시간을 모두 공백으로 구분해야하므로 제공해야합니다.

또한 형식/구문 분석에서는 날짜가 두 자리이고 월이 두 자릿수 여야합니다. 따라서 예상 결과를 얻으려면 "03/06/09 00:00"을 전달해야하며이 경우 LocalDateTime으로 직접 파싱 할 수 있습니다.

또는 ofLocalizedDate()를 사용 입력이 여전히 하루 달 동안 두 자리가 있어야합니다

DateTimeFormatter formatter = 
    DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).withLocale(Locale.UK); 
LocalDate date = LocalDate.parse("03/06/99", formatter); 

하는 것으로.

또는 누락 된 선행 0을 처리 할 수있는 특정 패턴을 사용하여 구문 분석 :

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/M/yy"); 
LocalDate date = LocalDate.parse("3/6/99", formatter); 
LocalDate date = LocalDate.parse("03/06/99", formatter); 
// handles both "3/6/99" and "03/06/99" 

업데이트 : 융통성이 분석은 또한이 사건을 처리합니다

DateTimeFormatter formatter = new DateTimeFormatterBuilder() 
     .parseLenient().appendPattern("dd/MM/yy").toFormatter(); 
LocalDate date = LocalDate.parse("3/6/99", formatter); 
LocalDate date = LocalDate.parse("03/06/99", formatter); 
// handles both "3/6/99" and "03/06/99" 
관련 문제