2017-04-04 264 views
1

我應該如何將Instant轉換爲具有小數以下亞秒精度的unix時間戳字符串?即時到Unix時間戳

測試用例是:

@Test 
public void toStringUnixTime() throws Exception { 
    assertEquals("0", TimeUtils.toStringUnixTime(Instant.EPOCH)); 
    assertEquals("1491327940.619", TimeUtils.toStringUnixTime(Instant.ofEpochMilli(1491327940619L))); 
    assertEquals("1491327940.000", TimeUtils.toStringUnixTime(Instant.ofEpochSecond(1491327940, 12345))); 
} 

建議這完全不是那麼回事(一直尾隨0,始終點)

public static String toStringUnixTime(Instant i){ 
    return i.getEpochSecond() + "." + String.format("%09d", i.getNano()); 
} 

回答

2

這很難,因爲java.time。* API故意選擇不提供轉換爲或Duration中的BigDecimal。基本原理是,將來某個時候,值類型將被添加到Java中,並且可能會有一種新的更有效的十進制類型。

Philipp目前的答案很好。我想補充,它可以被包裝在一個TemporalQuery如下:

public static TemporalQuery<String> UNIX_STRING = TimeUtils::toStringUnixTime; 

private static String toStringUnixTime(TemporalAccessor temporal) { 
    Instant i = Instant.from(temporal); 
    BigDecimal nanos = BigDecimal.valueOf(i.getNano(), 9); 
    BigDecimal seconds = BigDecimal.valueOf(i.getEpochSecond()); 
    BigDecimal total = seconds.add(nanos); 
    DecimalFormat df = new DecimalFormat("#.#########"); 
    return df.format(total); 
} 

現在我們有這個疑問,我們可以改變原來的代碼如下:

@Test 
public void toStringUnixTime() throws Exception { 
    assertEquals("0", Instant.EPOCH.query(UNIX_STRING)); 
    assertEquals("1491327940.619", Instant.ofEpochMilli(1491327940619L).query(UNIX_STRING)); 
    assertEquals("1491327940.000", Instant.ofEpochSecond(1491327940, 12345).query(UNIX_STRING)); 
} 

這樣使用查詢往往是一個比使用靜態工具類更好的編寫代碼的方式。該查詢也適用於OffsetDateTimeZonedDateTime

+0

我是否正確地認爲,在任何其他'TemporalAccessor'(例如LocalDate)上調用此函數將會失敗,但僅在運行時(編譯就好)?靜態方法不是給你更多的類型安全嗎? – Philipp

+0

它可以處理任何'Instant.from()'可以轉換的類型,例如'ZonedDateTime'和'OffsetDateTime'。但是,是的,它在其他情況下會失敗,比如'LocalDate'。取決於你認爲重要的事情。 – JodaStephen

+0

值類型發生了什麼?看着java 10 ...仍然沒有... – YoYo

1

一點,我想出了

public static String toStringUnixTime(Instant i){ 
    BigDecimal nanos = BigDecimal.valueOf(i.getNano(), 9); 
    BigDecimal seconds = BigDecimal.valueOf(i.getEpochSecond()); 
    BigDecimal total = seconds.add(nanos); 
    DecimalFormat df = new DecimalFormat("#.#########"); 
    return df.format(total); 
} 

這看起來不是最理想的,但是完成這項工作。