인스턴트를 문자열로 형식화


227

새로운 java 8 time-api와 패턴을 사용하여 Instant to String을 형식화하려고합니다.

Instant instant = ...;
String out = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(instant);

위의 코드를 사용하면 지원되지 않는 필드를 불평하는 예외가 발생합니다.

java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: YearOfEra
    at java.time.Instant.getLong(Instant.java:608)
    at java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:298)
    ...

답변:


310

시간대

포맷하려면 Instant시간대가 필요합니다. 시간대가 없으면 포맷터는 순간을 인간 날짜-시간 필드로 변환하는 방법을 모르므로 예외가 발생합니다.

시간대를 사용하여 포맷터에 직접 추가 할 수 있습니다 withZone().

DateTimeFormatter formatter =
    DateTimeFormatter.ofLocalizedDateTime( FormatStyle.SHORT )
                     .withLocale( Locale.UK )
                     .withZone( ZoneId.systemDefault() );

문자열 생성

이제 해당 포매터를 사용하여 Instant의 문자열 표현을 생성하십시오.

Instant instant = Instant.now();
String output = formatter.format( instant );

콘솔로 덤프하십시오.

System.out.println("formatter: " + formatter + " with zone: " + formatter.getZone() + " and Locale: " + formatter.getLocale() );
System.out.println("instant: " + instant );
System.out.println("output: " + output );

실행할 때.

formatter: Localized(SHORT,SHORT) with zone: US/Pacific and Locale: en_GB
instant: 2015-06-02T21:34:33.616Z
output: 02/06/15 14:34

50
감사합니다!! BTW 예외, 예를 들어 연도를 가리키는 "지원되지 않는 필드"는 눈에 띄게 둔합니다. 이 상황이 감지 되고 Instant에서 누락 된 영역 ID를 직접 가리키는 예외가 발생했을 수 있습니다.
davidbak

1
더 이상하게도 .withZone을 포함하고 (예 : .withZone (ZoneId.of ( "Z"))) LocalDateTime을 포맷하면 영역이 무시됩니다! .withZone ()이 포함되어 있으면 Instant와 LocalDateTime에 동일한 포매터를 사용할 수 있으며 후자에 표시된 시간에 영향을주지 않습니다.
Glenn

1
Instant에 GMT 인 TimeZone이 있다는 사실을 받아들이 기 어려운 이유는 무엇입니까?
Koray Tugay 2014 년

1
@KorayTugay "Instant is already GMT"라는 주석은 사실 일 수 있지만 시간대 를 지정하지 않고 Instant 포맷하면 작동하지 않기 때문에 예외 추적이 발생하면 도움 이되지 않습니다. 포맷터가 GMT로 기본 설정되어 있으면 좋았을 것입니다.
Ti Strga

이제 이것은 다음과 같은 yyyy-MM-dd hh:mm:ss형식을 제공 합니다.DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss").withZone(ZoneId.of("Europe/Paris"));
WesternGun

39
public static void main(String[] args) {

    DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
            .withZone(ZoneId.systemDefault());

    System.out.println(DATE_TIME_FORMATTER.format(new Date().toInstant()));

}

3
이 코드는 질문에 대답 할 수 있지만 문제를 해결하는 방법이유 에 대한 추가 컨텍스트를 제공 하면 답변의 장기적인 가치가 향상됩니다.
Alexander

1
이 코드 스 니펫은 문제를 해결할 수 있지만 설명을 포함하면 게시물의 품질을 향상시키는 데 실제로 도움이됩니다. 앞으로 독자에게 질문에 대한 답변을 제공하고 있으며 해당 사람들이 코드 제안의 이유를 모를 수도 있습니다.
Rosário Pereira Fernandes

23
DateTimeFormatter.ISO_INSTANT.format(Instant.now())

이렇게하면 UTC로 변환하지 않아도됩니다. 그러나 일부 다른 언어의 시간 프레임 워크는 밀리 초를 지원하지 않을 수 있으므로 수행해야합니다.

DateTimeFormatter.ISO_INSTANT.format(Instant.now().truncatedTo(ChronoUnit.SECONDS))

"다른 언어의 시간 프레임 워크"는 무엇을 의미합니까? ISO_INSTANT.format ()이 자동으로 몇 초로 잘리나요?
Guangtong Shen

일부 프레임 워크는 전체 ISO 규칙을 따르지 않고 입력 문자열의 일부로 밀리 초가 걸리면 중단되기 때문에 시간이 초까지 올라갈 것으로 예상합니다.
Archimedes Trajano

21

Instant클래스에는 영역 정보가 포함되어 있지 않으며 UNIX epoch에서 밀리 초 단위 (예 : UTC에서 1070 년 1 월 1 일) 만 타임 스탬프를 저장합니다. 따라서 날짜는 항상 구체적인 시간대로 인쇄되므로 포맷터에서 날짜를 인쇄 할 수 없습니다. 시간대를 포맷터로 설정해야하며 다음과 같이 모두 괜찮습니다.

Instant instant = Instant.ofEpochMilli(92554380000L);
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withLocale(Locale.UK).withZone(ZoneOffset.UTC);
assert formatter.format(instant).equals("07/12/72 05:33");
assert instant.toString().equals("1972-12-07T05:33:00Z");

4

또는 패턴에서 작성된 포맷터를 계속 사용하려면 Instant 대신 LocalDateTime을 사용할 수 있습니다.

LocalDateTime datetime = LocalDateTime.now();
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(datetime)

4

인스턴트는 이미 UTC이며 기본 날짜 형식은 yyyy-MM-dd 입니다. 당신이 그것에 만족하고 시간대 나 형식을 엉망으로 만들고 싶지 않다면, 당신은 또한 toString()그것을 할 수 있습니다 :

Instant instant = Instant.now();
instant.toString()
output: 2020-02-06T18:01:55.648475Z


T와 Z를 원하지 않습니까? (Z는이 날짜가 UTC임을 나타냅니다. Z는 "Zulu"(일명 UTC)를 나타냅니다.

instant.toString().replaceAll("[TZ]", " ")
output: 2020-02-06 18:01:55.663763


나노초 대신 밀리 초를 원하십니까? (그래서 SQL 쿼리에 넣을 수 있습니다) :

instant.truncatedTo(ChronoUnit.MILLIS).toString().replaceAll("[TZ]", " ")
output: 2020-02-06 18:01:55.664

기타


-3
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy MM dd");
String text = date.toString(formatter);
LocalDate date = LocalDate.parse(text, formatter);

이것이 도움이 될 수 있다고 생각합니다. 즉시 대신 일종의 localdate 변형을 사용해야 할 수도 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.