通过python将parquet int96时间戳转换为datetime/date TL;博士

通过python将parquet int96时间戳转换为datetime/date TL;博士,python,apache-spark,casting,timestamp,parquet,Python,Apache Spark,Casting,Timestamp,Parquet,我想将一个int96值(如ACIE4NxJAAAKhSUA)转换成可读的时间戳格式(如2020-03-02 14:34:22或任何可以正常解释的格式)…我主要使用python,因此我希望构建一个进行此转换的函数。如果有另一个函数可以做相反的事情——甚至更好 背景 我正在使用拼花工具通过以下命令将原始拼花文件(具有snappy压缩)转换为原始JSON: C:\Research> java -jar parquet-tools-1.8.2.jar cat --json original-fil

我想将一个int96值(如ACIE4NxJAAAKhSUA)转换成可读的时间戳格式(如2020-03-02 14:34:22或任何可以正常解释的格式)…我主要使用python,因此我希望构建一个进行此转换的函数。如果有另一个函数可以做相反的事情——甚至更好

背景 我正在使用拼花工具通过以下命令将原始拼花文件(具有snappy压缩)转换为原始JSON:

C:\Research> java -jar parquet-tools-1.8.2.jar cat --json original-file.snappy.parquet > parquet-output.json
在JSON中,我将这些值视为时间戳:

{... "_id":"101836","timestamp":"ACIE4NxJAAAKhSUA"}
我已经确定“ACIE4NxJAAAKhSUA”的时间戳值实际上是int96(读取拼花地板文件的模式也证实了这一点)

message spark_schema {
 ...(stuff)...
  optional binary _id (UTF8);
  optional int96 timestamp;
}
我想这也被称为黑斑羚时间戳(至少我收集到了这个)

进一步的问题研究 我一直在到处搜索关于如何“读取”int96值(到python中——我想用那种语言保存它,因为我最熟悉它)并输出时间戳的函数或信息——我什么也没找到

这里有一篇我已经研究过的文章(与本主题相关):

  • SO中的拼花匠研究
  • 在SO NOTE中通过戈兰铸造int96:这有一个功能,我可以探索,但我不确定如何深入
关于折旧的int96时间戳 请不要要求我停止在拼花地板文件中使用旧的/已折旧的时间戳格式,通过我迄今为止所做的研究,我很清楚这一点。我是文件/数据的接收者——我无法更改创建时使用的格式

如果有另一种方法来控制初始JSON输出以提供“非int96”值,我也会对此感兴趣


非常感谢您对so社区的帮助!

拼花工具将无法将格式类型从INT96更改为INT64。您在json输出中看到的是存储在INT96 TimestampType中的时间戳的字符串表示形式。您需要spark使用INT64 TimestampType中的时间戳重新编写此拼花,然后使用json输出wi我将生成一个时间戳(按照您想要的格式)

您需要在Spark中设置特定的配置-

spark-shell --conf spark.sql.parquet.outputTimestampType=TIMESTAMP_MICROS

2020-03-16 11:37:50 WARN  NativeCodeLoader:62 - Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
Setting default log level to "WARN".
To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).
Spark context Web UI available at http://192.168.0.20:4040
Spark context available as 'sc' (master = local[*], app id = local-1584383875924).
Spark session available as 'spark'.
Welcome to
      ____              __
     / __/__  ___ _____/ /__
    _\ \/ _ \/ _ `/ __/  '_/
   /___/ .__/\_,_/_/ /_/\_\   version 2.4.0
      /_/
Using Scala version 2.11.12 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_91)
Type in expressions to have them evaluated.
Type :help for more information.

val sourceDf = spark.read.parquet("original-file.snappy.parquet")
2020-03-16 11:38:31 WARN  Utils:66 - Truncated the string representation of a plan since it was too large. This behavior can be adjusted by setting 'spark.debug.maxToStringFields' in SparkEnv.conf.
sourceDf: org.apache.spark.sql.DataFrame = [application: struct<name: string, upgrades: struct<value: double> ... 3 more fields>, timestamp: timestamp ... 16 more fields]

scala> sourceDf.repartition(1).write.parquet("Downloads/output")
json转储提供-

parquet-tools cat --json Downloads/output/part-00000-edba239b-e696-4b4e-8fd3-c7cca9eea6bf-c000.snappy.parquet

{..."_id":"101836", "timestamp":1583973827000000}

记录的时间戳以纳秒为单位。希望这有帮助!

道格,这段代码来自arrow/cpp/src/parquet/types。h显示了Int96时间戳是如何在内部存储的:

constexpr int64_t Kjuliatonounixepochdays=int64_C(2440588);
constexpr int64_t kSecondsPerDay=int64_C(60*60*24);
constexpr int64_t kmillessecondsPerday=kSecondsPerDay*int64_C(1000);
constexpr int64_t kMicrosecondsPerDay=kmillesecondsperday*int64_C(1000);
constexpr int64_t kNanosecondsPerDay=kMicrosecondsPerDay*int64_C(1000);
手动对齐的结构(1)Int96{uint32_t值[3];};
结构端(Int96,12);
静态内联无效Int96SetNanoSeconds(拼花地板::Int96&i96,int64_t nanoseconds){
标准::memcpy(&i96.value,&nanoseconds,sizeof(nanoseconds));
}
静态内联int64_t Int96GetNanoSeconds(常数拼花::Int96和i96){
//我们在无符号域中进行计算以避免无符号行为
//溢出。
自新纪元起64天=
i96.值[2]-静态施法(kJulianToUnixEpochDays);
uint64_t纳秒=0;
memcpy(&纳秒,&i96.value,sizeof(uint64_t));
返回静态施法(自纪元起天数*纳秒秒秒+纳秒);
}

非常感谢您——这非常有帮助!这项工作与您提到的完全一样。我很好奇[在python/一些拼花python库中]是否有一个函数来解释字符串表示(在原始JSON中看到了什么)并且知道如何将其返回到INT64或timestamp_micros epoch…再次感谢!Doug,arrow/cpp/src/parquet/types.h中的代码可能会有帮助:
parquet-tools cat --json Downloads/output/part-00000-edba239b-e696-4b4e-8fd3-c7cca9eea6bf-c000.snappy.parquet

{..."_id":"101836", "timestamp":1583973827000000}