J'essaie d'obtenir l'heure Unix d'un champ d'horodatage en millisecondes (13 chiffres), mais elle est actuellement renvoyée en secondes (10 chiffres).
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])
Même si 2017-01-18 11:00:00.123
et 2017-01-18 11:00:00.000
sont différents, je reçois le même retour unix 1484758800
Qu'est-ce que je rate?
unix_timestamp()
renvoie l'horodatage Unix en secondes.
Les 3 derniers chiffres des horodatages sont identiques aux 3 derniers chiffres de la chaîne en millisecondes (1.999sec = 1999 milliseconds
), il suffit donc de prendre les 3 derniers chiffres de la chaîne en horodatage et de les ajouter à la fin de la chaîne en millisecondes.
Mise en œuvre de l'approche suggérée dans Réponse de 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()
Sortie:
+----------------------------+
|TIME |
+----------------------------+
|22-Jul-2018 04:21:18.792 UTC|
|23-Jul-2018 04:21:25.888 UTC|
+----------------------------+
root
|-- TIME: string (nullable = true)
Conversion de string time-format (en millisecondes) en unix_timestamp (double) . Extraction de millisecondes d'une chaîne à l'aide de la méthode de sous-chaîne (start_position = -7, length_of_substring = 3) et ajout de millisecondes séparément à unix_timestamp. (Cast sur sous-chaîne pour flotter pour l'ajout)
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)
Conversion de unix_timestamp (double) en type de données timestamp dans Spark.
df2 = df1.withColumn("TimestampType",F.to_timestamp(df1["unix_timestamp"]))
df2.show(n=2,truncate=False)
Cela vous donnera la sortie suivante
+----------------------------+----------------+-----------------------+
|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|
+----------------------------+----------------+-----------------------+
Vérification du schéma:
df2.printSchema()
root
|-- TIME: string (nullable = true)
|-- unix_timestamp: double (nullable = true)
|-- TimestampType: timestamp (nullable = true)