2016-06-26 6 views
7

datetime 관리와 관련된 다양한 코드를 Java 8 java.time 네임 스페이스로 정리하려고합니다. 지금은 의 작은 문제 (Instant)가 있습니다. DateTimeFormatter.ISO_INSTANT 포맷터는 0이 아닌 경우에만 밀리 초를 표시합니다.java.time.DateTimeFormatter : 항상 밀리 초를 렌더링하는 ISO_INSTANT가 필요합니다.

신기원은 1970-01-01T00:00:00.000Z 대신에 1970-01-01T00:00:00Z으로 렌더링됩니다.

나는이 문제를 설명하기 위해 단위 테스트를 실시했으며 서로 비교할 최종 날짜를 어떻게 필요로 하는지를 설명했습니다.

@Test 
public void java8Date() { 
    DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT; 
    String epoch, almostEpoch, afterEpoch; 

    { // before epoch 
     java.time.Instant instant = java.time.Instant.ofEpochMilli(-1); 
     almostEpoch = formatter.format(instant); 
     assertEquals("1969-12-31T23:59:59.999Z", almostEpoch); 
    } 

    { // epoch 
     java.time.Instant instant = java.time.Instant.ofEpochMilli(0); 
     epoch = formatter.format(instant); 
     // This fails, I get 1970-01-01T00:00:00Z instead 
     assertEquals("1970-01-01T00:00:00.000Z", epoch); 
    } 

    { // after epoch 
     java.time.Instant instant = java.time.Instant.ofEpochMilli(1); 
     afterEpoch = formatter.format(instant); 
     assertEquals("1970-01-01T00:00:00.001Z", afterEpoch); 
    } 

    // The end game is to make sure this rule is respected (this is how we order things in dynamo): 
    assertTrue(epoch.compareTo(almostEpoch) > 0); 
    assertTrue(afterEpoch.compareTo(epoch) > 0); // <-- This assert would also fail if the second assert fails 

    { // to confirm we're not showing nanos 
     assertEquals("1970-01-01T00:00:00.000Z", formatter.format(Instant.EPOCH.plusNanos(1))); 
     assertEquals("1970-01-01T00:00:00.001Z", formatter.format(Instant.EPOCH.plusNanos(1000000))); 
    } 
} 
+3

기본 형식은 0과 다른 경우에만 나노초도 렌더링합니다. 밀리 세컨드 (그리고 결코 나노초가 아닌)를 원할 경우,'DateTimeFormatter formatter = DateTimeFormatter.ofPattern ("yyyy-MM-dd'T'HH : mm : ss.SSSX")와 같은 커스텀 포맷터를 사용하면 안된다 .Zone (ZoneId . ("UTC")); – mihi

+0

'Instant :: toString()'에 사용 된 포맷터에 최대한 가까이 있기를 원했습니다. 어쩌면 나는 실제로 문자열 패턴을 사용해야 만했을 것입니다. – Florent

답변

7

OK, 나는 소스 코드를 보니 꽤 간단합니다 :

DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendInstant(3).toFormatter(); 

나는 그것이 모든 시나리오 작동 희망, 그리고 다른 사람을 도울 수 있습니다. 더 나은/깨끗한 답변을 추가하는 것을 주저하지 마십시오. InstantPrinterParser 서명이

public DateTimeFormatterBuilder appendInstant() { 
    appendInternal(new InstantPrinterParser(-2)); 
    return this; 
} 

그리고 생성자 :로

public static final DateTimeFormatter ISO_INSTANT; 
static { 
    ISO_INSTANT = new DateTimeFormatterBuilder() 
      .parseCaseInsensitive() 
      .appendInstant() 
      .toFormatter(ResolverStyle.STRICT, null); 
} 

그리고 DateTimeFormatterBuilder::appendInstant 선언 : 그것은 in the JDK's code, 출처

그냥

ISO_INSTANT는 다음과 같이 정의, 설명하기 :

InstantPrinterParser(int fractionalDigits) 
+1

검사 된 소스 코드에 링크하면 좋을 것입니다. –

+0

그래서 우리는 이것을 나노 미터가 아닌 ms만을 포함하도록 어떻게 변경합니까? – user1172490

+0

@BasilBourque 소스 코드 – Florent

0

accepted Answer by Florent이 정확하고 좋습니다.

설명을 추가하고 싶습니다.

언급 된 포맷터 DateTimeFormatter.ISO_INSTANTInstant 클래스의 경우에만 기본값입니다. OffsetDateTimeZonedDateTime과 같은 다른 클래스는 기본적으로 다른 포맷터를 사용할 수 있습니다.

java.time 클래스는 최대 nanosecond의 해상도를 제공하며, milliseconds보다 훨씬 세분화되어 있습니다. 이는 단순히 3 자리가 아닌 소수점 이하 9 자리를 의미합니다.

DateTimeFormatter.ISO_INSTANT의 동작은 소수 자릿수에 따라 다릅니다. 의사가 말한 것처럼 (강조 표시) :

서식을 지정할 때 두 번째 분이 항상 출력됩니다. nano-of-second 은 필요에 따라 0, 3, 6 또는 9 자리 숫자을 출력합니다.

2011-12-03T10 :

는 그래서 Instant 객체 내에 포함 된 데이터의 값에 따라, 이들 출력 중 하나를 볼 수 15 : 30Z

2011-12-03T10을 15 : 30.100Z

2011-12-03T10 : 15 : 30120Z

2011-12-03T10 : 15 : 30.123Z

2011-12-03T10 : 15 : 30.123400Z

2011-12-03T10 : 15 : 30.123456Z

2011-12 -03T10 : 15 : 30.123456780Z

2011-12-03T10 : 15 : 30.123456789Z

Instant 클래스는 일을 의미한다 java.time의 기본이되는 빌드 블록 데이터 전달, 데이터 저장 및 데이터 교환에 자주 사용하십시오. 사용자에게 표시 할 데이터의 문자열 표현을 생성 할 때는 OffsetDateTime 또는 ZonedDateTime을 사용하십시오.

관련 문제