java - Spark Strutured Streaming konvertiert den Zeitstempel automatisch in die Ortszeit




scala apache-spark (2)

Ich habe meinen Zeitstempel in UTC und ISO8601, aber mit Structured Streaming wird er automatisch in die Ortszeit konvertiert. Gibt es eine Möglichkeit, diese Konvertierung zu stoppen? Ich möchte es in UTC haben.

Ich lese JSON-Daten von Kafka und analysiere sie dann mit der from_json Spark-Funktion.

Eingang:

{"Timestamp":"2015-01-01T00:00:06.222Z"}

Fließen:

SparkSession
  .builder()
  .master("local[*]")
  .appName("my-app")
  .getOrCreate()
  .readStream()
  .format("kafka")
  ... //some magic
  .writeStream()
  .format("console")
  .start()
  .awaitTermination();

Schema:

StructType schema = DataTypes.createStructType(new StructField[] {
        DataTypes.createStructField("Timestamp", DataTypes.TimestampType, true),});

Ausgabe:

+--------------------+
|           Timestamp|
+--------------------+
|2015-01-01 01:00:...|
|2015-01-01 01:00:...|
+--------------------+

Wie Sie sehen, hat sich die Stunde von selbst erhöht.

PS: Ich habe versucht, mit der from_utc_timestamp Spark-Funktion zu experimentieren, aber kein Glück.


Bei mir hat es geklappt:

spark.conf.set("spark.sql.session.timeZone", "UTC")

Der Spark SQL wird angewiesen, UTC als Standard-Zeitzone für Zeitstempel zu verwenden. Ich habe es in Spark-SQL verwendet, zum Beispiel:

select *, cast('2017-01-01 10:10:10' as timestamp) from someTable

Ich weiß, dass es in 2.0.1 nicht funktioniert. Funktioniert aber in Spark 2.2. Ich habe auch SQLTransformer und es hat funktioniert.

Ich bin mir jedoch nicht sicher, ob ich etwas streamen soll.


Hinweis :

Diese Antwort ist vor allem in Spark <2.2 nützlich. Für neuere Spark-Versionen siehe die Antwort von

Wir sollten jedoch beachten, dass spark.sql.session.timeZone heute (Spark 2.4.0) nicht user.timezone ( java.util.TimeZone.getDefault ) setzt. Das Setzen von `` spark.sql.session.timeZone` alleine kann zu einer ziemlich unangenehmen Situation führen, in der SQL- und Nicht-SQL-Komponenten unterschiedliche Zeitzoneneinstellungen verwenden.

Daher empfehle ich weiterhin, user.timezone explizit user.timezone , auch wenn spark.sql.session.timeZone ist.

TL; DR Leider geht Spark derzeit so mit Zeitstempeln um, und es gibt wirklich keine eingebaute Alternative, als direkt mit der Epochenzeit zu arbeiten, ohne Datums- / Zeit-Dienstprogramme zu verwenden.

Sie können eine aufschlussreiche Diskussion über die Spark-Entwicklerliste führen: SQL TIMESTAMP-Semantik vs. SPARK-18350

Die sauberste Lösung, die ich bisher gefunden habe, besteht darin, -Duser.timezone sowohl für den Treiber als auch für die -Duser.timezone auf UTC zu setzen. Zum Beispiel mit submit:

bin/spark-shell --conf "spark.driver.extraJavaOptions=-Duser.timezone=UTC" \
                --conf "spark.executor.extraJavaOptions=-Duser.timezone=UTC"

oder durch Anpassen der Konfigurationsdateien ( spark-defaults.conf ):

spark.driver.extraJavaOptions      -Duser.timezone=UTC
spark.executor.extraJavaOptions    -Duser.timezone=UTC




spark-structured-streaming