time date datetme timestamp 傻傻分不清楚
時間格式對於任何一個工程師來說都是繞不開的知識,爬蟲工程師同樣如此。爬蟲工程師要將不同網站的相同型別內容存放在同一個資料表當中,常見的有:
* 站點 A 的時間格式為 “2018-5” * 站點 B 的時間格式為 “3天前” * 站點 C 的時間格式為 “5-10 8:25” 複製程式碼
在資料庫儲存的時候,應該選用哪種時間格式合適呢?新建欄位的時候是選擇 DATE 格式還是 DATETIME 格式?YEAR 又是什麼?
Python 內建時間函式有 time 和 datetime,什麼時候適合用 time ?什麼時候選擇 datetime 呢?
Mysql 時間型別
在資料庫建表的時候,通常有5中欄位型別讓人選擇: TIME、DATE、DATETIME、TIMESTAMP、YEAR 。
每種型別的儲存空間和時間格式如下:
- TIME型別 :儲存空間[3 bytes] - 時間格式[HH:MM:SS] - 時間範圍[-838:59:59到~ 838:59:59] - DATE型別 :儲存空間[3 bytes] - 時間格式[YYYY-MM-DD] - 時間範圍[1000-01-01 到 9999-12-31] (可以理解為年月日) - DATETIME型別 :儲存空間[8 bytes] - 時間格式[YYYY-MM-DD HH:MM:SS] - 時間範圍[1000-01-01 00:00:00 到 9999-12-31 23:59:59] (可以理解為年月日時分秒) - TIMESTAMP型別 :儲存空間[4 bytes] - 時間格式[YYYY-MM-DD HH:MM:SS] - 時間範圍[1970-01-01 00:00:01 到 2038-01-1903:14:07] (以秒為計算) - YEAR型別 :儲存空間[1 bytes] - 時間格式[YYYY] - 時間範圍[1901到2155](按年計算) 複製程式碼
YEAR 這樣的時間格式用的是比較少的,而 TIME 用的也不多,常見的還是 DATE、DATETIME 和時間戳 TIMESTAMP。
Python 的 time
Python提供了三種時間函式,時間模組 time、基本時間日期模組 datetime 和日曆模組 Calendar。Python 的 time 模組下有很多函式可以轉換常見日期格式。如函式 time.time() 用於獲取當前時間戳:
import time timestamp = time.time() print(timestamp, type(timestamp)) 複製程式碼
輸出的時間戳是 float 型別:
1544788687.041193 <class 'float'> 複製程式碼
時間戳單位最適於做日期運算。但是1970年之前的日期就無法以此表示了。太遙遠的日期也不行,UNIX和Windows只支援到2038年。Time 模組包含了以下內建函式,既有時間處理的,也有轉換時間格式的:

Python 的日曆
Calendar 函式都是日曆相關的,星期一是預設的每週第一天,星期天是預設的最後一天。更改設定需呼叫calendar.setfirstweekday()函式。模組包含了以下內建函式:

日曆模組 Calendar 是用的次數比較少的(在爬蟲和Django開發的實際應用較少)。出現較多的是 time 模組和 dateteime 模組。那 time 和 datetime 是什麼關係呢?
- time模組--比較接近底層的 - datetime模組--基於time新增了很過功能,提供了更多函式 複製程式碼
使用對比
1、獲取當前時間
import datetime, time """ 崔慶才丨靜覓、韋世東丨奎因 邀你關注微信公眾號【進擊的Coder】 """ print(time.time()) print(datetime.datetime.now()) 複製程式碼
得到的輸出結果是:
1544789253.025471 2018-12-14 20:07:33.025502 複製程式碼
2、當前時間格式化
import datetime, time """ 崔慶才丨靜覓、韋世東丨奎因 邀你關注微信公眾號【進擊的Coder】 """ """ time當前時間 """ localtime = time.localtime(time.time()) print("當前時間元組 :", localtime) print("不格式化:", time.time()) res1 = time.strftime('%Y-%m-%d', localtime) print("strftime 可以把時間格式化為日期形式 :", res1) res2 = time.strftime('%Y-%m-%d %H:%M:%S', localtime) print("strftime 可以把時間轉換為日期和時間 :", res2) # ------------------------------------------------ """ datetime當前時間 """ time_now = datetime.datetime.now() res3 = datetime.datetime.now().strftime("%Y-%m-%d") res4 = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") print("不格式化的當前時間:", time_now) print("datetime 也可以這樣用:", res3) print("datetime 也可以這樣用:", res4) 複製程式碼
得到的結果是:
當前時間元組 : time.struct_time(tm_year=2018, tm_mon=12, tm_mday=14, tm_hour=20, tm_min=18, tm_sec=11, tm_wday=4, tm_yday=348, tm_isdst=0) 不格式化: 1544789891.681039 strftime 可以把時間格式化為日期形式 : 2018-12-14 strftime 可以把時間轉換為日期和時間 : 2018-12-14 20:18:11 不格式化的當前時間: 2018-12-14 20:18:11.681079 datetime 也可以這樣用: 2018-12-14 datetime 也可以這樣用: 2018-12-14 20:18:11 複製程式碼
這裡可以看出這兩個模組獲得的時間都不是人類容易閱讀的,都需要通過strftime函式進行格式化。
3、文字時間轉換
這裡我指的是爬蟲獲取的其他網站的時間,通常有幾種格式:
- 長時間 -- 2018-01-06 18:35:05、2018-01-06 18:35
- 日期 -- 2018-01-06
- 月時間 -- 2018-01
- 時間 -- 18:35:05
爬蟲得到的時間都是給人閱讀的,只不過分隔符不同。在入庫的時候,爬蟲工程師希望他們的時間格式是統一的,年月日時分秒或者年月日,如果可以就用時間戳,方便計算(年月日時分秒對應年月日時分秒,年月日不可直接轉換為年月日時分秒)。
遇到日期型別 2018-01-06 的時間格式,是不可以用函式直接轉成長時間 (比如 2018-01-06 18:35:05) 格式的,強行操作會報錯。當遇到這種需要將時間格式統一的情況,沒有直接操作的辦法,只能對時間進行轉換。轉換又分為兩種,相同時間格式轉換與不同時間格式轉換:
第一種情形
目標:2018-01-06 18:35:05 轉換為2018/01/06 18:35:05
它有兩種方法可以滿足
方法一的邏輯是不同格式的時間轉換要先轉成時間陣列,然後再由時間陣列格式化成想要的型別:
import datetime,time a = "2013-10-10 23:40:00"# 想要轉換成 a = "2013/10/10 23:40:00" timeArray = time.strptime(a, "%Y-%m-%d %H:%M:%S") otherStyleTime = time.strftime("%Y/%m/%d %H:%M:%S", timeArray) print(timeArray) print(otherStyleTime) 複製程式碼
從輸出結果:
time.struct_time(tm_year=2013, tm_mon=10, tm_mday=10, tm_hour=23, tm_min=40, tm_sec=0, tm_wday=3, tm_yday=283, tm_isdst=-1) 2013/10/10 23:40:00 複製程式碼
可以看到,先通過 time.strptime 把它轉換成時間陣列,然後通過 time.strftime 把時間陣列格式化成我想要的格式。
方法二,由於最終格式化的時間也是字串 str,所以當遇到這種情況的時候,還可以直接用 replace 來進行轉換:
a = "2013-10-10 23:40:00"# 想要轉換成 a = "2013/10/10 23:40:00" print(a.replace("-", "/")) 複製程式碼
輸出結果為:
2013/10/10 23:40:00 複製程式碼
第二種情形
目標:2018-01-06 轉換為2018-01-06 18:35:05
它也有兩種方法可以滿足
它的邏輯是將年月日的字串拼接上時分秒,然後再按照上面的兩種方法進行轉換,比如:
a = "2013-10-10 "# 想要轉換成 a = "2013/10/10 23:40:00" ac = a + "00:00:00" print(ac.replace("-", "/")) 複製程式碼
得到輸出結果
2013/10/10 00:00:00 複製程式碼
第三種情形
目標:2018-01-06 18:35:05 轉換為2018-01-06
思路與第一種一致,先轉換為時間陣列,然後再由時間陣列進行格式化:
import datetime,time a = "2013-10-10 23:40:00"# 想要轉換成 a = "2013/10/10" timeArray = time.strptime(a, "%Y-%m-%d %H:%M:%S") otherStyleTime = time.strftime("%Y/%m/%d", timeArray) print(type(timeArray)) print(otherStyleTime) 複製程式碼
得到結果輸出為(可以看到 timeArray 的型別是 time.struct_time):
<class 'time.struct_time'> 2013/10/10 複製程式碼
4、時間的比較運算
都知道字串是不可以進行比較計算的,那麼我們就需要用到其他的格式進行。time 的 strptime 轉換成時間陣列是不可以進行運算的,但是 datetime 可以。
第一種,時間格式相同
import datetime,time d1 = datetime.datetime.strptime('2012-03-05 17:41:20', '%Y-%m-%d %H:%M:%S') d2 = datetime.datetime.strptime('2012-03-05 16:41:20', '%Y-%m-%d %H:%M:%S') delta = d1 - d2 print(type(d1)) print(delta.seconds) print(delta) 複製程式碼
得到的輸出是:
<class 'datetime.datetime'> 3600 1:00:00 複製程式碼
從結果上可以看到,格式相同的兩種時間,可以通過datetime.datetime.strptime進行轉換後再運算,在結果中還可以通過.seconds來計算 相差秒數 和通過.days來計算 相差天數
第二種,如果時間格式不一樣,但是轉換後的型別一樣,也是可以比較的:
import datetime,time d1 = datetime.datetime.strptime('2012/03/05 17:41:20', '%Y/%m/%d %H:%M:%S') d2 = datetime.datetime.strptime('2012-03-05 16:41:20', '%Y-%m-%d %H:%M:%S') delta = d1 - d2 print(delta.seconds) print(delta) 複製程式碼
這段程式碼裡面時間的字串形式就不一樣,但是通過同樣的函式進行轉換後就可以比較計算了。
第三種,年月日時分秒與年月日的計算,其實原理是一樣的,轉換後他們的格式都一樣,所以也是可以計算的,2012/03/05 17:41:20與2012-03-05的時間相差:
import datetime,time d1 = datetime.datetime.strptime('2012/03/05 17:41:20', '%Y/%m/%d %H:%M:%S') d2 = datetime.datetime.strptime('2012-03-01', '%Y-%m-%d') delta = d1 - d2 print(delta.days,delta.seconds) print(delta) print(type(delta)) 複製程式碼
輸出結果是
4 63680 4 days, 17:41:20 <class 'datetime.timedelta'> 複製程式碼
通過print的結果可以得到幾點資訊: 不同格式的時間在轉化後是可以進行比較運算的 可以通過.days和.seconds來進行天數與時分秒的展示 計算後得到的資料型別是 'datetime.timedelta' 而不是str型別
比如計算3天后的時間:
import datetime,time now = datetime.datetime.now() delta = datetime.timedelta(days=3) n_days = now + delta print(type(n_days)) print(n_days.strftime('%Y-%m-%d %H:%M:%S')) 複製程式碼
得到的結果是:
<class 'datetime.datetime'> 2018-01-21 10:26:14 複製程式碼
用 datetime.timedelta 取得3天時間,然後將當前時間加上3天,得到的是 'datetime.datetime' 型別資料,變成人類閱讀的格式則需要 strftime 函式進行格式化,最終得到想要的 2018-01-21 10:26:14。
5、時間戳
把字串時間轉換為時間戳:
import datetime,time a = "2013-10-10 23:40:00" # 轉換為時間陣列 timeArray = time.strptime(a, "%Y-%m-%d %H:%M:%S") # 轉換為時間戳: timeStamp = time.mktime(timeArray) print(timeArray) print(timeStamp) 複製程式碼
輸出結果為:
time.struct_time(tm_year=2013, tm_mon=10, tm_mday=10, tm_hour=23, tm_min=40, tm_sec=0, tm_wday=3, tm_yday=283, tm_isdst=-1) 1381419600.0 複製程式碼
可以看到time的時間陣列與時間戳並不是同一樣東西,他們是有區別的
6、strftime與strptime
這兩個是 python 中常用的
strftime 函式:
- 函式接收以時間元組,並返回以可讀字串表示的當地時間,格式由引數 format 決定。
- time.strftime(format[, t])
- format -- 格式字串。t -- 可選的引數t是一個 struct_time 物件。
- 返回以可讀字串表示的當地時間。
import time t = (2009, 2, 17, 17, 3, 38, 1, 48, 0) t = time.mktime(t) print(time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(t))) 複製程式碼
得到結果輸出:
2009-02-17 09:03:38 複製程式碼
strptime() 函式根據指定的格式把一個時間字串解析為時間元組。 time.strptime(string[, format]) string -- 時間字串。format -- 格式化字串。 返回 struct_time 物件。
import datetime,time d1 = datetime.datetime.strptime('20120305 17:41:20', '%Y%m%d %H:%M:%S') d2 = datetime.datetime.strptime('2012-03-01', '%Y-%m-%d') print(d1) print(d2) 複製程式碼
得到結果:
2012-03-05 17:41:20 2012-03-01 00:00:00 複製程式碼
時間格式與入庫
前面鋪墊了這麼多,最終的目的還是需要入庫。這裡以4種資料庫時間型別為例:
- 欄位名 => 資料型別
- r_time => time
- r_date => date
- r_datetime => datetime
- r_timestamp => timestamp
根據最上方所寫的 Mysql 時間型別,可以得出對應的時間格式為:
- 時間格式 => 資料型別
- 17:35:05 => time
- 2018-3-1 => date
- 2018/3/1 17:35 => datetime
- 2018/3/1 17:35 => timestamp
time型別
time 型別的格式指定為 17:35:05,不可替換為(17-35-05 或者 17/35/05),會報錯
可以簡寫成 17:35,資料庫會自動補全後面的 00,入庫後最終資料 17:35:00
如果簡寫成 17,則入庫後變成 00:00:17
當然,如果更奇葩的寫法 17:,17:35: 這種是會報錯的
date型別
date 型別的格式指定為 2018-3-1 與 2018/3/1,最終入庫格式是(2018-03-01),它會自動補全
可以簡寫成 [18/3/1]、[17/3/1]、[07/3/1]、[97/3/1],資料庫會自動補全前面的年份,入庫後最終資料 2018-03-01、2017-03-01、2007-03-01、1997-03-01
不可簡寫成 [2017]、[2017/3],會報錯,必須是完整的日期格式
datetime型別
datetime 型別的格式指定為 2018-3-1 17:35:00 和 2018/3/1 17:35:00,最終入庫格式是 2018-03-01 17:35:00
它是 date 與 time 的結合,有很多共同特性
可以簡寫成 [18/3/1 17:35:05]、[17/3/1 17:35]、[07/3/1 17]、[97/3/1 17],資料庫會自動補全前面的年份,入庫後最終資料 2018-03-01 17:35:05、2017-03-01 17:35:00、2007-03-01 17:00:00、1997-03-01 17:00:00。可以看到它自動將時間格式補全成統一格式,這裡與 time 不同的是,如果只寫 17 不寫分秒,time 會預設將 17 當成秒,這裡則是預設當成小時。
與 date 一樣,年月日不可省略,必須以年月日格式出現
timestamp型別
根據上面的描述,timestamp的入庫格式與datetime是一樣的,不同的是時間範圍和儲存空間,它的格式與用法跟datetime一致