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
转换为 Date
的 discussion。
基于此,我创建了以下代码:
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
我不喜欢手动将您的字节数组转换为 int
和 long
,但我不知道 Parquet 是否足以使用那里可能可用的转换.如果可以,请使用它们。
我们使用哪个 LocalDate
作为起点并不重要,因为无论如何我们都会将其更改为正确的儒略日,所以我选择 LocalDate.MIN
只是为了选择一个。
我阅读文档的方式,Julian days 总是在本地时区,也就是说,不理解时区,它们总是从中午(而不是午夜)开始。
读取镶木地板文件(使用 Scala)时,我将时间戳字段读回为:
Int96Value{Binary{12 constant bytes, [0, 44, 84, 119, 54, 49, 0, 0, -62, -127, 37, 0]}}
如何将其转换为日期字符串?
我为你做了一些调查。 Int96
格式非常具体,似乎已被弃用。
这是关于将 Int96
转换为 Date
的 discussion。
基于此,我创建了以下代码:
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
我不喜欢手动将您的字节数组转换为 int
和 long
,但我不知道 Parquet 是否足以使用那里可能可用的转换.如果可以,请使用它们。
我们使用哪个 LocalDate
作为起点并不重要,因为无论如何我们都会将其更改为正确的儒略日,所以我选择 LocalDate.MIN
只是为了选择一个。
我阅读文档的方式,Julian days 总是在本地时区,也就是说,不理解时区,它们总是从中午(而不是午夜)开始。