我已经使用以下命令启动了火花壳
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中的建议明确设置了时区,但得到的结果被我认为是错误的。
答案 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
函数。