새 날짜 시간 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 클래스의 소스 코드를 보면 다음과 같습니다.

  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);
    }

문서에 설명 된대로 :

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

그리고이 모든 문자가 정의됩니다 .

그렇다면 DateTimeFormatter.ofPattern패턴 문자를 사용하지 않는 이유 는 무엇입니까?



답변

LocalDateDateTime이 아니라 날짜를 나타냅니다. 따라서 “HH : mm : ss”는 LocalDate. LocalDateTime날짜와 시간을 모두 나타내려는 경우 대신 a 를 사용하십시오 .


답변

@James_D의 정답에 다음 세부 정보를 추가하고 싶습니다.

배경 : 대부분의 날짜 및 시간 라이브러리 ( java.util.CalendarJava에서 .Net-DateTime 또는 DateJavaScript 또는 DateTimePerl 참조)는 범용 다목적 고유 시간 유형의 개념을 기반으로합니다 (독일어에는 시적 표현이 있습니다. ” eierlegende Wollmilchsau ‘). 이 디자인에는 지원되지 않는 필드가있을 수 없습니다. 그러나 가격이 비싸다. 모든 종류의 시간적 객체에 대한 공통 분모를 찾기가 불가능하기 때문에 이러한 융통성없는 접근 방식으로는 문제를 적절히 처리 할 수없는 경우가 많습니다.

JSR-310은 지원되는 내장 필드의 유형별 세트로 구성된 다른 시간 유형을 허용하는 다른 방법을 선택 했습니다. 자연스러운 결과는 모든 가능한 필드가 모든 유형에서 지원되는 것은 아니라는 것입니다 (사용자가 자신 만의 특수 필드를 정의 할 수도 있음). 또한 지원되는 특정 필드 집합에 대해 모든 유형의 개체 를 프로그래밍 방식으로 요청할 수도 있습니다 TemporalAccessor. 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 

의 문제를 설명하는 HOUR_OF_DAY 필드가 없습니다 UnsupportedTemporalTypeException. 그리고 JSR-310- 패턴 심볼을 필드 에 매핑하는 것을 보면 심볼 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:)으로 구문 분석하고 구문 분석 된 중간 개체의 모든 필드 값을 허용하는지 여부를 결정합니다.


답변

나에게 적합한 수업은 ZonedDateTime시간과 시간대를 모두 포함하는 것이 었습니다 .

LocalDate시간 정보가 없으므로 UnsupportedTemporalTypeException: Unsupported field: HourOfDay.

사용할 수는 LocalDateTime있지만 표준 시간대 정보가 없으므로 미리 정의 된 포맷터 중 하나를 사용하여 액세스하려고하면 UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds.


답변