通过python将parquet int96时间戳转换为datetime/date TL;博士
我想将一个int96值(如ACIE4NxJAAAKhSUA)转换成可读的时间戳格式(如2020-03-02 14:34:22或任何可以正常解释的格式)…我主要使用python,因此我希望构建一个进行此转换的函数。如果有另一个函数可以做相反的事情——甚至更好 背景 我正在使用拼花工具通过以下命令将原始拼花文件(具有snappy压缩)转换为原始JSON:通过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
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:这有一个功能,我可以探索,但我不确定如何深入
非常感谢您对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}