【问题标题】:Why does spark (Python) gobble my milliseconds?为什么 spark (Python) 会吞噬我的毫秒数?
【发布时间】:2018-10-12 17:34:07
【问题描述】:

我有毫秒格式的时间戳,需要将它们从系统时间转换为 UTC。无论如何...在进行转换时,火花会吞噬我的毫秒数,并将它们显示为零。

简短示例:

from pyspark import Row
from pyspark import SparkContext
from pyspark.sql.functions import to_timestamp, date_format

spark = SparkContext.getOrCreate()

test = spark.createDataFrame([Row(timestamp = "2018-03-24 14:37:12,133")])
test_2 = test.withColumn('timestamp_2', to_timestamp('timestamp', 'yyyy-MM-dd HH:mm:ss,SSS'))
test_3 = test_2.withColumn('timestamp_3', date_format('timestamp_2', 'yyyy-MM-dd HH:mm:ss,SSS'))
test_3.write.option('header', True).csv('something')

这将导致:

timestamp,timestamp_2,timestamp_3
"2018-03-24 14:37:12,133",2018-03-24T14:37:12.000+01:00,"2018-03-24 14:37:12,000"

我能以某种方式保留毫秒吗?

我使用的是 python 3.6.4 和 spark 版本 2.3.2。

【问题讨论】:

  • 显然这只是to_timestamp 所做的事情。我不知道他们为什么要这样设计,Python docsScala docs 都没有意义; Python 文档说它正在转换为 DateType,这比你看到的更没有意义,而 Scala 文档在 to_timestamp 的描述中奇怪地破坏了英语。
  • Scala 文档至少说“以秒为单位”,但没有说明为什么 TimestampType 具有比这更高的分辨率时会以秒为单位。他们也说“Unix时间戳”,但是当输出格式是TimestampType而不是Unix时间戳时,这也没有多大意义。
  • 好的。您是否知道一个不太难看的解决方案,以便我可以将其转换为时间戳? :)
  • 你的 SQL 后端是什么?这一定是它的时间戳类型或其他东西的限制。

标签: python apache-spark pyspark


【解决方案1】:

设法让它现在工作。由于 spark 似乎无法在毫秒内正常工作,我定义了一个使用 pytzdatetime 包的 UDF,以便将字符串转换为 datetime,更改时区,然后再次打印字符串。

import pytz
from datetime import datetime
from pyspark.sql.functions import udf
from pyspark.sql.types import StringType
from pyspark import Row
from pyspark import SparkContext

spark = SparkContext.getOrCreate()

def convert_to_utc(timestamp):
    local = pytz.timezone("Arctic/Longyearbyen")
    naive = datetime.strptime(timestamp, '%Y-%m-%d %H:%M:%S,%f')
    local_dt = local.localize(naive, is_dst=None)
    utc_dt = local_dt.astimezone(pytz.utc)
    return utc_dt.strftime('%Y-%m-%d %H:%M:%S,%f')[:-3]

convert_to_utc_udf = udf(lambda timestamp: convert_to_utc(timestamp), StringType())

test = spark.createDataFrame([Row(timestamp = "2018-03-24 14:37:12,133")])
test_2 = test.withColumn('timestamp_2', convert_to_utc_udf('timestamp'))
test_2.write.option('header', True).csv('something')

#Output:
#timestamp,timestamp_2
#"2018-03-24 14:37:12,133","2018-03-24 13:37:12,133"

灵感来源:

How to convert a string column with milliseconds to a timestamp with milliseconds in Spark 2.1 using Scala?

还有:

How do I convert local time to UTC in Python?

【讨论】:

  • 我看不出"2018-03-24 14:37:12,133",2018-03-24T14:37:12.000+01:00,"2018-03-24 14:37:12,000"和以前有什么不同。
  • 您能否解释一下您所做的更改以及具体使其起作用的原因,并删除代码中不相关的部分?
  • 您好伊万,感谢您的反馈。我将删除答案中不必要的部分。但是请注意,结果表的最后一列是不同的。 "2018-03-24 14:37:12,133",2018-03-24T14:37:12.000+01:00,"2018-03-24 14:37:12,000","2018-03-24 13:37:12,133"
  • 您不会以这种方式参与pyspark.sql.types.TimestampType - 您的结果数据只有字符串。所以问题本身仍然没有答案。
  • 没错。如前所述,目标是我想将时间戳从本地时间转换为 UTC 时间,并希望保持毫秒。
猜你喜欢
  • 2017-10-24
  • 2012-05-15
  • 2018-05-18
  • 2015-05-07
  • 1970-01-01
  • 2016-01-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多