前言
網(wǎng)上關(guān)于mysq時(shí)間耳贬、python時(shí)間與時(shí)間戳等文章很多踏堡,翻來(lái)翻去找不到頭緒,根據(jù)不同博客的寫(xiě)法咒劲,挑了幾個(gè)來(lái)測(cè)試顷蟆,這里記錄一下。
況且腐魂,不以實(shí)際需求為前提的博文帐偎,就是瞎寫(xiě),估計(jì)以后自己都看不懂蛔屹。
Mysql 時(shí)間類型
在數(shù)據(jù)庫(kù)建表的時(shí)候削樊,通常有5中字段類型讓人選擇: TIME、DATE兔毒、DATETIME漫贞、TIMESTAMP、YEAR育叁,它們又各自是什么格式呢迅脐?要寫(xiě)的讓自己容易記:
- TIME類型 :存儲(chǔ)空間[3 bytes] - 時(shí)間格式[HH:MM:SS] - 時(shí)間范圍[-838:59:59 到 ~ 838:59:59]
- DATE類型 :存儲(chǔ)空間[3 bytes] - 時(shí)間格式[YYYY-MM-DD] - 時(shí)間范圍[1000-01-01 到 9999-12-31] (可以理解為年月日)
- DATETIME類型 :存儲(chǔ)空間[8 bytes] - 時(shí)間格式[YYYY-MM-DD HH:MM:SS] - 時(shí)間范圍[1000-01-01 00:00:00 到 9999-12-31 23:59:59] (可以理解為年月日時(shí)分秒)
- TIMESTAMP類型 :存儲(chǔ)空間[4 bytes] - 時(shí)間格式[YYYY-MM-DD HH:MM:SS] - 時(shí)間范圍[1970-01-01 00:00:01 到 2038-01-19 03:14:07] (以秒為計(jì)算)
- YEAR類型 :存儲(chǔ)空間[1 bytes] - 時(shí)間格式[YYYY] - 時(shí)間范圍1901 到 2155
根據(jù)上面的類型得知,YEAR這種類型用的稍微少一點(diǎn)豪嗽,TIME用的估計(jì)也不多谴蔑,比較多的還是DATE、DATETIME和時(shí)間戳TIMESTAMP
Python 日期和時(shí)間
Python提供了三種時(shí)間函數(shù)龟梦,時(shí)間模塊time隐锭、基本時(shí)間日期模塊datetime和日歷模塊Calendar,具體的詳細(xì)介紹和用法在[菜鳥(niǎo)教程-時(shí)間和日期:傳送A计贰,傳送B]有介紹成榜,這里不復(fù)制粘貼了。
日歷模塊Calendar是用的次數(shù)比較少的(在爬蟲(chóng)和Django開(kāi)發(fā)的實(shí)際應(yīng)用較少)蹦玫,出現(xiàn)較多的是time模塊和dateteime模塊:
- time模塊 -- 比較接近底層的
- datetime模塊 -- 基于time新增了很過(guò)功能赎婚,提供了更多函數(shù)
使用對(duì)比
1、獲取當(dāng)前時(shí)間
import datetime,time
""" 當(dāng)前時(shí)間 """
print(time.time())
print(datetime.datetime.now())
得到的輸出結(jié)果是:
1516200437.9920225
2018-01-17 22:47:17.992047
2樱溉、當(dāng)前時(shí)間格式化
import datetime,time
""" time當(dāng)前時(shí)間 """
localtime = time.localtime(time.time())
print("本地時(shí)間為 :", localtime)
gtime = time.strftime('%Y-%m-%d',localtime)
print("可以把時(shí)間轉(zhuǎn)換為 :",gtime)
gltime = time.strftime('%Y-%m-%d %H:%M:%S',localtime)
print("可以把時(shí)間轉(zhuǎn)換為 :",gltime)
#------------------------------------------------
""" datetime當(dāng)前時(shí)間 """
localtime = datetime.datetime.now()
gtime = datetime.datetime.now().strftime("%Y-%m-%d")
gltime = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print(localtime)
print(gtime)
print(gltime)
得到的結(jié)果是:
本地時(shí)間為 : time.struct_time(tm_year=2018, tm_mon=1, tm_mday=17, tm_hour=22, tm_min=55, tm_sec=46, tm_wday=2, tm_yday=17, tm_isdst=0)
可以把時(shí)間轉(zhuǎn)換為 : 2018-01-17
可以把時(shí)間轉(zhuǎn)換為 : 2018-01-17 22:55:46
#------------------------------------------------
2018-01-18 08:03:18.760582
2018-01-18
2018-01-18 08:03:18
這里可以看出挣输,用兩個(gè)模塊獲得的當(dāng)前時(shí)間都不是人類容易閱讀的,都需要通過(guò)strftime函數(shù)進(jìn)行格式化福贞。
3撩嚼、文本時(shí)間轉(zhuǎn)換
這里我指的是爬蟲(chóng)獲取的其他網(wǎng)站的時(shí)間,通常有幾種格式:
- 長(zhǎng)時(shí)間 -- 2018-01-06 18:35:05挖帘、2018-01-06 18:35
- 日期 -- 2018-01-06
- 月時(shí)間 -- 2018-01
- 時(shí)間 -- 18:35:05
通常完丽,爬蟲(chóng)得到的時(shí)間都是人閱讀的,只不過(guò)分隔符不同拇舀。并且在入庫(kù)的時(shí)候逻族,我希望他們的時(shí)間格式是統(tǒng)一的,年月日時(shí)分秒或者年月日骄崩,如果可以就用時(shí)間戳聘鳞,方便計(jì)算(年月日時(shí)分秒對(duì)應(yīng)年月日時(shí)分秒,年月日不可直接轉(zhuǎn)換為年月日時(shí)分秒)要拂。
遇到日期類型2018-01-06的時(shí)間格式抠璃,是不可以用函數(shù)直接轉(zhuǎn)成長(zhǎng)時(shí)間2018-01-06 18:35:05格式的,報(bào)錯(cuò)脱惰。當(dāng)遇到這種情況搏嗡,而我又想將時(shí)間統(tǒng)一,只能進(jìn)行轉(zhuǎn)換拉一。轉(zhuǎn)換又分為兩種采盒,相同時(shí)間格式轉(zhuǎn)換與不同時(shí)間格式轉(zhuǎn)換:
第一種情形
目標(biāo):2018-01-06 18:35:05 轉(zhuǎn)換為2018-01-06 18:35:05
它有兩種方法可以滿足
方法一的邏輯是不同格式的時(shí)間轉(zhuǎn)換要先轉(zhuǎn)成時(shí)間數(shù)組,然后再由時(shí)間數(shù)組格式化成想要的類型:
import datetime,time
a = "2013-10-10 23:40:00" # 想要轉(zhuǎn)換成 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)
從輸出結(jié)果:
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
可以看到舅踪,先通過(guò)time.strptime把它轉(zhuǎn)換成時(shí)間數(shù)組纽甘,然后通過(guò)time.strftime把時(shí)間數(shù)組格式化成我想要的格式。
方法二抽碌,由于最終格式化的時(shí)間也是字符串str悍赢,所以當(dāng)遇到這種情況的時(shí)候,還可以直接用replace來(lái)進(jìn)行轉(zhuǎn)換:
a = "2013-10-10 23:40:00" # 想要轉(zhuǎn)換成 a = "2013/10/10 23:40:00"
print(a.replace("-", "/"))
輸出結(jié)果為:
2013/10/10 23:40:00
第二種情形
目標(biāo):2018-01-06 轉(zhuǎn)換為2018-01-06 18:35:05
它也有兩種方法可以滿足
它的邏輯是將年月日的字符串拼接上時(shí)分秒货徙,然后再按照上面的兩種方法進(jìn)行轉(zhuǎn)換左权,比如:
a = "2013-10-10 " # 想要轉(zhuǎn)換成 a = "2013/10/10 23:40:00"
ac = a + "00:00:00"
print(ac.replace("-", "/"))
得到輸出結(jié)果
2013/10/10 00:00:00
第三種情形
目標(biāo):2018-01-06 18:35:05 轉(zhuǎn)換為2018-01-06
思路與第一種一致,先轉(zhuǎn)換為時(shí)間數(shù)組痴颊,然后再由時(shí)間數(shù)組進(jìn)行格式化:
import datetime,time
a = "2013-10-10 23:40:00" # 想要轉(zhuǎn)換成 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)
得到結(jié)果輸出為(可以看到timeArray的類型是time.struct_time):
<class 'time.struct_time'>
2013/10/10
4赏迟、時(shí)間的比較運(yùn)算
都知道字符串是不可以進(jìn)行比較計(jì)算的,那么我們就需要用到其他的格式進(jìn)行蠢棱。time的strptime轉(zhuǎn)換成時(shí)間數(shù)組是不可以進(jìn)行運(yùn)算的锌杀,但是datetime可以甩栈。
第一種 ,時(shí)間格式相同
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
從結(jié)果上可以看到糕再,格式相同的兩種時(shí)間量没,可以通過(guò)datetime.datetime.strptime進(jìn)行轉(zhuǎn)換后再運(yùn)算,在結(jié)果中還可以通過(guò).seconds來(lái)計(jì)算 相差秒數(shù) 和通過(guò).days來(lái)計(jì)算 相差天數(shù)
第二種 突想,如果時(shí)間格式不一樣殴蹄,但是轉(zhuǎn)換后的類型一樣,也是可以比較的:
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)
這段代碼里面時(shí)間的字符串形式就不一樣猾担,但是通過(guò)同樣的函數(shù)進(jìn)行轉(zhuǎn)換后就可以比較計(jì)算了袭灯。
第三種 ,年月日時(shí)分秒與年月日的計(jì)算绑嘹,其實(shí)原理是一樣的稽荧,轉(zhuǎn)換后他們的格式都一樣,所以也是可以計(jì)算的圾叼,2012/03/05 17:41:20與2012-03-05的時(shí)間相差:
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))
輸出結(jié)果是
4 63680
4 days, 17:41:20
<class 'datetime.timedelta'>
通過(guò)print的結(jié)果可以得到幾點(diǎn)信息:
不同格式的時(shí)間在轉(zhuǎn)化后是可以進(jìn)行比較運(yùn)算的
可以通過(guò).days和.seconds來(lái)進(jìn)行天數(shù)與時(shí)分秒的展示
計(jì)算后得到的數(shù)據(jù)類型是 'datetime.timedelta' 而不是str類型
比如計(jì)算3天后的時(shí)間:
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'))
得到的結(jié)果是:
<class 'datetime.datetime'>
2018-01-21 10:26:14
用datetime.timedelta取得3天時(shí)間蛤克,然后將當(dāng)前時(shí)間加上3天,得到的是'datetime.datetime'類型數(shù)據(jù)夷蚊,變成人類閱讀的格式則需要strftime函數(shù)進(jìn)行格式化构挤,最終得到想要的2018-01-21 10:26:14。
5惕鼓、時(shí)間戳
把字符串時(shí)間轉(zhuǎn)換為時(shí)間戳:
import datetime,time
a = "2013-10-10 23:40:00"
# 轉(zhuǎn)換為時(shí)間數(shù)組
timeArray = time.strptime(a, "%Y-%m-%d %H:%M:%S")
# 轉(zhuǎn)換為時(shí)間戳:
timeStamp = time.mktime(timeArray)
print(timeArray)
print(timeStamp)
輸出結(jié)果為:
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的時(shí)間數(shù)組與時(shí)間戳并不是同一樣?xùn)|西筋现,他們是有區(qū)別的
6、strftime與strptime
這兩個(gè)是python中常用的
strftime函數(shù):
- 函數(shù)接收以時(shí)間元組箱歧,并返回以可讀字符串表示的當(dāng)?shù)貢r(shí)間矾飞,格式由參數(shù)format決定。
- time.strftime(format[, t])
- format -- 格式字符串呀邢。t -- 可選的參數(shù)t是一個(gè)struct_time對(duì)象洒沦。
- 返回以可讀字符串表示的當(dāng)?shù)貢r(shí)間。
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)))
得到結(jié)果輸出:
2009-02-17 09:03:38
strptime()
函數(shù)根據(jù)指定的格式把一個(gè)時(shí)間字符串解析為時(shí)間元組价淌。
time.strptime(string[, format])
string -- 時(shí)間字符串申眼。format -- 格式化字符串。
返回struct_time對(duì)象蝉衣。
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)
得到結(jié)果:
2012-03-05 17:41:20
2012-03-01 00:00:00
時(shí)間格式與入庫(kù)
前面鋪墊了這么多括尸,最終的目的還是需要入庫(kù)。這里以4種數(shù)據(jù)庫(kù)時(shí)間類型為例:
- 字段名 => 數(shù)據(jù)類型
- r_time => time
- r_date => date
- r_datetime => datetime
- r_timestamp => timestamp
根據(jù)最上方所寫(xiě)的Mysql時(shí)間類型病毡,可以得出對(duì)應(yīng)的時(shí)間格式為:
- 時(shí)間格式 => 數(shù)據(jù)類型
- 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),會(huì)報(bào)錯(cuò)
可以簡(jiǎn)寫(xiě)成17:35,數(shù)據(jù)庫(kù)會(huì)自動(dòng)補(bǔ)全后面的00,入庫(kù)后最終數(shù)據(jù)17:35:00
如果簡(jiǎn)寫(xiě)成17,則入庫(kù)后變成00:00:17
當(dāng)然有送,如果更奇葩的寫(xiě)法17:,17:35:這種是會(huì)報(bào)錯(cuò)的
date類型
date類型的格式指定為2018-3-1與2018/3/1淌喻,最終入庫(kù)格式是(2018-03-01),它會(huì)自動(dòng)補(bǔ)全
可以簡(jiǎn)寫(xiě)成[18/3/1]娶眷、[17/3/1]似嗤、[07/3/1]、[97/3/1]届宠,數(shù)據(jù)庫(kù)會(huì)自動(dòng)補(bǔ)全前面的年份,入庫(kù)后最終數(shù)據(jù)2018-03-01、2017-03-01乘粒、2007-03-01豌注、1997-03-01
不可簡(jiǎn)寫(xiě)成[2017]、[2017/3]灯萍,會(huì)報(bào)錯(cuò)轧铁,必須是完整的日期格式
datetime類型
datetime類型的格式指定為2018-3-1 17:35:00和2018/3/1 17:35:00,最終入庫(kù)格式是2018-03-01 17:35:00
它是date與time的結(jié)合旦棉,有很多共同特性
可以簡(jiǎn)寫(xiě)成[18/3/1 17:35:05]齿风、[17/3/1 17:35]、[07/3/1 17]绑洛、[97/3/1 17]救斑,數(shù)據(jù)庫(kù)會(huì)自動(dòng)補(bǔ)全前面的年份,入庫(kù)后最終數(shù)據(jù)2018-03-01 17:35:05、2017-03-01 17:35:00真屯、2007-03-01 17:00:00脸候、1997-03-01 17:00:00“竽瑁可以看到它自動(dòng)將時(shí)間格式補(bǔ)全成統(tǒng)一格式运沦,這里與time不同的是,如果只寫(xiě)17不寫(xiě)分秒配深,time會(huì)默認(rèn)將17當(dāng)成秒携添,這里則是默認(rèn)當(dāng)成小時(shí)。
與date一樣篓叶,年月日不可省略烈掠,必須以年月日格式出現(xiàn)
timestamp類型
根據(jù)上面的描述,timestamp的入庫(kù)格式與datetime是一樣的澜共,不同的是時(shí)間范圍和存儲(chǔ)空間向叉,它的格式與用法跟datetime一致