在多數情況下,使用to_timestamp()
,幾乎可以解決掉所有的時間轉換問題,但Data Cleaning 是永遠不會讓你好過的,那這時候可以怎麼做呢?
這時候user define function 就出來了
為了這種狀況,救世主就出現了,我們可以自己定義想要的處理方式,並加入各種各樣的邏輯,然後就可以完美的處理資料啦!
user define function 其實很簡單,基本上就在你原本的function外面加上udf(),就可以實現你的user defined function 了
那我們接下來看看要怎麼實作這個時間轉換的問題吧
當你的一個data set 中可能有很多不同的時間format(MM/DD/YYYY
,DD/MM/YYYY
)
就可以參考下列做法去做轉換,推薦於使用spark3.0以上版本,因為spark3.0以上版本的timestamp format機制較於嚴格,常常會有因為format已經無法符合現行的架構出現的error
所以這時候我們就可以求助於user defined function,
這時候我們需要import time
去做處理
可以借助python中的time.strptime(date, "%m/%d/%Y %I:%M:%S %p")
去給定目前的時間格式,接下來Do Re Mi So ~
啊不小心透露年齡了,簡單來說這樣就可以快速又簡單地完成你的時間轉換喔!
下面是sample code的部分~
def timestamp_change(date,formatString):
"""Timestamp handle
change multiple format to 'yyyy-MM-dd hh:mm:ss'
1. MM/DD/YYYY and PM/AM e.g.Format: 1/17/2023 10:06:18 PM
2. MM/DD/YYYY e.g.Format: 1/17/2023
3. DD/MM/YYYY. e.g.Format: 17/1/2023.
4. DD/MM/YYYY e.g.Format: 17/1/2023
Args:
date : date string
formatString : like MM/DD/YYYY or DD/MM/YYYY
Return:
format timestamp
"""
if date is None:
return date
split_date = date.split('/')
## means strange data ,so we need to use another way to fixed
if len(split_date) == 1:
return date
else :
if formatString == 'MM/DD/YYYY':
if re.search("[A-z]",split_date[2]) != None:
time_obj_default = time.strptime(date, "%m/%d/%Y %I:%M:%S %p")
mon = str(time_obj_default.tm_mon)
day = str(time_obj_default.tm_mday)
hour = str(time_obj_default.tm_hour)
minute = str(time_obj_default.tm_min)
sec = str(time_obj_default.tm_sec)
if len(mon) == 1:
mon ='0'+mon
if len(day) == 1:
day ='0'+day
if len(hour) == 1:
hour ='0'+hour
if len(minute) == 1:
minute ='0'+minute
if len(sec) == 1:
sec ='0'+sec
return(str(time_obj_default.tm_year)+'-'+mon+'-'+day+' '+hour+':'+minute+':'+sec)
else:
date =date.split('.')[0]
time_obj_default = time.strptime(date, "%m/%d/%Y")
mon = str(time_obj_default.tm_mon)
day = str(time_obj_default.tm_mday)
if len(mon) == 1:
mon ='0'+mon
if len(day) == 1:
day ='0'+day
return(str(time_obj_default.tm_year)+'-'+mon+'-'+day+' 00:00:00')
elif formatString == 'DD/MM/YYYY':
if re.search("[A-z]",split_date[2]) != None:
time_obj_default = time.strptime(date, "%d/%m/%Y %I:%M:%S %p")
mon = str(time_obj_default.tm_mon)
day = str(time_obj_default.tm_mday)
hour = str(time_obj_default.tm_hour)
minute = str(time_obj_default.tm_min)
sec = str(time_obj_default.tm_sec)
if len(mon) == 1:
mon ='0'+mon
if len(day) == 1:
day ='0'+day
if len(hour) == 1:
hour ='0'+hour
if len(minute) == 1:
minute ='0'+minute
if len(sec) == 1:
sec ='0'+sec
return(str(time_obj_default.tm_year)+'-'+mon+'-'+day+' '+hour+':'+minute+':'+sec)
else:
date =date.split('.')[0]
time_obj_default = time.strptime(date, "%d/%m/%Y")
mon = str(time_obj_default.tm_mon)
day = str(time_obj_default.tm_mday)
if len(mon) == 1:
mon ='0'+mon
if len(day) == 1:
day ='0'+day
return(str(time_obj_default.tm_year)+'-'+mon+'-'+day+' 00:00:00')
timestamp_change_udf = udf(lambda x,y: timestamp_change(x,y),StringType())
##接下來你只要直接去呼叫你的function就可以成功轉換囉
df = df.withColumn('Date_of_open',to_timestamp(timestamp_change_udf('Date_of_open','formatString')))
希望今天的內容對大家有幫助!