2017-03-20 1 views
4

그래서 SimpleDateFormat 및 Date를 사용하여 일부 기존 코드를 대체하려고 할 때 java.time.DateTimeFormatter 및 LocalDate를 사용할 때 문제가 발생했습니다. 두 가지 날짜 형식은 동일하지 않습니다. 이 시점에서 나는 두 날짜 유형이 동일하지 않다는 것을 말해야 만하지만, 나는 시나리오에 대해 결코 신경 쓰지 않는다는 것을 의미하므로 무시할 수있다. 같은 패턴이 DateTimeFormatter 당신이 SDF 동등한 날짜를보고 기대 널 (null)을 생산 끝 모두 포맷터에서 사용하는 경우 당신이 볼 수 있듯이SimpleDateFormat을 DateTimeFormatter로 변환

public Date getDate(String value) { 
    SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy"); 
    try { 
     return dateFormat.parse(value); 
    } catch (ParseException e) { 
     return null; 
    } 
} 

public LocalDate getLocalDate(String value) { 
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy"); 
    try { 
     return LocalDate.parse(value, formatter); 
    } catch (DateTimeParseException e) { 
     return null; 
    } 
} 

public void testDates() { 
    getDate("03/07/2016");    // Sun Jul 03 00:00:00 BST 2016 
    getDate("3/7/2016");     // Sun Jul 03 00:00:00 BST 2016 
    getDate("3/7/2016 00:00:00");  // Sun Jul 03 00:00:00 BST 2016 
    getDate("3/7/2016 00:00:00.0+0100"); // Sun Jul 03 00:00:00 BST 2016 
    getDate("3/7/2016T00:00:00.0+0100"); // Sun Jul 03 00:00:00 BST 2016 

    getLocalDate("03/07/2016");    // 2016-07-03 
    getLocalDate("3/7/2016");     // null 
    getLocalDate("3/7/2016 00:00:00");  // null 
    getLocalDate("3/7/2016 00:00:00.0+0100"); // null 
    getLocalDate("3/7/2016T00:00:00.0+0100"); // null 
} 

. 이 시나리오에서는 필자는 불필요한 데이터는 삭제 될 것으로 예상하지만 그렇지 않습니다.

그럼 어떻게 강력한 날짜/시간 구문 분석기를 만들 수 있습니까?!

+2

나는 생각하지 않는다'DD가/MM은/yyyy'이 달의 하루 명확하게 2 자리, 월 2 자리, 올해 4 자리 숫자를 필요로'때문에 SimpleDateFormat'이, 더 강력한 것입니다. 입력 내용이이 요구 사항과 일치하지 않으면 프레임 워크에서 구문 분석 예외를 발생시켜야합니다. 사용자 요구 사항과 다른 변환을하는 것은 위험합니다. –

+1

예 SDF가 손상되었지만 코드가 이에 의존합니다. 따라서 일반적으로 API는 고정 된 형식이어야하며이 시나리오에서는 파일을 파싱하고 사람들은 다양한 형식으로 날짜를 제공 할 수 있다는 점에 동의합니다. 코드는 그들 모두를 수용해야합니다. 분명히 이것은 직면 한 문제의 발췌 일뿐입니다. 실제로 날짜 순서 지정과 구분 기호에 대한 검사가 훨씬 더 많습니다. – Remlap21

답변

3

그래서 다른 답변이있을 수 있지만 내가 가진 가장 극단적 인 경우를 충족시켜줍니다. 첫째로 나는 dd/MM을 d/M으로 줄였습니다. 이것은 예상되는 문자의 최소 수를 나타내므로 두 자리 수를 완전히 파싱합니다. 새로운 DateTimeFormatterBuilder(). parseLenient()를 사용할 수도 있습니다. 그러나 이것은 불필요한 것으로 보입니다.

두 번째로 포맷 패턴 자체에 선택적 절을 사용하기로 결정했습니다. 이렇게하면 어떤 부분을 제공 할지를 지정할 수 있습니다. 정확히 어떤 부분을 해결하려고했는지는 알 수 없습니다.

하는 것은 우리를 떠나 :

DateTimeFormatter.ofPattern(d/M/yyyy[' ']['T'][H:mm[:ss[.S]]][X]); 

이 이제 오프셋 T 분리기, 초, 밀리 및 영역을 포함하여 시간을 사용하거나 사용하지 않고 날짜를 제공 처리합니다.

운이 좋으면 다른 사람을 도우십시오!

private DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/M/yyyy[' ']['T'][H:mm[:ss[.S]]][X]"); 

public LocalDate getRobustLocalDate(String value) { 
    try { 
     return LocalDate.parse(value, formatter); 
    } catch (DateTimeParseException e) { 
     return null; 
    } 
} 

@Test 
public void testDates() { 
    getRobustLocalDate("03/07/2016");    // 2016-07-03 
    getRobustLocalDate("3/7/2016");     // 2016-07-03 
    getRobustLocalDate("3/7/2016 00:00:00");  // 2016-07-03 
    getRobustLocalDate("3/7/2016 00:00:00.0+0100"); // 2016-07-03 
    getRobustLocalDate("3/7/2016T00:00:00.0+0100"); // 2016-07-03 
} 
+1

메소드를 호출 할 때마다 실제로'DateTimeFormatter'를 초기화 할 필요가 없습니다.'DateTimeFormatter' 클래스의 인스턴스가 불변이므로 메소드 밖에서 저장할 수 있고 재사용 할 수 있으므로 객체 생성 및 패턴 구문 분석을 약간 절약 할 수 있습니다. 당신의 패턴은 바뀌지 않을 것입니다, 그래서 이것이 유효한 조정 일 수 있다고 생각합니다. –

+0

네 - 전적으로 동의합니다. 테스트 목적으로 만 그런 것 같습니다. 다른 사람들에게 더 명확하게 편집 할 것입니다. – Remlap21

관련 문제