我有以下資料框架,包含日期格式 - yyyyMMddTHH:mm:ss UTC
資料準備
sparkDF = sql.createDataFrame([("20201021T00:00:00 0530"/span>,),
("20211011T00:00:00 0530",),
("20200212T00:00:00 0300",),
("20211021T00:00:00 0530",),
("20211021T00:00:00 0900",),
("20211021T00:00:00-0500",)
]
,['timestamp'])
sparkDF.show(truncate=False)
----------------------
|timestamp |
----------------------
|20201021T00:00:00 0530|
|20211011T00:00:00 0530|
|20200212T00:00:00 0300|
|20211021T00:00:00 0530|
|20211021T00:00:00 0900|
|20211021T00:00:00-0500|
----------------------
我知道日期格式來決議和轉換值到DateType
時間戳的決議
sparkDF.select(F.to_date(F。 col('timestamp'),"yyyyMMdd'T'HH:mm:ss 0530").alias('timestamp_parsed')) .show()
----------------
|timestamp_parsed|
----------------
| 2020-10-21|
| 2021-10-11|
| null|
| 2021-10-21|| null
| null|
|空
----------------
正如你所看到的,它特定于 0530字串,我知道我可以使用多個模式和coalesce第一個非空值的事實
多個模式 & Coalesce
sparkDF.withColumn('p1',F. to_date(F.col('timestamp'),"yyyyMMdd'T'HH:mm:ss 0530")
.withColumn('p2',F.to_date(F.col('timestamp'),"yyyMMdd'T'HH:mm:ss 0900")
.withColumn('p3',F.to_date(F.col('timestamp'),"yyyMMdd'T'HH:mm:ss-0500")
.withColumn('p4',F.to_date(F.col('timestamp'),"yyyMMdd'T'HH:mm:ss 0300")
.withColumn('timestamp_parsed',F.coalesce(F.col('p1'),F。 col('p2'),F.col('p3'),F.col('p4') )
.drop(*['p1','p2','p3','p4'])
.show(truncate=False)
---------------------- ----------------
|timestamp |timestamp_parsed|。
---------------------- ----------------
|20201021T00:00:00 0530|2020-10-21|
|20211011T00:00:00 0530|2021-10-11|
|20200212T00:00:00 0300|2020-02-12|
|20211021T00:00:00 0530|2021-10-21|
|20211021T00:00:00 0900|2021-10-21|
|20211021T00:00:00-0500|2021-10-21 !
---------------------- ----------------
是否有更好的方法來完成這個任務,因為在資料源中可能有一堆其他的UTC,在Spark中是否有一個標準的UTC TZ來決議所有的情況
uj5u.com熱心網友回復:
我認為你把to_date函式的第二個引數弄錯了,這導致你的輸出中出現了空值
你的時間戳中的 530是Zulu值,它只是表示當前的時間戳相對于UTC來說提前( )或延后(-)多少個小時和分鐘。 請參考Basil的回答
uj5u.com熱心網友回復:
你通常可以使用x、X或Z作為偏移模式,你可以在Spark日期模式檔案頁找到。然后你可以用以下完整的模式來決議你的日期。yyyyMMdd'T'HH:mm:ssxx
然而,如果你使用這種偏移模式,你的日期將首先被轉換為UTC格式,這意味著所有具有正偏移的時間戳將被匹配到前一天。例如,"20201021T00:00:00 0530"將被匹配到2020-10-20,使用to_date與前一個模式。
如果你想獲得顯示的日期,忽略偏移量,你應該首先使用regexp_extract函式從完整的時間戳字串中提取日期字串,然后執行to_date。
如果你以你的例子"20201021T00:00:00 0530",你想用regexp提取的是20201021部分,并對其應用to_date。你可以用下面的模式來做。^(d )。如果你有興趣,你可以在java的模式檔案中找到如何構建其他模式。
所以你的代碼應該是:
from pyspark.sql import functions as F
sparkDF.select(
F.to_date(
F.regexp_extract(F.col('timestamp'), '^(d )', 0), 'yyyMMdd')
).別名('timestamp_parsed')
).show()
通過你的輸入,你將得到:
。 ----------------
|timestamp_parsed|
----------------
|2020-10-21 !
|2021-10-11 !
|2020-02-12 |
|2021-10-21 !
|2021-10-21 !
|2021-10-21 !
----------------
uj5u.com熱心網友回復:
你可以在spark中創建 "udf "并使用它。下面是scala中的代碼。
import spark. implicits._
//只是為了創建資料集 用于你給出的例子
val data = Seq(
("20201021T00:00:00 0530"),
("20211011T00:00:00 0530"),
("20200212T00:00:00 0300"),
("20211021T00:00:00 0530"),
("20211021T00:00:00 0900"),
("20211021T00:00:00-0500"))
val dataset = data.toDF("timestamp")
val udfToDateUTC = functions.udf((epochMilliUTC: String) => {
val formatter = DateTimeFormatter.ofPattern("yyyyMMdd'T'HH:mm:ssZ"/span>)
val res = OffsetDateTime.parse(epochMilliUTC, formatter).withOffsetSameInstant(ZoneOffset.UTC)
res.toString()
})
dataset.select(dataset.col("timestamp"),udfToDateUTC(dataset.col("timestamp")).alias("timestamp_parsed") ).show(false
//輸出
---------------------- -----------------
|timestamp |timestamp_parsed |
---------------------- -----------------
|20201021T00:00:00 0530|2020-10-20T18:30Z|
|20211011T00:00:00 0530|2021-10-10T18:30Z|
|20200212T00:00:00 0300|2020-02-11T21:00Z|
|20211021T00:00:00 0530|2021-10-20T18:30Z|
|20211021T00:00:00 0900|2021-10-20T15:00Z|
|20211021T00:00:00-0500|2021-10-21T05:00Z|
---------------------- -----------------
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/310741.html
標籤:
