如何在Java中将Parquet文件的16位INT96时间戳字符串转为可读格式
解决方案
你遇到的16位字符串是Base64编码的Parquet int96时间戳(int96为12字节,Base64编码后刚好16字符)。以下是Java中完整的转换步骤:
核心步骤
- 将Base64字符串解码为12字节的int96原始数组
- 从数组中解析出Parquet int96的两个组成部分:当天纳秒数(8字节,小端序)、Julian日数(4字节,小端序)
- 将Julian日数转换为公历日期,结合纳秒数生成完整时间戳
- 格式化为目标字符串格式
完整代码示例
import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.JulianFields; import java.util.Base64; public class ParquetInt96TimestampConverter { public static String convertInt96Base64ToReadable(String base64Timestamp) { // 1. 解码Base64为12字节数组 byte[] int96Bytes = Base64.getDecoder().decode(base64Timestamp); if (int96Bytes.length != 12) { throw new IllegalArgumentException("Invalid int96 timestamp: must be 12 bytes after Base64 decode"); } // 2. 解析小端序的纳秒数和Julian日数 ByteBuffer buffer = ByteBuffer.wrap(int96Bytes).order(ByteOrder.LITTLE_ENDIAN); long nanosOfDay = buffer.getLong(); int julianDay = buffer.getInt(); // 3. 转换为LocalDateTime LocalDate date = LocalDate.ofEpochDay(0).with(JulianFields.JULIAN_DAY, julianDay); LocalDateTime dateTime = date.atStartOfDay().plusNanos(nanosOfDay); // 4. 格式化为目标格式 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); return dateTime.format(formatter); } public static void main(String[] args) { String exampleBase64 = "ACrpbPIZAABOfyUA"; String readable = convertInt96Base64ToReadable(exampleBase64); System.out.println(readable); // 输出类似 2017-10-24T03:01:50 } }
关键说明
- 字节序问题:Parquet的int96时间戳采用小端序(Little-Endian)存储,必须用
ByteBuffer.order(ByteOrder.LITTLE_ENDIAN)解析,否则数值会完全错误。 - Julian日数转换:Java 8+的
JulianFields.JULIAN_DAY直接对应Parquet int96使用的Julian纪元起点(公元前4713年1月1日),无需额外偏移计算。 - 纳秒范围:Parquet规范保证
nanosOfDay在0到86399999999999之间(即一天内的纳秒数),无需处理跨天情况。
内容的提问来源于stack exchange,提问作者etcxuyr
相关产品推荐
相关产品推荐

