web-dev-qa-db-ja.com

unix_timestamp()は、Apache SparkでUNIX時間をミリ秒単位で返すことができますか?

タイムスタンプフィールドからミリ秒(13桁)でUNIX時間を取得しようとしていますが、現在は秒(10桁)で返されます。

scala> var df = Seq("2017-01-18 11:00:00.000", "2017-01-18 11:00:00.123", "2017-01-18 11:00:00.882", "2017-01-18 11:00:02.432").toDF()
df: org.Apache.spark.sql.DataFrame = [value: string]

scala> df = df.selectExpr("value timeString", "cast(value as timestamp) time")
df: org.Apache.spark.sql.DataFrame = [timeString: string, time: timestamp]


scala> df = df.withColumn("unix_time", unix_timestamp(df("time")))
df: org.Apache.spark.sql.DataFrame = [timeString: string, time: timestamp ... 1 more field]

scala> df.take(4)
res63: Array[org.Apache.spark.sql.Row] = Array(
[2017-01-18 11:00:00.000,2017-01-18 11:00:00.0,1484758800], 
[2017-01-18 11:00:00.123,2017-01-18 11:00:00.123,1484758800], 
[2017-01-18 11:00:00.882,2017-01-18 11:00:00.882,1484758800], 
[2017-01-18 11:00:02.432,2017-01-18 11:00:02.432,1484758802])

たとえ 2017-01-18 11:00:00.123および2017-01-18 11:00:00.000は異なり、同じUNIX時間を取り戻します1484758800

何が欠けていますか?

15
van_d39

unix_timestamp() UNIXタイムスタンプを秒単位で返します。

タイムスタンプの最後の3桁は、ミリ秒文字列の最後の3桁と同じです(1.999sec = 1999 milliseconds)なので、タイムスタンプ文字列の最後の3桁を取り、ミリ秒文字列の最後に追加します。

2

Dao Thiの回答 で提案されたアプローチの実装

import pyspark.sql.functions as F
df = spark.createDataFrame([('22-Jul-2018 04:21:18.792 UTC', ),('23-Jul-2018 04:21:25.888 UTC',)], ['TIME'])
df.show(2,False)
df.printSchema()

出力:

+----------------------------+
|TIME                        |
+----------------------------+
|22-Jul-2018 04:21:18.792 UTC|
|23-Jul-2018 04:21:25.888 UTC|
+----------------------------+
root
|-- TIME: string (nullable = true)

string time-format(ミリ秒を含む)をunix_timestamp(double)に変換します。サブストリングメソッドを使用して文字列からミリ秒を抽出し(start_position = -7、length_of_substring = 3)、ミリ秒をunix_timestampに個別に追加します。 (追加するためにサブストリングからフロートにキャスト)

df1 = df.withColumn("unix_timestamp",F.unix_timestamp(df.TIME,'dd-MMM-yyyy HH:mm:ss.SSS z') + F.substring(df.TIME,-7,3).cast('float')/1000)

Sparkでunix_timestamp(double)timestamp datatypeに変換します。

df2 = df1.withColumn("TimestampType",F.to_timestamp(df1["unix_timestamp"]))
df2.show(n=2,truncate=False)

これにより、次の出力が得られます

+----------------------------+----------------+-----------------------+
|TIME                        |unix_timestamp  |TimestampType          |
+----------------------------+----------------+-----------------------+
|22-Jul-2018 04:21:18.792 UTC|1.532233278792E9|2018-07-22 04:21:18.792|
|23-Jul-2018 04:21:25.888 UTC|1.532319685888E9|2018-07-23 04:21:25.888|
+----------------------------+----------------+-----------------------+

スキーマの確認:

df2.printSchema()


root
 |-- TIME: string (nullable = true)
 |-- unix_timestamp: double (nullable = true)
 |-- TimestampType: timestamp (nullable = true)
1
Sangram Gaikwad

ミリ秒は小数部のタイムスタンプ形式で非表示

これを試して:

df = df.withColumn("time_in_milliseconds", col("time").cast("double"))

1484758800.792のようなものが得られます。792はミリ秒です。

少なくとも私にとってはうまくいきます(Scala、Spark、Hive)