Первые 8 байтов - это время в наносекциях, а не миллисекундах. Они тоже измеряются не с эпохи, а с полуночи. Часть даты хранится отдельно в последних 4 байтах как Юлианский номер дня .
Вот результат эксперимента, который я провел ранее, который может помочь. Я хранил '2000-01-01 12:34:56' как int96 и выгружал с паркетными инструментами:
$ parquet-tools dump hdfs://path/to/parquet/file | tail -n 1
value 1: R:0 D:1 V:117253024523396126668760320
Поскольку 117253024523396126668760320 = 0x60FD4B3229000059682500, 12 байтов равны 00 60 FD 4B 32 29 00 00 | 59 68 25 00, где | показывает границу между частями времени и даты.
00 60 FD 4B 32 29 00 00 - это временная часть. Нам нужно обратить байты обратно, потому что временная метка int96 использует обратный порядок байтов, поэтому мы получаем 0x000029324BFD6000 = 45296 * 10 ^ 9 наносекунд = 45296 секунд = 12 часов + 34 минуты + 56 секунд.
59 68 25 00 - это часть даты, если мы поменяем местами байты, мы получим 0x00256859 = 2451545 как номер юлианского дня, что соответствует 2000-01-01.