防止火花改变火花壳中的时间戳

时间:2019-10-09 19:16:38

标签: apache-spark apache-spark-sql timezone user-defined-functions

我已经使用以下命令启动了火花壳

spark-shell --conf spark.sql.session.timeZone=utc

在下面的示例中运行时,结果是在utc_shifted列中移动的时间戳。它不包含UDF的所需输出,但包含其他内容。具体来说:输入为UTC,然后火花再次将其转换。如何解决此问题?

+-----------------+-----------------------+-------------------+
|value            |utc_shifted            |fitting            |
+-----------------+-----------------------+-------------------+
|20191009145901202|2019-10-09 12:59:01.202|2019-10-09 14:59:01|
|20191009145514816|2019-10-09 12:55:14.816|2019-10-09 14:55:14|
+-----------------+-----------------------+-------------------+

似乎不通过默认的时区参数可以解决此问题,但是我不确定执行器之一是否可以使用不同/错误的时区,但我仍然可以得到正确的结果。所以我更喜欢设置它。 为什么这对spark自己的时间戳解析没有影响?如何为我的UDF获得类似的行为?

可复制的示例:

val input = Seq("20191009145901202", "20191009145514816").toDF

import scala.util.{Failure, Success, Try}
import java.sql.Timestamp
import java.text.SimpleDateFormat
import org.apache.spark.sql.DataFrame

def parseTimestampWithMillis(
      timestampColumnInput: String,
      timestampColumnOutput: String,
      formatString: String)(df: DataFrame): DataFrame = {
    def getTimestamp(s: String): Option[Timestamp] = {
      if (s.isEmpty) {
        None
      } else {
        val format = new SimpleDateFormat(formatString)
        Try(new Timestamp(format.parse(s).getTime)) match {
          case Success(t) => {
            println(s"input: ${s}, output: ${t}")
            Some(t)
          }
          case Failure(_) => None
        }
      }
    }

    val getTimestampUDF = udf(getTimestamp _)
    df.withColumn(
      timestampColumnOutput, getTimestampUDF(col(timestampColumnInput)))
  }


input.transform(parseTimestampWithMillis("value", "utc_shifted", "yyyyMMddHHmmssSSS")).withColumn("fitting", to_timestamp(col("value"), "yyyyMMddHHmmssSSS")).show(false)

+-----------------+-----------------------+-------------------+
|value            |utc_shifted            |fitting            |
+-----------------+-----------------------+-------------------+
|20191009145901202|2019-10-09 12:59:01.202|2019-10-09 14:59:01|
|20191009145514816|2019-10-09 12:55:14.816|2019-10-09 14:55:14|
+-----------------+-----------------------+-------------------+

实际上,此设置不仅会影响显示,还会影响写入文件时的输出。

编辑

基本上,我按照Spark Strutured Streaming automatically converts timestamp to local time中的建议明确设置了时区,但得到的结果被我认为是错误的。

1 个答案:

答案 0 :(得分:0)

spark-shell --conf spark.sql.session.timeZone=UTC --conf "spark.driver.extraJavaOptions=-Duser.timezone=UTC" --conf "spark.executor.extraJavaOptions=-Duser.timezone=UTC"

似乎给我想要的结果。

但这并不能解释为什么这仅适用于我的UDF而不适用于触发内部to_timestamp函数。