前幾天搞了下時間各種格式之間的轉換,記錄一下。
Python表示時間主要有兩個庫,分別是time和datetime。time模塊更接近於操作系統,所以其屬性也是和Unix timestamp相關比較多。比如其能表示的年份爲1970-2038。因爲時間戳含義就是從1970-1-1到現在的秒數,用int類型表示,int類型爲32bit,表示範圍是[-2^31+1 ~2^31-1],即[-2147483648, 2147483648],換成成年大概68年,所以最大有效期爲1970+68=2038。
如果想用更大的年份,最好用datetime。其最大年份可以用datetime.MAXYEAR查看,爲9999。
time模塊介紹
1. struct_time類。此類就是一個完整時間的元組,共有9個元素。如果調用time模塊的其他函數,如gmtime(),localtime()和strptime(),那麼返回的就是一個struct_time對象,9個元素分別爲:
屬性 | 值 |
---|---|
tm_year(年) | 如2019 |
tm_mon(月) | 如11 |
tm_mday(日) | 如31,每個月的日有區別 |
tm_hour(小時) | 0-23 |
tm_min(分) | 0-59 |
tm_sec(秒) | 0-59 |
tm_wday(周幾) | 0-6(0爲週日) |
tm_yday(一年中的第幾天) | 1-365 |
tm_isdst(是否夏令時) | 默認爲-1 |
2. time.time() 獲取當前時間的時間戳
3. time.localtime() 將時間戳轉化爲struct_time格式,時區爲當前時區
4. time.gmtime() 將時間戳轉化爲UTC時間的struct_time
5. time.mktime() 將struck_time轉化爲時間戳
6. time.sleep() 睡眠時間,單位是秒
7.time.asctime() 將struct_time表示爲這種形式"Fri Nov 08 14:47:02 2019"。默認以time.localtime()爲參數
8. print time.ctime() 將時間戳表示爲這種形式"Fri Nov 08 14:47:02 2019"。默認以time.time()爲參數
9. time.strftime(format[,t]) 將時間元組struct_time轉化爲format格式的字符串, 如果t沒有指定,那麼默認以time.localtime()爲時間。時間格式爲:
時間格式 | 含義 |
---|---|
%a | 本地(locale)簡化星期名稱 |
%A | 本地完整星期名稱 |
%b | 本地簡化月份名稱 |
%B | 本地完整月份名稱 |
%c | 本地相應的日期和時間表示 |
%d | 一個月中的第幾天(01 - 31) |
%H | 一天中的第幾個小時(24小時制,00 - 23) |
%I | 第幾個小時(12小時制,01 - 12) |
%j | 一年中的第幾天(001 - 366) |
%m | 月份(01 - 12) |
%M | 分鐘數(00 - 59) |
%p | 本地am或者pm的相應符 |
%S | 秒(01 - 61) |
%U | 一年中的星期數。(00 - 53星期天是一個星期的開始。)第一個星期天之前的所有天數都放在第0周。 |
%w | 一個星期中的第幾天(0 - 6,0是星期天) |
%W | 和%U基本相同,不同的是%W以星期一爲一個星期的開始。 |
%x | 本地相應日期 |
%X | 本地相應時間 |
%y | 去掉世紀的年份(00 - 99) |
%Y | 完整的年份 |
%Z | 時區的名字(如果不存在爲空字符) |
%% | ‘%’字符 |
如:time.strptime('%Y-%m-%d %H:%M:%S', time.localtime())
注:
“%p”只有與“%I”配合使用纔有效果。
當使用strptime()函數時,只有當在這年中的週數和天數被確定的時候%U和%W纔會被計算。
10. time.strptime() 於time.strftime()相反,這個函數將字符串時間轉化爲時間元組struct_time。
如: time.strptime('2019-10-18 16:04:36', '%Y-%m-%d %H:%M:%S')
三者關係如圖:
datetime模塊介紹
datetime功能相比time更加豐富,模塊下又包含了幾個類:
類名 | 功能說明 |
---|---|
date | 日期對象 |
time | 時間對象 |
datetime | 日期時間對象 |
datetime_CAPI | 日期時間對象C語言接口 |
timedelta | 時間間隔,即兩個時間點之間的長度 |
tzinfo | 時區信息對象 |
1. date類
date類基本元素由年月日組成。可以通過datetime.date.max和datetime.date.min查看其表示的範圍
1) 構造函數datetime。可以這樣搞
d = datetime.date(2019,8,7)
print d
打印2019-08-07,注意的是這個2019-08-07並不是字符串,而是datetime類的對象
2) datetime.date.today() 返回當前日期,如:
datetime.date.today()
Out[217]: datetime.date(2019, 11, 8)
3)datetime.date.fromtimestamp() 根據給定的時間戳,返回一個date對象, 如:
datetime.date.fromtimestamp(1569895835)
Out[218]: datetime.date(2019, 10, 1)
4) datetime.date.weekday() 參數是一個datetime對象,返回今天是一週的第幾天,從週一(0)開始算
t = datetime.date.today() //今天是週五
datetime.date.weekday(t)
Out[221]: 4
5) datetime.date.isoweekday() 以date對象爲參數,返回今天是周幾,週一返回1,週二返回2...
t = datetime.date.today() //今天是週五
datetime.date.isoweekday(t)
Out[223]: 5
6) datetime.date.isocalendar() 以date對象爲參數,返回一個元組,包括年,今天是本年第幾周,今天是星期幾
t = datetime.date.today() //今天是2019.11.8
datetime.date.isocalendar(t)
Out[224]: (2019, 45, 5)
7) datetime.date.strftime(format) 參數爲格式化的字符串,比如'%Y-%m-%d %H:%M:%S',返回值是一個字符串
d = datetime.date(2019,8,7)
format = '%Y-%m-%d %H:%M:%S'
print d.strftime(format)
8)datetime.date.replace() 參數爲要替換的新值,返回替換後的datetime對象
d = datetime.date(2019,8,7)
format = '%Y-%m-%d %H:%M:%S'
d1 = d.replace(2018)
print d1.strftime(format) //2018-08-07 00:00:00
d1 = d.replace(month=5)
print d1.strftime(format) //2019-05-07 00:00:00
9) datetime.date.year month day 輸出當前datatime對象的年月日
d = datetime.date(2019,8,7)
print d.year, d.month, d.day //2019 8 7
也可以通過getattribute方法來獲取屬性值:
d = datetime.date(2019,1,1)
print d.__getattribute__('year'), d.__getattribute__('month'), d.__getattribute__('day')
10) datetime.date.isoformat() 返回yyyy-mm-dd格式的字符串
print datetime.date(2019,8,7).isoformat() //2019-08-07
11) datetime.date.timetuple() 返回time模塊的struct_time格式元組
d = datetime.date(2019,8,7)
print d.timetuple() // time.struct_time(tm_year=2019, tm_mon=8, tm_mday=7, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=2, tm_yday=219, tm_isdst=-1)
12) datetime.date.toordinal() 返回公元元歷(1年1月1日)開始到現在的天數。
d = datetime.date(2019,1,1)
print d.toordinal() //737060。不知道它怎麼算的,如果1年1月1日是1,那麼2019.1.1和這個日期相差了2018 * 365 天,結果應該是736570而不是737060,理解有問題
13) datetime.date.fromordinal() toordinal的相反操作,傳入一個天數,返回日期
d = datetime.date(2019,1,1)
a = d.toordinal()
print datetime.date.fromordinal(a)
14)日期的比較,例子如下:
d1 = datetime.date(2019,1,1)
d2 = datetime.date(2019,1,2)
d3 = datetime.date(2019,1,1)
print d1.__ge__(d3) //True
print d1.__gt__(d2) //False
print d1.__eq__(d2) //False
print d1.__eq__(d3) //True
print d1.__le__(d2) //True
print d2.__lt__(d3) //False
15) 能表示的最大和最小值min(),max()
print datetime.date.min //0001-01-01
print datetime.date.max //9999-12-31
16) 能表示的最小單位datetime.date.resolution
print datetime.date.resolution //1 day, 0:00:00
2. time類
datetime.date類最小單位爲天,datetime.time類爲毫秒
time類由小時,分鐘,秒,微妙和tzinfo組成。類似的,其構造函數爲:
time([hour[, minute[, second[, microsecond[, tzinfo]]]]])
1) datetime.time(15,23,45,368) 返回值爲time類的對象
datetime.time(hour=15,minute=23,second=45,microsecond=36800) //結果爲15:23:45.036800
2) 獲取time對象的屬性值
d = datetime.time(hour=15,minute=23,second=45,microsecond=36800)
print d.hour,d.minute,d.second,d.microsecond,d.tzname() //輸出結果爲15 23 45 36800 None
與datetime.date類似,也可以通過getattribute方法獲取, 如:
d = datetime.time(hour=15,minute=23,second=45,microsecond=36800)
print d.__getattribute__('hour'), d.__getattribute__('minute'), d.__getattribute__('second'), d.__getattribute__('microsecond')
3) 按照格式轉爲爲字符串對象datetime.time.strftime('%H:%M:%S')
d = datetime.time(hour=15,minute=23,second=45,microsecond=36800)
print d.strftime('%H:%M:%S')
4)查看時區信息d.tzname()
d.tzname()
5) 替換某個時間datetime.time.replace(),與date類似
d = datetime.time(hour=15,minute=23,second=45,microsecond=36800)
print d.strftime('%H:%M:%S')
d1 = d.replace(hour=19)
print d1 //19:23:45.036800
d1 = d.replace(minute=35)
print d1 //15:35:45.036800
d1 = d.replace(second=36)
print d1 //15:23:36.036800
d1 = d.replace(microsecond=66000)
print d1 //15:23:45.066000
6) datetime.date.isoformat() 返回'%H:%M:%S'格式的字符串
d = datetime.time(hour=15,minute=23,second=45,microsecond=36800)
print d.isoformat() //15:23:45.036800
7) 最大最小值min, max
print datetime.time.min //00:00:00
print datetime.time.max //23:59:59.999999
8) 能表示的最小單位datetime.time.resolution
print datetime.time.resolution //0:00:00.000001
3. datetime類
datetime.datetime類是date類和time類的合體,函數的類型和含義都很類似,只是相較於date或者time進行了擴充。比如說datetime類的構造函數:
datetime(self, year, month, day, hour=None, minute=None, second=None, microsecond=None, tzinfo=None)
1) datetime.resolution 能表示的最小時間單位
d = datetime.datetime(2019,11,11,16,33,24,666000,)
print d.resolution //0:00:00.000001
2) datetime.date() 獲取表示日期的部分
d = datetime.datetime(2019,11,11,16,33,24,666000,)
print d.date() //2019-11-11
3) datetime.time() 獲取表示時間的部分:
d = datetime.datetime(2019,11,11,16,33,24,666000,)
print d.time()
4)datetime.isoformat() 返回iso格式時間串
d = datetime.datetime(2019,11,11,16,33,24,666000,)
print d.isoformat() //2019-11-11T16:33:24.666000
5) datetime.utcfromtimestamp(timestamp) 參數爲時間戳,返回值爲datetime對象
print datetime.utcfromtimestamp(time.time()) //返回utc時間2019-11-12 08:04:54.660000,當前時間爲2019-11-12 16:04:54
6)datetime.replace 用法date和time
7)datetime.strftime() 將datetime時間格式化爲字符串
d = datetime.datetime(2019,11,11,16,33,24,666000,)
print d.strftime('%Y-%m-%d %H:%M:%S') //2019-11-11 16:33:24
8) datetime.strptime() 參數爲時間字符串,和時間格式,返回datetime對象
print datetime.datetime.strptime('2019-3-26 7:18:16', format) //2019-03-26 07:18:16
9) datetime.timetuple() 將datetime對象轉化爲time模塊的struct_time
d = datetime.datetime(2019,11,11,16,33,24,666000,)
print d.timetuple() //time.struct_time(tm_year=2019, tm_mon=11, tm_mday=11, tm_hour=16, tm_min=33, tm_sec=24, tm_wday=0, tm_yday=315, tm_isdst=-1)
10) datetime.today() 獲取今天的時間,返回值爲datetime對象
print datetime.datetime.today() //2019-11-12 11:43:35.904000
11) datetime.weekday(),fromordinal(), toordinal(), isoweekday(), isocalendar() 同date
12) datetime.utcnow() 返回當前標準時區的時間對象
print datetime.datetime.utcnow() //返回值爲2019-11-12 03:52:00.943000;當前北京時間爲2019-11-12 11:52:00.943000
13)可以通過datetime.year/month/day/hour/minute/second/microsecond 來獲取datetime對象的具體某個時間值:
d = datetime.datetime(2019,11,11,16,33,24,666000,)
print d.month, d.hour, d.second
14) datetime.fromtimestamp() 參數爲timestamp, 返回datetime對象
datetime.datetime.fromtimestamp(time.time()) //返回2019-11-12 16:06:16.437000,即當前時間
15)datetime.ctime() 同date類
16)datetime.astimezone() 傳入參數是一個timezone,根據時區設置,返回datetime對象。需要注意的是,轉化前的datetime是需要有時區信息纔可以的。
d = datetime.datetime(2019,11,11,16,33,24,666000,tzinfo=UTC(8))
print d.astimezone(UTC(7)) //2019-11-11 15:33:24.666000+07:00, 此處UTC是一個自己創建的類,詳見tzinfo章節
17)datetime.combine() 將date和time組合成datetime對象
a1 = datetime.date(2019,1,1)
d1 = datetime.time(hour=15,minute=23,second=45,microsecond=36800)
datetime.datetime.combine(a1, d1) //2019-01-01 15:23:45.036800
18) datetime.now() 返回當前時間的datetime對象(帶時區)
print datetime.datetime.now() //2019-11-12 17:22:00.501000
19) datetime.tzname(),datetime.utcoffset, datetime.dst() 見tzinfo
20) datetime.utctimetuple() 創建utc時間的time模塊的struct_time結構
d = datetime.datetime(2019,11,11,16,33,24,666000,tzinfo=UTC(8))
print d.utctimetuple()
21) 類似於date模塊,datetime模塊也可以用__gt__等進行比較
d = datetime.datetime(2019,11,11,16,33,24,666000,tzinfo=UTC(8))
d1 = datetime.datetime(2019,11,12,16,33,24,666000,tzinfo=UTC(8))
print d1.__gt__(d) //返回True
3. timedelta類
timedelta類用來進行日期時間的運算,最大單位是天,最小單位是微妙。其構造函數爲:
datetime.timedelta(days=0, seconds=0, microseconds=0,milliseconds=0, minutes=0, hours=0, weeks=0)
1) timedelta的使用
timedelta中參數的值分爲正負,正值爲加,負值爲減。比如先創建了一個datetime對象d
d = datetime.datetime(2019,11,11,16,33,24,666000,tzinfo=UTC(8))
如果要計算時間d之後一天,一小時,一分鐘,一秒,一毫秒和一微妙後的時間是多少就可以這麼做:
d = datetime.datetime(2019,11,11,16,33,24,666000,tzinfo=UTC(8))
print d + datetime.timedelta(days=-1,hours=1,minutes=1,seconds=1,microseconds=1,milliseconds=1) //2019-11-10 17:34:25.667001+08:00
2) timedelta.days 返回timedelta有多少整天,不包含小時和分鐘, 如:
td = datetime.timedelta(days=13,hours=2,minutes=3,seconds=1,microseconds=1,milliseconds=1)
print td.days //返回13
4. tzinfo類
tzinfo類是一個虛擬類,如果要使用的話,需要創建一個子類,並實現相關方法。需要重寫的方法有name(),utcoffset(),dst()這三個方法。
class UTC(tzinfo): """UTC""" def __init__(self,offset = 0): self._offset = offset def utcoffset(self, dt): return timedelta(hours=self._offset) def tzname(self, dt): return "UTC+%s" % self._offset def dst(self, dt): return timedelta(hours=self._offset)
創建一個北京時間的datetime
d = datetime.datetime(2019,11,11,16,33,24,666000,tzinfo=UTC(8)) print d.tzname(), d.utcoffset(), d.dst() #打印結果:UTC+8 8:00:00 8:00:00
需要注意的是,tzinfo是要和datetime一起使用的,如果直接創建一個UTC對象,打印tzname需要同時傳入一個datetime對象纔可以,看定義就比較明白了。
如果不想自己實現tzinfo,可以用現成的庫pytz
pytz中可以直接通過pytz.timezone()獲取一個對象,比如要獲取上海的,可以是:
pytz.timezone('Asia/Shanghai')
5. 實用舉例
1. 獲取Linux時間戳
1) 獲取當前時間的時間戳
print time.time()
2)獲取特定時間的時間戳
d = datetime.datetime(2019,11,11,16,33,24,666000,tzinfo=pytz.UTC) print time.mktime(d.timetuple()) #1573461204.0
或者這樣
timeStr = '2019-10-01 10:10:35' //指定一個時間
timearray = time.strptime(timeStr, '%Y-%m-%d %H:%M:%S') //將時間按照格式轉化爲time.struct_time格式
print timestemp = time.mktime(timearray) //生成時間戳1569895835.0
廖雪峯老師的網站上有一種方法是調用
>>> dt = datetime(2015, 4, 19, 12, 20) # 用指定日期時間創建datetime
>>> dt.timestamp() # 把datetime轉換爲timestamp
但是這種方法我這邊沒有不成功,可能是庫不對
2. 獲取時間字符串
1) 利用time模塊獲取當前時間字符串
format = '%Y-%m-%d %H:%M:%S' print time.strftime(format)
這種方法利用了strftime默認以time.localtime()爲第二個參數,獲取當前時間
2) 利用datetime模塊獲取當前時間字符串
format = '%Y-%m-%d %H:%M:%S' dt = datetime.datetime.now() print dt.strftime(format)
datetime.now()返回的是datetime對象,再利用strftime轉化爲字符串
3)將timestamp轉化爲時間字符串
print datetime.datetime.fromtimestamp(timestamp)
也可以利用time模塊轉化爲字符串格式
format = '%Y-%m-%d %H:%M:%S' timestamp = 1573461204 print time.strftime(format, time.localtime(timestamp))
4)時區轉化
有一點需要明確,就是timestamp是和時區沒有關係的,就是說,無論哪個時區,時間確定了,那麼時間戳就是固定的。
首先定義一下epoch time,對於格林威治時間,epoch time就是1970年01月01日00時00分00秒,對於北京時間就是1970年01月01日08時00分00秒
如果現在是北京時間2019-11-29 15:00:00,北京時間屬於UTC+8時區,那麼此時,UTC+0時區的時間就是2019-11-29 07:00:00。此時北京時間的時間戳爲2019-11-29 15:00:00 - 1970-1-1 08:00:00的秒數,UTC+0時間的時間戳爲2019-11-29 07:00:00 - 1970-1-1 07:00:00的秒數,二者是相等的
反過來,對於一個給定的timestamp,對於不同的時區,就是不同的時間,因爲不同的時間epoch time就是不同的了
a. 可以通過datetime的函數astimezone轉化
dt = datetime.datetime.now().replace(tzinfo=pytz.timezone('Asia/Shanghai')) print dt #print 2019-11-29 15:34:49.802000+08:06 print dt.astimezone(pytz.timezone('UTC')) #print 2019-11-29 07:28:49.802000+00:00