即时到Unix时间戳

时间:2017-04-04 18:24:31

标签: java java-time

如何将Instant转换为带小数的unix时间戳字符串,以获得亚秒级精度?

测试用例是:

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

提案并不完全有效(总是落后0,总是点)

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

2 个答案:

答案 0 :(得分:2)

这很难,因为java.time。* API故意选择不在BigDecimalInstant中提供转换为Duration。理由是,在将来的某个时刻,值类型将被添加到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.000012345", Instant.ofEpochSecond(1491327940, 12345).query(UNIX_STRING));
}

使用这样的查询通常是编写代码比使用静态实用程序类更简洁的方法。该查询还适用于OffsetDateTimeZonedDateTime

答案 1 :(得分: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);
}

这似乎不是最理想的,但可以胜任。