python中處理時(shí)間的模塊有三個(gè),datetime,time,calendar,融匯貫通三個(gè)模塊,才能隨心所欲地用python處理時(shí)間。本文就是為此而寫,文章著重點(diǎn)在于梳理出三個(gè)模塊的設(shè)計(jì)脈絡(luò),便于大家記憶里面的api。在需要的時(shí)候能夠去查找相應(yīng)的方法。但由于calendar模塊使用不多,限于篇幅,本文沒有涉及。
1,概述
datetime模塊主要是用來表示日期的,就是我們常說的年月日時(shí)分秒,calendar模塊主要是用來表示年月日,是星期幾之類的信息,time模塊主要側(cè)重點(diǎn)在時(shí)分秒,粗略從功能來看,我們可以認(rèn)為三者是一個(gè)互補(bǔ)的關(guān)系,各自專注一塊。方便用戶依據(jù)不同的使用目的選用趁手的模塊。
2,從time模塊說起
為了學(xué)習(xí)time模塊,我們需要先知道幾個(gè)與時(shí)間相關(guān)的概念:
1),epoch
假設(shè)我們要將時(shí)間表示成毫秒數(shù),比方說1000000毫秒,那有一個(gè)問題必須解決,這個(gè)1000000毫秒的起點(diǎn)是什么時(shí)間,也就是我們的時(shí)間基準(zhǔn)點(diǎn)是什么時(shí)間?好比我說你身高1.8米,那這個(gè)身高是指相對(duì)于你站立的地面說的。這個(gè)時(shí)間基準(zhǔn)點(diǎn)就是epoch,在Unix系統(tǒng)中,這個(gè)基準(zhǔn)點(diǎn)就是1970年1月1日0點(diǎn)整那個(gè)時(shí)間點(diǎn)。
2),GMT,UTC
上面我們說epoch表示1970年的起始點(diǎn),那這個(gè)1970年又是相對(duì)于哪個(gè)基準(zhǔn)時(shí)間呢?一般來說,就是相對(duì)于格林尼治時(shí)間,也叫做GMT(GreenwichMeanTime)時(shí)間,還叫做UTC(CoordinatedUniversalTime),為啥一個(gè)時(shí)間基準(zhǔn)有兩個(gè)名字?歷史上,先有的GMT,后有的UTC.
UTC是我們現(xiàn)在用的時(shí)間標(biāo)準(zhǔn),GMT是老的時(shí)間計(jì)量標(biāo)準(zhǔn)。UTC是根據(jù)原子鐘來計(jì)算時(shí)間,而GMT是根據(jù)地球的自轉(zhuǎn)和公轉(zhuǎn)來計(jì)算時(shí)間。
所以,可以認(rèn)為UTC是真正的基準(zhǔn)時(shí)間,GMT相對(duì)UTC的偏差為0。
在實(shí)際中,我們的計(jì)算機(jī)中有一個(gè)硬件模塊RCT,里面會(huì)實(shí)時(shí)記錄UTC時(shí)間,該模塊有單獨(dú)的電池供電,即使關(guān)機(jī)也不影響。
有了epoch這個(gè)時(shí)間基準(zhǔn),又有了UTC這個(gè)基準(zhǔn)的基準(zhǔn),我們就可以精確地表示一個(gè)時(shí)間了。
3),DST,tzone
盡管我們已經(jīng)可以精確地表示一個(gè)時(shí)間,很多情況下,我們還是要根據(jù)地區(qū)實(shí)際情況對(duì)時(shí)間進(jìn)行一個(gè)調(diào)整,最常見的就是時(shí)區(qū),tzone,相信大家都比較熟悉。
此時(shí),當(dāng)我們說5點(diǎn)5分這個(gè)時(shí)間時(shí),還需加上是哪個(gè)時(shí)區(qū)的5點(diǎn)5分才能精確說明一個(gè)時(shí)間。
另外一個(gè)對(duì)時(shí)間做出調(diào)整的就是DST.
DST全稱是DaylightSavingTime,是說,為了充分利用日光,減少用電,人為地對(duì)時(shí)間做出一個(gè)調(diào)整,這取決于不同國家和地區(qū)的政策法規(guī)。比如說,假設(shè)你冬天7點(diǎn)天亮起床,但夏天6點(diǎn)天亮,那么在夏天到來時(shí)人為將時(shí)間加1個(gè)小時(shí),這樣就可以讓你還是覺得7點(diǎn)起床,但實(shí)際上是提前一個(gè)小時(shí)了。
那么,好奇的我們,一定要問一問,python是如何知道tzone和DST這兩個(gè)的值呢?答案是通過環(huán)境變量。
這里我們只以linux為例來說明一下。
在linux中有TZ環(huán)境變量,其值類似這樣:
CST+08EDT,M4.1.0,M10.5.0,這個(gè)字符串可以做如下解讀,用空格分開他們,分成三部分
CST+08EDT,M4.1.0,M10.5.0
1.第一部分中的CST表示時(shí)區(qū)的名字,即ChinaStandardTime,也就是我們說的北京時(shí)間,+8表示北京時(shí)間加上8小時(shí)就是UTC時(shí)間
2.第二部分EDT表示DST的名字,我們說DST是因各個(gè)國家地區(qū)的政策法規(guī)不同而不同的,EDT后面也可以像CST后面一樣加一個(gè)時(shí)間調(diào)整值,但由于我們國內(nèi)只在86年到92年實(shí)行過一段時(shí)間DST,現(xiàn)在已經(jīng)廢止,所以后面不用加調(diào)整時(shí)間。
3.第三部分表示的是實(shí)行DST的開始和結(jié)束時(shí)間,我們就不細(xì)解讀了。
4),時(shí)間的表示,獲取,轉(zhuǎn)換
time模塊中獲取時(shí)間的基本方法是
t=time.time()
它返回的是從epoch到現(xiàn)在的秒數(shù)(用浮點(diǎn)數(shù)表示),用的是UTC時(shí)間。
我們自然而然地想把這個(gè)秒數(shù)轉(zhuǎn)為年月日時(shí)分秒的形式,而這種轉(zhuǎn)換又分兩種,一種還是用UTC時(shí)間,一種用我們所在時(shí)區(qū)進(jìn)行調(diào)整后的時(shí)間。
time模塊給我們提供了兩個(gè)方法,
1.time.gmtime(t)
2.time.localtime(t)
二者都返回一個(gè)類struct_time的實(shí)例
相比用秒數(shù)表示的時(shí)間,這樣的表示更適合我們理解。
這兩個(gè)函數(shù)如果調(diào)用時(shí)不傳參數(shù),它們內(nèi)部會(huì)調(diào)用time.time(),并用返回的秒數(shù)做轉(zhuǎn)換。
相反的,python同樣提供了將這兩種struct_time轉(zhuǎn)為秒數(shù)的方法。
1.calendar.timegm()方法用來把UTC的struct_time(gmtime的返回對(duì)象)轉(zhuǎn)為從epoch開始的秒數(shù)
2.time.mktime()用來把用時(shí)區(qū)調(diào)整過的struct_time(即localtime的返回對(duì)象)對(duì)象轉(zhuǎn)為從epoch開始的秒數(shù)
也就是說mktime方法會(huì)先找到系統(tǒng)中的時(shí)區(qū)和DST信息,并利用這個(gè)信息對(duì)struct_time進(jìn)行調(diào)整后再換算成秒數(shù)。
另一種常見的需求是在時(shí)間和表示時(shí)間的字符串之間進(jìn)行轉(zhuǎn)換。
time模塊中的strftime和strptime就是做這個(gè)用的。
看名字大家就應(yīng)該知道它們的含義,
1.strftime即stringformattime,用來將時(shí)間格式化成字符串
2.strptime即stringparsetime,用來將字符串解析成時(shí)間。
需要注意的是,這里的時(shí)間都是struct_time對(duì)象。
關(guān)于怎么格式化時(shí)間,是很簡單的知識(shí),這里就借用官網(wǎng)文檔的內(nèi)容了。
除了這兩個(gè)函數(shù),time模塊中還提供了兩個(gè)簡便方法,來幫助將時(shí)間轉(zhuǎn)為字符串
asctime用來將一個(gè)struct_time對(duì)象轉(zhuǎn)為標(biāo)準(zhǔn)24字符的字符串,如下所示:
SunJun2023:21:051993
ctime方法與asctime作用相同,只不過它接收的是秒數(shù),在內(nèi)部,會(huì)先把秒數(shù)通過localtime轉(zhuǎn)為struct_time,再往后就與asctime一樣了。
以上就是time模塊的核心內(nèi)容,我嘗試用一個(gè)口訣幫助記憶這些API
time點(diǎn)time得秒數(shù)
傳入gm,localtime得struct_time
要想變回原秒數(shù)
你得傳回calendar.timegm和time.mktime
stringf和stringp
格式化時(shí)間靠哥倆
你要還是嫌費(fèi)事
1.asctime,ctime來助力
2.專門幫你轉(zhuǎn)字符串
3.前者接收struct_time
4.后者專門處理秒數(shù)
5.分工合作不費(fèi)力
學(xué)好time模塊基本功
做個(gè)時(shí)間的明白人!
下面,我們要開始學(xué)習(xí)datetime模塊。
3,datetime模塊
1),概覽
time模塊解決了時(shí)間的獲取和表示,datetime模塊則進(jìn)一步解決了快速獲取并操作時(shí)間中的年月日時(shí)分秒信息的能力。
簡單說,該模塊核心的類就三個(gè),date類表示年月日,time類表示時(shí)分秒毫秒,這里不要和time模塊搞混淆了。一句順口溜可以幫助記清這個(gè)情況:
1.time里面沒time
2.藏在datetime里
編的是不是不咋地?嗯,我也這么覺得。
datetime類就是date和time的組合。
有一點(diǎn)需要提前說明一下,time類和datetime類都有一個(gè)屬性,它的值是一個(gè)tzinfo對(duì)象,里面包含了該time或者datetime的時(shí)區(qū)信息,一般稱這個(gè)time或者datetime對(duì)象是aware的,它能夠準(zhǔn)確換算成自epoch開始的秒數(shù)。
如果該屬性設(shè)置為None,那么,這時(shí)的time對(duì)象或者datetime對(duì)象就沒有時(shí)區(qū)信息,具體它表示的是localtime還是utctime,需要我們自己在程序中去決定。
這里我們所說的localtime是指我們所在時(shí)區(qū)的時(shí)間,utctime指的就是國際標(biāo)準(zhǔn)時(shí)間,也就是格林尼治時(shí)間。下文同。
請(qǐng)記住一點(diǎn),date中是沒有時(shí)區(qū)信息的。
2),從創(chuàng)建datetime開始
創(chuàng)建datetime對(duì)象,我最常用的辦法如下
dt=datetime.datetime.fromtimestamp(time.time())
以上,time.time()獲得自epoch開始的秒數(shù),fromtimestamp方法會(huì)將這個(gè)秒數(shù)轉(zhuǎn)變成一個(gè)datetime對(duì)象。
這里有一個(gè)問題,這個(gè)datetime對(duì)象究竟是utc的還是local的?
答案是local的,這是該方法的默認(rèn)行為。如果你在fromtimestamp方法中傳入一個(gè)表示時(shí)區(qū)的參數(shù),即tzinfo對(duì)象,就會(huì)按傳入的時(shí)區(qū)信息進(jìn)行轉(zhuǎn)換。
獲得表示當(dāng)前l(fā)ocal時(shí)間的datetime對(duì)象,還有兩個(gè)簡便方法
datetime.datetime.now()
datetime.datetime.today()
以上我們得到的都是local的datetime對(duì)象,如何獲得utc的datetime對(duì)象呢?有兩個(gè)辦法
datetime.datetime.utcfromtimestamp()
datetime.datetime.utcnow()
我們還可以從字符串中創(chuàng)建datetime對(duì)象,
方法為datetime.striptime(date_string,format)
其內(nèi)部還是先調(diào)用的time模塊中的striptime方法,獲取struct_time對(duì)象,再利用struct_time對(duì)象中的年月日時(shí)分秒信息構(gòu)建datetime對(duì)象。
同樣的,datetime類也提供了strftime(),asctime(),ctime()方法,相信不說你也知道是做什么的了。
datetime類還提供了一個(gè)combine方法,用來將一個(gè)date對(duì)象和一個(gè)time對(duì)象組合成一個(gè)datetime對(duì)象。
需要注意的是,datetime模塊中出現(xiàn)timestamp時(shí),一般可將其理解成time.time()返回的秒數(shù)
3),date和time的創(chuàng)建
date對(duì)象的創(chuàng)建和datetime非常相似,
datetime.date.today()
datetime.date.fromtimestamp()都可以創(chuàng)建一個(gè)date對(duì)象。
當(dāng)然,你也可以通過構(gòu)造方法傳入年月日來創(chuàng)建date對(duì)象。
相比之下,time對(duì)象的創(chuàng)建就很有限,只能通過
datetime.time([hour[,minute[,second[,microsecond[,tzinfo]]]]])
這個(gè)方法創(chuàng)建。
4),以上三個(gè)對(duì)象的操作和timedelta類
在實(shí)際使用中,我們有一大塊需求就是對(duì)日期進(jìn)行比較和加減運(yùn)算。得益于python的操作符重載能力,python中可以方便地對(duì)
date對(duì)象之間,或者datetime對(duì)象之間進(jìn)行小于(<)比較和減法(-)操作。
注意,這里僅限于同類對(duì)象之間,而且,不包括time對(duì)象之間。
兩個(gè)date對(duì)象作減,或者兩個(gè)datetime對(duì)象之間作減,差值用一個(gè)timedelta對(duì)象表示。
同理,一個(gè)date對(duì)象或者datetime對(duì)象也可以加或者減一個(gè)timedelta對(duì)象。
一個(gè)timedelta對(duì)象含有三個(gè)屬性:days,seconds,microseconds,days屬性可以取負(fù)值,另外兩個(gè)屬性都只能是正值。
你可以用total_seconds()方法獲得一個(gè)timedelta對(duì)象的秒數(shù)表示。
兩個(gè)timedelta對(duì)象之間可加,可減,但不能做大小比較,因?yàn)檫@樣沒什么意義。
一個(gè)timedelta對(duì)象還可以與整數(shù)相乘,或通過//操作與一個(gè)整數(shù)相除。
還可以取反,或者用abs函數(shù)獲得絕對(duì)值
4,無總結(jié),不進(jìn)步
本文的目的不在于詳細(xì)說明python處理時(shí)間日期的api如何使用,而是想通過一個(gè)概覽的形式,讓大家抓住time和datetime模塊的設(shè)計(jì)結(jié)構(gòu),從而能夠清楚這些模塊提供了哪些能力,在需要的時(shí)候能夠想起來去用,至于查詳細(xì)的api,應(yīng)該是可以輕松解決的。
以上內(nèi)容為大家介紹了Python中的時(shí)間處理大總結(jié),希望對(duì)大家有所幫助,如果想要了解更多Python相關(guān)知識(shí),請(qǐng)關(guān)注IT培訓(xùn)機(jī)構(gòu):千鋒教育。http://m.2667701.com/