2014-04-14 2 views
62

새로운 날짜 시간 API를 사용하여 날짜를 포맷하지만 실행할 때이 :나는 새 날짜 시간 API와 함께 연주했다

public class Test {   
    public static void main(String[] args){ 
     String dateFormatted = LocalDate.now() 
             .format(DateTimeFormatter 
               .ofPattern("yyyy-MM-dd HH:mm:ss")); 
     System.out.println(dateFormatted); 
    } 
} 

이 발생합니다 :

Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: HourOfDay 
    at java.time.LocalDate.get0(LocalDate.java:680) 
    at java.time.LocalDate.getLong(LocalDate.java:659) 
    at java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:298) 
    at java.time.format.DateTimeFormatterBuilder$NumberPrinterParser.format(DateTimeFormatterBuilder.java:2543) 
    at java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2182) 
    at java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:1745) 
    at java.time.format.DateTimeFormatter.format(DateTimeFormatter.java:1719) 
    at java.time.LocalDate.format(LocalDate.java:1685) 
    at Test.main(Test.java:23) 

가의 소스 코드를 볼 때 LOCALDATE 클래스, 나는 참조 :

0 :

private int get0(TemporalField field) { 
     switch ((ChronoField) field) { 
      case DAY_OF_WEEK: return getDayOfWeek().getValue(); 
      case ALIGNED_DAY_OF_WEEK_IN_MONTH: return ((day - 1) % 7) + 1; 
      case ALIGNED_DAY_OF_WEEK_IN_YEAR: return ((getDayOfYear() - 1) % 7) + 1; 
      case DAY_OF_MONTH: return day; 
      case DAY_OF_YEAR: return getDayOfYear(); 
      case EPOCH_DAY: throw new UnsupportedTemporalTypeException("Invalid field 'EpochDay' for get() method, use getLong() instead"); 
      case ALIGNED_WEEK_OF_MONTH: return ((day - 1)/7) + 1; 
      case ALIGNED_WEEK_OF_YEAR: return ((getDayOfYear() - 1)/7) + 1; 
      case MONTH_OF_YEAR: return month; 
      case PROLEPTIC_MONTH: throw new UnsupportedTemporalTypeException("Invalid field 'ProlepticMonth' for get() method, use getLong() instead"); 
      case YEAR_OF_ERA: return (year >= 1 ? year : 1 - year); 
      case YEAR: return year; 
      case ERA: return (year >= 1 ? 1 : 0); 
     } 
     throw new UnsupportedTemporalTypeException("Unsupported field: " + field); 
    } 

는 문서에 설명 된대로

이 메서드는 클래스 설명서에 설명 된대로 문자 및 기호의 간단한 패턴을 기반으로 포맷터를 만듭니다.

이 글자는 모두 defined입니다.

그렇다면 왜 DateTimeFormatter.ofPattern으로 패턴 문자를 사용할 수 없습니까?

답변

109

LocalDate은 DateTime이 아니라 날짜를 나타냅니다. 따라서 "HH : mm : ss"는 LocalDate을 포맷 할 때 의미가 없습니다. 날짜와 시간을 모두 나타내려면 LocalDateTime을 대신 사용하십시오.

25

내가 @James_D의 정답에 다음과 같은 세부 사항을 추가하고 싶습니다 :

배경 : 대부분의 날짜 및 시간 - 라이브러리 (자바 java.util.Calendar, 자바 스크립트도 닷넷 날짜 시간 또는 Date 참조 또는 Perl에서 DateTime)는 보편적 인 다목적 고유 한 일시적 유형의 개념을 기반으로합니다 (독일어에서는 "eierlegende Wollmilchsau"라는 시적인 표현이 있습니다). 이 디자인에서는 지원되지 않는 필드가있을 수 없습니다. 그러나 가격이 비싸다. 많은 시간 문제는 온갖 종류의 시간 대상에 대해 공통 분모를 찾는 것이 불가능하기 때문에 이러한 융통성없는 접근법으로는 적절하게 처리 될 수 없다.

JSR-310은 다른 방식 인을 선택했습니다. 즉, 지원되는 기본 제공 필드의 유형별 세트로 구성된 다른 시간 유형을 허용합니다. 자연스러운 결과는 가능한 모든 필드가 모든 유형에서 지원되는 것은 아니며 사용자는 고유 한 필드를 정의 할 수도 있습니다. 또한 지원되는 필드 집합에 대해 TemporalAccessor 유형의 모든 개체 programmatically ask이 가능합니다. LocalDate 위해 우리는 찾을 수 :

•DAY_OF_WEEK 
•ALIGNED_DAY_OF_WEEK_IN_MONTH 
•ALIGNED_DAY_OF_WEEK_IN_YEAR 
•DAY_OF_MONTH 
•DAY_OF_YEAR 
•EPOCH_DAY 
•ALIGNED_WEEK_OF_MONTH 
•ALIGNED_WEEK_OF_YEAR 
•MONTH_OF_YEAR 
•PROLEPTIC_MONTH 
•YEAR_OF_ERA 
•YEAR 
•ERA 

UnsupportedTemporalTypeException의 문제를 설명하고 더 HOUR_OF_DAY 필드가 없습니다. 우리는 JSR-310- mapping of pattern symbols to fields를 보면 우리는 기호 H가 지원되지 않는 HOUR_OF_DAY에 매핑되는 것을 볼 수 :

/** Map of letters to fields. */ 
private static final Map<Character, TemporalField> FIELD_MAP = new HashMap<>(); 
static { 
    FIELD_MAP.put('G', ChronoField.ERA); 
    FIELD_MAP.put('y', ChronoField.YEAR_OF_ERA); 
    FIELD_MAP.put('u', ChronoField.YEAR); 
    FIELD_MAP.put('Q', IsoFields.QUARTER_OF_YEAR); 
    FIELD_MAP.put('q', IsoFields.QUARTER_OF_YEAR); 
    FIELD_MAP.put('M', ChronoField.MONTH_OF_YEAR); 
    FIELD_MAP.put('L', ChronoField.MONTH_OF_YEAR); 
    FIELD_MAP.put('D', ChronoField.DAY_OF_YEAR); 
    FIELD_MAP.put('d', ChronoField.DAY_OF_MONTH); 
    FIELD_MAP.put('F', ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH); 
    FIELD_MAP.put('E', ChronoField.DAY_OF_WEEK); 
    FIELD_MAP.put('c', ChronoField.DAY_OF_WEEK); 
    FIELD_MAP.put('e', ChronoField.DAY_OF_WEEK); 
    FIELD_MAP.put('a', ChronoField.AMPM_OF_DAY); 
    FIELD_MAP.put('H', ChronoField.HOUR_OF_DAY); 
    FIELD_MAP.put('k', ChronoField.CLOCK_HOUR_OF_DAY); 
    FIELD_MAP.put('K', ChronoField.HOUR_OF_AMPM); 
    FIELD_MAP.put('h', ChronoField.CLOCK_HOUR_OF_AMPM); 
    FIELD_MAP.put('m', ChronoField.MINUTE_OF_HOUR); 
    FIELD_MAP.put('s', ChronoField.SECOND_OF_MINUTE); 
    FIELD_MAP.put('S', ChronoField.NANO_OF_SECOND); 
    FIELD_MAP.put('A', ChronoField.MILLI_OF_DAY); 
    FIELD_MAP.put('n', ChronoField.NANO_OF_SECOND); 
    FIELD_MAP.put('N', ChronoField.NANO_OF_DAY);  
} 

이 필드 맵핑이 필드는 구체적인 유형에서 지원되는 것은 아닙니다. 파싱은 여러 단계에서 발생합니다. 필드 매핑은 첫 번째 단계 일뿐입니다. 그런 다음 두 번째 단계는 TemporalAccessor 유형의 원시 객체로 파싱합니다. 마지막으로 대상 유형 (여기서는 LocalDate)에 대한 대리자를 구문 분석하고 파싱 된 중간 개체의 모든 필드 값을 받아들이는지 결정합니다.

+0

https://en.wiktionary.org/wiki/eierlegende_Wollmilchsau (말 그대로 "달걀 양모 - 우유 - 암 s지") 긍정적 인 특성을 지녔거나 가지고 있다고 주장하는 올인원 장치 또는 사람 몇 가지 특수 도구의 작업을 수행 할 수 있습니다. :-) –

1

LocalDate에는 시간 정보가 없으므로 UnsupportedTemporalTypeException: Unsupported field: HourOfDay이 표시됩니다.

LocalDateTime을 사용할 수 있지만 표준 시간대 정보가 없으므로 미리 정의 된 형식 지정자 중 하나를 사용하여 액세스하려고하면 UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds이 표시됩니다.

나를위한 올바른 클래스는 시간과 시간대를 모두 포함하는 ZonedDateTime입니다.

+0

당신은 나를 많이 구해 줬습니다. 고맙습니다!!! – Hafiz