2017-04-04 214 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); 
} 

这看起来不是最理想的,但是完成这项工作。