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


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.