Int96Value 到日期字符串

Int96Value to Date string

读取镶木地板文件(使用 Scala)时,我将时间戳字段读回为:

Int96Value{Binary{12 constant bytes, [0, 44, 84, 119, 54, 49, 0, 0, -62, -127, 37, 0]}}

如何将其转换为日期字符串?

我为你做了一些调查。 Int96 格式非常具体,似乎已被弃用。

这是关于将 Int96 转换为 Datediscussion

基于此,我创建了以下代码:

  def main(args: Array[String]): Unit = {
    import java.util.Date
    import org.apache.parquet.example.data.simple.{Int96Value, NanoTime}
    import org.apache.parquet.io.api.Binary

    val int96Value = new Int96Value(Binary.fromConstantByteArray(Array(0, 44, 84, 119, 54, 49, 0, 0, -62, -127, 37, 0)))
    val nanoTime = NanoTime.fromInt96(int96Value)
    val nanosecondsSinceUnixEpoch = (nanoTime.getJulianDay - 2440588) * (86400 * 1000 * 1000 * 1000) + nanoTime.getTimeOfDayNanos
    val date = new Date(nanosecondsSinceUnixEpoch / (1000 * 1000))
    println(date)
  }

但是,它打印 Sun Sep 27 17:05:55 CEST 2093。我不确定这是否是您预期的日期。

编辑: 按照建议使用 Instance

val nanosInSecond = 1000 * 1000 * 1000;
val instant = Instant.ofEpochSecond(nanosecondsSinceUnixEpoch / nanosInSecond, nanosecondsSinceUnixEpoch % nanosInSecond)
println(instant) // prints 2093-09-27T15:05:55.933865216Z

java.time 支持儒略日。

感谢 ygor 进行研究并找出如何解释数组的 12 个字节。

    byte[] int96Bytes = { 0, 44, 84, 119, 54, 49, 0, 0, -62, -127, 37, 0 };

    // Find Julian day
    int julianDay = 0;
    int index = int96Bytes.length;
    while (index > 8) {
        index--;
        julianDay <<= 8;
        julianDay += int96Bytes[index] & 0xFF;
    }

    // Find nanos since midday (since Julian days start at midday)
    long nanos = 0;
    // Continue from the index we got to
    while (index > 0) {
        index--;
        nanos <<= 8;
        nanos += int96Bytes[index] & 0xFF;
    }

    LocalDateTime timestamp = LocalDate.MIN
            .with(JulianFields.JULIAN_DAY, julianDay)
            .atTime(LocalTime.NOON)
            .plusNanos(nanos);
    System.out.println("Timestamp: " + timestamp);

这会打印:

Timestamp: 2017-10-24T03:01:50

我不喜欢手动将您的字节数组转换为 intlong,但我不知道 Parquet 是否足以使用那里可能可用的转换.如果可以,请使用它们。

我们使用哪个 LocalDate 作为起点并不重要,因为无论如何我们都会将其更改为正确的儒略日,所以我选择 LocalDate.MIN 只是为了选择一个。

我阅读文档的方式,Julian days 总是在本地时区,也就是说,不理解时区,它们总是从中午(而不是午夜)开始。

Link: Documentation of JulianFields in java.time