在 Python 中是沒有原生數(shù)據(jù)類型支持時間的,日期與時間的操作需要借助三個模塊,分別是 time、datetime、calendar。
在學(xué)習(xí)之前,還有一些術(shù)語要補充一下,這些術(shù)語你當(dāng)成慣例即可。這里在 Python 官方文檔中也有相關(guān)說明,不過信息比較多,橡皮擦為你摘錄必須知道的一部分。
epoch(紀(jì)元) 是時間開始的點,其值取決于平臺。
對于 Unix, epoch(紀(jì)元) 是 1970年1月1日00:00:00(UTC)。要找出給定平臺上的 epoch ,請使用 time.gmtime(0) 進行查看,例如橡皮擦電腦顯示:
time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=0)
術(shù)語 紀(jì)元秒數(shù) 是指自 epoch (紀(jì)元)時間點以來經(jīng)過的總秒數(shù),通常不包括閏秒。 在所有符合 POSIX 標(biāo)準(zhǔn)的平臺上,閏秒都不會記錄在總秒數(shù)中。
程序員中常把 紀(jì)元秒數(shù) 稱為 時間戳。
該模塊核心為控制時鐘時間。
該函數(shù)獲取時鐘的基本信息,得到的值因不同系統(tǒng)存在差異,函數(shù)原型比較簡單:
time.get_clock_info(name)
其中 name 可以取下述值:
該函數(shù)的返回值具有以下屬性:
import time
available_clocks = [
('clock', time.clock),
('monotonic', time.monotonic),
('perf_counter', time.perf_counter),
('process_time', time.process_time),
('time', time.time),
]
for clock_name, func in available_clocks:
print('''
{name}:
adjustable : {info.adjustable}
implementation: {info.implementation}
monotonic : {info.monotonic}
resolution : {info.resolution}
current : {current}
'''.format(
name=clock_name,
info=time.get_clock_info(clock_name),
current=func()))
運行結(jié)果如下圖所示。
上圖顯示橡皮擦的計算機在 clock 與 perf_counter 中,調(diào)用底層 C 函數(shù)是一致的。
在 Python 中通過 time.time() 函數(shù)獲取紀(jì)元秒數(shù),它可以把從 epoch 開始之后的秒數(shù)以浮點數(shù)格式返回。
import time
print(time.time())
# 輸出結(jié)果 1615257195.558105
時間戳大量用于計算時間相關(guān)程序,屬于必須掌握內(nèi)容。
時間戳主要用于時間上的方便計算,對于人們閱讀是比較難理解的,如果希望獲取可讀時間,使用 ctime() 函數(shù)獲取。
import time
print(time.ctime())
# 輸出內(nèi)容:Tue Mar 9 10:35:51 2021
如何將時間戳轉(zhuǎn)換為可讀時間,使用 localtime 函數(shù)即可。
localtime = time.localtime(time.time())
print("本地時間為 :", localtime)
輸出結(jié)果為 <class 'time.struct_time'> 類型數(shù)據(jù),后文將對其進行格式化操作:
本地時間為 : time.struct_time(tm_year=2021, tm_mon=3, tm_mday=9, tm_hour=10, tm_min=37, tm_sec=27, tm_wday=1, tm_yday=68, tm_isdst=0)
上述代碼中的時間戳最小值是 0,最大值由于 Python 環(huán)境和操作系統(tǒng)決定,我本地 64 位操作系統(tǒng)進行測試的時候,得到的數(shù)據(jù)如下:
import time
localtime = time.localtime(0)
print("時間為 :", localtime)
# 時間為 : time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=8, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=0)
localtime = time.localtime(32536799999)
print("時間為 :", localtime)
# 時間為 : time.struct_time(tm_year=3001, tm_mon=1, tm_mday=19, tm_hour=15, tm_min=59, tm_sec=59, tm_wday=0, tm_yday=19, tm_isdst=0)
localtime = time.localtime(99999999999)
print("時間為 :", localtime)
# OSError: [Errno 22] Invalid argument
print(type(localtime))
monotonic time 從系統(tǒng)啟動開始計時,從 0 開始單調(diào)遞增。
操作系統(tǒng)的時間可能不是從 0 開始,而且會因為時間出錯而回調(diào)。
該函數(shù)原型如下,不需要任何參數(shù),返回一個浮點數(shù),表示小數(shù)秒內(nèi)的單調(diào)時鐘的值:
time.monotonic()
測試代碼如下:
print("單調(diào)時間",time.monotonic())
# 輸出:單調(diào)時間 12279.244
time() 函數(shù)返回的是紀(jì)元秒數(shù)(時間戳), clock() 函數(shù)返回的是處理器時鐘時間。
該函數(shù)函數(shù)的返回值:
需要注意的是 Python 3.8 已移除 clock() 函數(shù),用 time.perf_counter() 或 time.process_time() 方法替代。
t0 = time.clock()
# 運行一段代碼
print(time.clock() - t0, "程序運行時間")
我使用的 Python 版本較高,提示異常如下:
time.clock has been deprecated in Python 3.3 and will be removed from Python 3.8: use time.perf_counter or time.process_time instead t0 = time.clock()
perf_counter() 函數(shù)的 epoch (紀(jì)元)是未定義的。一般使用該函數(shù)都是為了比較和計算,不是為了用作絕對時間,該點需要注意下。
該函數(shù)用于測量較短持續(xù)時間的具有最高有效精度的時鐘,包括睡眠狀態(tài)消耗的時間,使用兩次調(diào)用才會有效。
測試代碼如下:
t0 = time.perf_counter()
# 運行一段代碼
for i in range(100000):
pass
print("程序運行時間", time.perf_counter() - t0)
與其類似的函數(shù)有 perf_counter_ns()、process_time()、process_time_ns(),具體可以查詢手冊進行學(xué)習(xí),先掌握 perf_counter() 函數(shù)即可。
上文已經(jīng)涉及了時間組件相關(guān)的知識,通過 localtime 得到的 struct_time 類型的數(shù)據(jù)。
這里涉及到的函數(shù)有 gmtime() 返回 UTC 中的當(dāng)前時間,localtime() 返回當(dāng)前時區(qū)對應(yīng)的時間,mktime() 接收 struce_time 類型數(shù)據(jù)并將其轉(zhuǎn)換成浮點型數(shù)值,即時間戳。
print("*"*10)
print(time.gmtime())
print("*"*10)
print(time.localtime())
print("*"*10)
print(time.mktime(time.localtime()))
struct_time 類型包含的內(nèi)容
上述代碼返回的數(shù)據(jù)格式為:
time.struct_time(tm_year=2021, tm_mon=3, tm_mday=9, tm_hour=12, tm_min=50, tm_sec=35, tm_wday=1, tm_yday=68, tm_isdst=0)
其中各值可以根據(jù)英文含義進行理解 :tm_year 年份(range[1,12]),tm_mon 月份(range[1,12]),tm_mday 天數(shù)(range[1,31]),tm_hour 天數(shù)(range[0,23]),tm_min 分鐘 (range[0,59]), tm_sec 秒數(shù) (range[0,61]), tm_wday 星期 (range[0,6],0 是星期日), tm_yday 一年中的一天(range[1,366] ),tm_isdst 在夏令時生效時設(shè)置為 1,而在夏令時不生效時設(shè)置為 0,值-1 表示這是未知的。
strptime() 和 strftime() 函數(shù)可以使時間值在 struct_time 表示和字符串表示之間相互轉(zhuǎn)換。
對于 strftime 函數(shù),其中的參數(shù)參考官方即可。
x = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
print(x)
這里的學(xué)習(xí),沒有什么難度大的點,孰能生巧的知識。
strptime 函數(shù)的應(yīng)用
x = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
print(x)
# 方向操作,字符串格式化成 time.struct_time
struct_time = time.strptime(x, "%Y-%m-%d %H:%M:%S")
print(struct_time)
需要記憶的就是 strftime 與 strptime 函數(shù)只有中間的字符不同,一個是 f ,另一個是 p。
對于 time 模塊,sleep 函數(shù)屬于必備知識點,但是太常用了,你肯定已經(jīng)很熟悉了。
對于模塊的學(xué)習(xí),最權(quán)威的就是官方手冊了——time 模塊。
該模塊比 time 模塊高級了很多,并且對 time 模塊進行了封裝,提供的功能更加強大了。
在 datetime 模塊中,Python 提供了 5 個主要的對象類,分別如下:
優(yōu)先展示部分該類的屬性和方法,都是記憶層面的知識。
測試代碼如下:
from datetime import date
import time
print('date.min:', date.min)
print('date.max:', date.max)
print('date.resolution:', date.resolution)
print('date.today():', date.today())
print('date.fromtimestamp():', date.fromtimestamp(time.time()))
輸出結(jié)果:
date.min: 0001-01-01
date.max: 9999-12-31
date.resolution: 1 day, 0:00:00
date.today(): 2021-03-09
date.fromtimestamp(): 2021-03-09
date 對象的屬性和方法
通過下述代碼創(chuàng)建一個 date 對象:
d = date(year=2021,month=3,day=9)
print(d)
該對象具備下述屬性和方法:
time 類定義的類屬性:
通過其構(gòu)造函數(shù)可以創(chuàng)建一個 time 對象。
t = time(hour=20, minute=20, second=40)
print(t)
time 類提供的實例方法和屬性:
該類是 date 類與 time 類的結(jié)合體,很多屬性和方法前文已經(jīng)介紹,再補充一些比較常用的屬性和方法。
獲取當(dāng)前的日期與時間:
from datetime import datetime
dt = datetime.now()
print(dt)
獲取時間戳:
dt = datetime.now()
# 使用 datetime 的內(nèi)置函數(shù) timestamp()
stamp = datetime.timestamp(dt)
print(stamp)
通過 timedelta 函數(shù)返回一個 timedelta 時間間隔對象,該函數(shù)沒有必填參數(shù),如果寫入一個整數(shù)就是間隔多少天的的意思。
# 間隔 10 天
timedelta(10)
# 跨度為1 周
timedelta(weeks=1)
兩個時間間隔對象可以彼此之間相加或相減,返回的仍是一個時間間隔對象。
一個 datetime 對象如果減去一個時間間隔對象,那么返回的對應(yīng)減去之后的 datetime 對象,然后兩個 datetime 對象如果相減,返回的是一個時間間隔對象。
更多關(guān)于 datetime 類使用的知識,可以參考官方手冊。
此模塊的函數(shù)都是日歷相關(guān)的,例如打印某月的字符月歷。
calendar 模塊定義了 Calendar 類,它封裝了值的計算, 例如給定月份或年份中周的日期。通過 TextCalendar 和 HTMLCalendar 類可以生成預(yù)格式化的輸出。
基本代碼:
import calendar
c = calendar.TextCalendar(calendar.SUNDAY)
c.prmonth(2021, 3)
上述代碼,默認是從周日開始的,輸出結(jié)果:
March 2021
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
該模塊使用頻率較低,詳細使用參考地址 進行學(xué)習(xí)。
本篇博客為大家補充了一下時間和日期庫的相關(guān)知識,希望能進入你的收藏夾。
作者:夢想橡皮擦
原文鏈接:https://blog.csdn.net/hihell/article/details/114413866
秒 在1967年的第13屆國際度量衡會議上決定以原子時定義的秒作為時間的國際標(biāo)準(zhǔn)單位:銫133原子基態(tài)的兩個超精細能階間躍遷對應(yīng)輻射的9,192,631,770個周期的持續(xù)時間, 起始歷元定在1958年1月1日0時。
原子鐘是一種時鐘,它以原子共振頻率標(biāo)準(zhǔn)來計算及保持時間的準(zhǔn)確。原子鐘是世界上已知最準(zhǔn)確的時間測量和頻率標(biāo)準(zhǔn)。
GMT 格林威治標(biāo)準(zhǔn)時間(Greenwich Mean Time),是指位于倫敦郊區(qū)的皇家格林威治天文臺的標(biāo)準(zhǔn)時間,因為本初子午線(Prime meridian)被定義為通過那里的經(jīng)線。GMT也叫世界時UT。
UTC 協(xié)調(diào)世界時間(Coordinated Universal Time), 又稱世界標(biāo)準(zhǔn)時間,基于國際原子鐘,誤差為每日數(shù)納秒。協(xié)調(diào)世界時的秒長與原子時的秒長一致,在時刻上則要求盡量與世界時接近(規(guī)定二者的差值保持在 0.9秒以內(nèi))。
閏秒 不只有閏年,還有閏秒。閏秒是指為保持協(xié)調(diào)世界時接近于世界時時刻,由國際計量局統(tǒng)一規(guī)定在年底或年中(也可能在季末)對協(xié)調(diào)世界時增加或減少1秒的調(diào)整。由于地球自轉(zhuǎn)的不均勻性和長期變慢性(主要由潮汐摩擦引起的),會使世界時(民用時)和原子時之間相差超過到±0.9秒時,就把世界時向前撥1秒(負閏秒,最后一分鐘為59秒)或向后撥1秒(正閏秒,最后一分鐘為61秒);閏秒一般加在公歷年末或公歷六月末。
時區(qū) 是地球上的區(qū)域使用同一個時間定義。有關(guān)國際會議決定將地球表面按經(jīng)線從南到北,劃分成24個時區(qū),并且規(guī)定相鄰區(qū)域的時間相差1小時。當(dāng)人們跨過一個區(qū)域,就將自己的時鐘校正1小時(向西減1小時,向東加1小時),跨過幾個區(qū)域就加或減幾小時。比如我大中國處于東八區(qū),表示為GMT+8。
夏令時 (Daylight Saving Time:DST),又稱日光節(jié)約時制、日光節(jié)約時間或夏令時間。這是一種為節(jié)約能源而人為規(guī)定地方時間的制度,在夏天的時候,白天的時間會比較長,所以為了節(jié)約用電,因此在夏天的時候某些地區(qū)會將他們的時間定早一小時,也就是說,原本時區(qū)是8點好了,但是因為夏天太陽比較早出現(xiàn),因此把時間向前挪,在原本8點的時候,訂定為該天的9點(時間提早一小時)~如此一來,我們就可以利用陽光照明,省去了花費電力的時間,因此才會稱之為夏季節(jié)約時間!
Unix時間戳 指的是從協(xié)調(diào)世界時(UTC)1970年1月1日0時0分0秒開始到現(xiàn)在的總秒數(shù),不考慮閏秒。
在 Python 文檔里,time是歸類在Generic Operating System Services中,換句話說, 它提供的功能是更加接近于操作系統(tǒng)層面的。通讀文檔可知,time 模塊是圍繞著 Unix Timestamp 進行的。
該模塊主要包括一個類 struct_time,另外其他幾個函數(shù)及相關(guān)常量。需要注意的是在該模塊中的大多數(shù)函數(shù)是調(diào)用了所在平臺C library的同名函數(shù), 所以要特別注意有些函數(shù)是平臺相關(guān)的,可能會在不同的平臺有不同的效果。另外一點是,由于是基于Unix Timestamp,所以其所能表述的日期范圍被限定在 1970 – 2038 之間,如果你寫的代碼需要處理在前面所述范圍之外的日期,那可能需要考慮使用datetime模塊更好。
獲取當(dāng)前時間和轉(zhuǎn)化時間格式
>>> import time
>>> time.time()
1473386416.954
>>> time.ctime()
'Fri Sep 09 10:00:25 2016'
>>> time.ctime(time.time())
'Fri Sep 09 10:28:08 2016'
>>> time.asctime()
'Fri Sep 09 10:22:40 2016'
>>> time.asctime(time.localtime())
'Fri Sep 09 10:33:00 2016'
>>> time.localtime()
time.struct_time(tm_year=2016, tm_mon=9, tm_mday=9, tm_hour=10, tm_min=1, tm_sec=19, tm_wday=4, tm_yday=253, tm_isdst=0)
>>> time.localtime(time.time())
time.struct_time(tm_year=2016, tm_mon=9, tm_mday=9, tm_hour=10, tm_min=19, tm_sec=11, tm_wday=4, tm_yday=253, tm_isdst=0)
>>> time.gmtime()
time.struct_time(tm_year=2016, tm_mon=9, tm_mday=9, tm_hour=2, tm_min=13, tm_sec=10, tm_wday=4, tm_yday=253, tm_isdst=0)
>>> time.gmtime(time.time())
time.struct_time(tm_year=2016, tm_mon=9, tm_mday=9, tm_hour=2, tm_min=15, tm_sec=35, tm_wday=4, tm_yday=253, tm_isdst=0)
struct_time共有9個元素,其中前面6個為年月日時分秒,后面三個分別代表的含義為:
time.mktime()
將一個以struct_time格式轉(zhuǎn)換為時間戳
>>> time.mktime(time.localtime())
1473388585.0
time.strftime(format[,t]) 把一個struct_time時間轉(zhuǎn)化為格式化的時間字符串。如果t未指定,將傳入time.localtime()。如果元組中任何一個元素越界,ValueError的錯誤將會被拋出。
>>> time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
'2016-09-09 10:54:21'
time.strptime(string[,format])
把一個格式化時間字符串轉(zhuǎn)化為struct_time。實際上它和strftime()是逆操作。
>>> time.strptime(time.ctime())
time.struct_time(tm_year=2016, tm_mon=9, tm_mday=9, tm_hour=11, tm_min=0, tm_sec=4, tm_wday=4, tm_yday=253, tm_isdst=-1)
time.sleep(secs)
線程推遲指定的時間運行。單位為秒。
time.clock()
這個需要注意,在不同的系統(tǒng)上含義不同。在UNIX系統(tǒng)上,它返回的是“進程時間”,它是用秒表示的浮點數(shù)(時間戳)。而在WINDOWS中,第一次調(diào)用,返回的是進程運行的實際時間。而第二次之后的調(diào)用是自第一次調(diào)用以后到現(xiàn)在的運行時間。(實際上是以WIN32上QueryPerformanceCounter()為基礎(chǔ),它比毫秒表示更為精確)
import time
time.sleep(1)
print("clock1:%s" % time.clock())
time.sleep(1)
print("clock2:%s" % time.clock())
time.sleep(1)
print("clock3:%s" % time.clock())
運行結(jié)果為:
clock1:1.57895443216e-06
clock2:1.00064381867
clock3:2.00158724394
其中第一個clock()輸出的是程序運行時間,第二、三個clock()輸出的都是與第一個clock的時間間隔
import time
print(time.timezone)
print(time.tzname)
print(time.tzname[0].decode("GBK"))
print(time.tzname[1].decode("GBK"))
運行結(jié)果
-28800
('\xd6\xd0\xb9\xfa\xb1\xea\xd7\xbc\xca\xb1\xbc\xe4', '\xd6\xd0\xb9\xfa\xcf\xc4\xc1\xee\xca\xb1')
中國標(biāo)準(zhǔn)時間
中國夏令時
datetime 比 time 高級了不少,可以理解為 datetime 基于 time 進行了封裝,提供了更多實用的函數(shù)。
datetime模塊定義了下面這幾個類:
注:上面這些類型的對象都是不可變(immutable)的。
date類定義了一些常用的類方法與類屬性:
from datetime import date
import time
print('date.max:', date.max)
print('date.min:', date.min)
print('date.resolution:', date.resolution)
print('date.today():', date.today())
print('date.fromtimestamp():', date.fromtimestamp(time.time()))
執(zhí)行結(jié)果:
date.max: 9999-12-31
date.min: 0001-01-01
date.resolution: 1 day, 0:00:00
date.today(): 2016-09-12
date.fromtimestamp(): 2016-09-12
date提供的實例方法和屬性:
from datetime import date
today = date.today()
print('today:', today)
print('.year:', today.year)
print('.month:', today.month)
print('.replace():', today.replace(year=2017) )
print('.weekday():', today.weekday())
print('.isoweekday():', today.isoweekday())
print('.isocalendar():', today.isocalendar())
print('.isoformat():', today.isoformat())
print('.strftime():', today.strftime('%Y-%m-%d') )
print('.toordinal():', today.toordinal())
執(zhí)行結(jié)果:
today: 2016-09-12
.year: 2016
.month: 9
.replace(): 2017-09-12
.weekday(): 0
.isoweekday(): 1
.isocalendar(): (2016, 37, 1)
.isoformat(): 2016-09-12
.strftime(): 2016-09-12
.toordinal(): 736219
date還對某些操作進行了重載,它允許我們對日期進行如下一些操作:
time類的構(gòu)造函數(shù)如下:(其中參數(shù)tzinfo,它表示時區(qū)信息。)
class datetime.time(hour[, minute[, second[, microsecond[, tzinfo]]]])
time類定義的類屬性:
time類提供的實例方法和屬性:
像date一樣,也可以對兩個time對象進行比較,或者相減返回一個時間間隔對象。這里就不提供例子了。
datetime是date與time的結(jié)合體,包括date與time的所有信息。它的構(gòu)造函數(shù)如下:datetime.datetime(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]]),各參數(shù)的含義與date、time的構(gòu)造函數(shù)中的一樣,要注意參數(shù)值的范圍。
datetime類定義的類屬性與方法:
from datetime import datetime
import time
print('datetime.max:', datetime.max)
print('datetime.min:', datetime.min)
print('datetime.resolution:', datetime.resolution)
print('today():', datetime.today())
print('now():', datetime.now())
print('utcnow():', datetime.utcnow())
print('fromtimestamp(tmstmp):', datetime.fromtimestamp(time.time()))
print('utcfromtimestamp(tmstmp):', datetime.utcfromtimestamp(time.time()))
運行結(jié)果:
datetime.max: 9999-12-31 23:59:59.999999
datetime.min: 0001-01-01 00:00:00
datetime.resolution: 0:00:00.000001
today(): 2016-09-12 19:57:00.761000
now(): 2016-09-12 19:57:00.761000
utcnow(): 2016-09-12 11:57:00.761000
fromtimestamp(tmstmp): 2016-09-12 19:57:00.761000
utcfromtimestamp(tmstmp): 2016-09-12 11:57:00.761000
datetime類提供的實例方法與屬性(很多屬性或方法在date和time中已經(jīng)出現(xiàn)過,在此有類似的意義,這里只羅列這些方法名,具體含義不再逐個展開介紹,可以參考上文對date與time類的講解。):
year、month、day、hour、minute、second、microsecond、tzinfo:
像date一樣,也可以對兩個datetime對象進行比較,或者相減返回一個時間間隔對象,或者日期時間加上一個間隔返回一個新的日期時間對象。
通過timedelta函數(shù)返回一個timedelta對象,也就是一個表示時間間隔的對象。函數(shù)參數(shù)情況如下所示:
class datetime.timedelta([days[, seconds[, microseconds[, milliseconds[, minutes[, hours[, weeks]]]]]]])
其沒有必填參數(shù),簡單控制的話第一個整數(shù)就是多少天的間隔的意思:
datetime.timedelta(10)
兩個時間間隔對象可以彼此之間相加或相減,返回的仍是一個時間間隔對象。而更方便的是一個datetime對象如果減去一個時間間隔對象,那么返回的對應(yīng)減去之后的datetime對象,然后兩個datetime對象如果相減返回的是一個時間間隔對象。這很是方便。
tzinfo是一個抽象類,不能被直接實例化。需要派生子類,提供相應(yīng)的標(biāo)準(zhǔn)方法。datetime模塊并不提供tzinfo的任何子類。最簡單的方式是使用pytz模塊。
pytz是Python的一個時區(qū)處理模塊(同時也包括夏令時),在理解時區(qū)處理模塊之前,需要先要了解一些時區(qū)的概念。
要知道時區(qū)之間的轉(zhuǎn)換關(guān)系,其實這很簡單:把當(dāng)?shù)貢r間減去當(dāng)?shù)貢r區(qū),剩下的就是格林威治時間了。例如北京時間的18:00就是18:00+08:00,相減以后就是10:00+00:00,因此就是格林威治時間的10:00。
Python的datetime可以處理2種類型的時間,分別為offset-naive和offset-aware。前者是指沒有包含時區(qū)信息的時間,后者是指包含時區(qū)信息的時間,只有同類型的時間才能進行減法運算和比較。
datetime模塊的函數(shù)在默認情況下都只生成offset-naive類型的datetime對象,例如now()、utcnow()、fromtimestamp()、utcfromtimestamp()和strftime()。其中now()和fromtimestamp()可以接受一個tzinfo對象來生成offset-aware類型的datetime對象,但是標(biāo)準(zhǔn)庫并不提供任何已實現(xiàn)的tzinfo類,只能自己實現(xiàn)。
下面就是實現(xiàn)格林威治時間和北京時間的tzinfo類的例子:
ZERO_TIME_DELTA = timedelta(0)
LOCAL_TIME_DELTA = timedelta(hours=8) # 本地時區(qū)偏差
class UTC(tzinfo):
def utcoffset(self, dt):
return ZERO_TIME_DELTA
def dst(self, dt):
return ZERO_TIME_DELTA
class LocalTimezone(tzinfo):
def utcoffset(self, dt):
return LOCAL_TIME_DELTA
def dst(self, dt):
return ZERO_TIME_DELTA
def tzname(self, dt):
return '+08:00'
一個tzinfo類需要實現(xiàn)utcoffset、dst和tzname這3個方法。其中utcoffset需要返回夏時令的時差調(diào)整;tzname需要返回時區(qū)名,如果你不需要用到的話,也可以不實現(xiàn)。
一旦生成了一個offset-aware類型的datetime對象,我們就能調(diào)用它的astimezone()方法,生成其他時區(qū)的時間(會根據(jù)時差來計算)。而如果拿到的是offset-naive類型的datetime對象,也是可以調(diào)用它的replace()方法來替換tzinfo的,只不過這種替換不會根據(jù)時差來調(diào)整其他時間屬性。因此,如果拿到一個格林威治時間的offset-naive類型的datetime對象,直接調(diào)用replace(tzinfo=UTC())即可轉(zhuǎn)換成offset-aware類型,然后再調(diào)用astimezone()生成其他時區(qū)的datetime對象。
看上去一切都很簡單,但不知道你還是否記得上文所述的夏時令。提起夏時令這個玩意,真是讓我頭疼,因為它沒有規(guī)則可循:有的國家實行夏時令,有的國家不實行,有的國家只在部分地區(qū)實行夏時令,有的地區(qū)只在某些年實行夏時令,每個地區(qū)實行夏時令的起止時間都不一定相同,而且有的地方TMD還不是用幾月幾日來指定夏時令的起止時間的,而是用某月的第幾個星期幾這種形式。
pytz模塊,使用Olson TZ Database解決了跨平臺的時區(qū)計算一致性問題,解決了夏令時帶來的計算問題。由于國家和地區(qū)可以自己選擇時區(qū)以及是否使用夏令時,所以pytz模塊在有需要的情況下得更新自己的時區(qū)以及夏令時相關(guān)的信息。
pytz提供了全部的timezone信息,如:
import pytz
print(len(pytz.all_timezones))
print(len(pytz.common_timezones))
運行結(jié)果:
588
436
如果需要獲取某個國家的時區(qū),可以使用如下方式:
import pytz
print(pytz.country_timezones('cn'))
執(zhí)行結(jié)果:
[u'Asia/Shanghai', u'Asia/Urumqi']
中國一個有兩個時區(qū),一個為上海,一個為烏魯木齊,我們來看下我們有什么區(qū)別:
from datetime import datetime
import pytz
print(pytz.country_timezones('cn'))
tz1 = pytz.timezone(pytz.country_timezones('cn')[0])
print(tz1)
print(datetime.now(tz1))
tz2 = pytz.timezone(pytz.country_timezones('cn')[1])
print(tz2)
print(datetime.now(tz2))
執(zhí)行結(jié)果:
[u'Asia/Shanghai', u'Asia/Urumqi']
Asia/Shanghai
2016-09-14 09:55:39.384000+08:00
Asia/Urumqi
2016-09-14 07:55:39.385000+06:00
可以看到上海是東八區(qū),而烏魯木齊是東六區(qū)。
操作起來有而比較簡單,本地時區(qū)與UTC的互轉(zhuǎn):
from datetime import datetime
import pytz
now = datetime.now()
tz = pytz.timezone('Asia/Shanghai')
print(tz.localize(now))
print(pytz.utc.normalize(tz.localize(now)))
執(zhí)行結(jié)果:
2016-09-14 10:25:44.633000+08:00
2016-09-14 02:25:44.633000+00:00
使用astimezone()可以進行時區(qū)與時區(qū)之間的轉(zhuǎn)換。
from datetime import datetime
import pytz
utc = pytz.utc
beijing_time = pytz.timezone('Asia/Shanghai')
japan_time = pytz.timezone('Asia/Tokyo')
now = datetime.now(beijing_time)
print("Beijing Time:",now)
print("UTC:",now.astimezone(utc))
print("JAPAN TIME:",now.astimezone(japan_time))
執(zhí)行結(jié)果:
Beijing Time: 2016-09-14 10:19:22.671000+08:00
UTC: 2016-09-14 02:19:22.671000+00:00
JAPAN TIME: 2016-09-14 11:19:22.671000+09:00
另外可以采用 replace來修改時區(qū),時區(qū)多出6分鐘(不要使用)。具體原因為:
民國17年(1928年),國民政府統(tǒng)一中國,原中央觀象臺的業(yè)務(wù)由南京政府中央研究院的天文研究所和氣象研究所分別接收。天文研究所編寫的曆書基本上沿襲中央觀象臺的做法,仍將全國劃分為5個標(biāo)準(zhǔn)時區(qū),只是在有關(guān)交氣、合朔、太陽出沒時刻等處,不再使用北平的地方平時,而改以南京所在的標(biāo)準(zhǔn)時區(qū)的區(qū)時即東經(jīng)120°標(biāo)準(zhǔn)時替代。從北平地方平時改為東經(jīng)120°標(biāo)準(zhǔn)時,兩者相差了352秒。
from datetime import datetime
import pytz
now = datetime.now()
print(now)
tz = pytz.timezone('Asia/Shanghai')
print(now.replace(tzinfo=tz))
執(zhí)行結(jié)果:
2016-09-14 10:29:20.200000
2016-09-14 10:29:20.200000+08:06
由于用到的場景比較少,不做細化學(xué)習(xí)。
安裝模塊:pip install Python-dateutil
解析時間到datetime格式,支持大部分時間字符串。沒指定時間默認是0點,沒指定日期默認是今天,沒指定年份默認是今年。
from dateutil import parser
print(parser.parse("8th March,2004"))
print(parser.parse("8 March,2004"))
print(parser.parse("March 8th,2004"))
print(parser.parse("March 8,2004"))
print(parser.parse("2016-09-14"))
print(parser.parse("20160914"))
print(parser.parse("2016/09/14"))
print(parser.parse("09/14/2016"))
print(parser.parse("09,14"))
print(parser.parse("12:00:00"))
print(parser.parse("Wed, Nov 12"))
執(zhí)行結(jié)果:
2004-03-08 00:00:00
2004-03-08 00:00:00
2004-03-08 00:00:00
2004-03-08 00:00:00
2016-09-14 00:00:00
2016-09-14 00:00:00
2016-09-14 00:00:00
2016-09-14 00:00:00
2016-09-09 00:00:00
2016-09-14 12:00:00
2016-11-12 00:00:00
函數(shù)主要功能:按照規(guī)則生成日期和時間。函數(shù)原型如下。
rrule(self, freq, dtstart=None, interval=1, wkst=None, count=None, until=None, bysetpos=None, bymonth=None, bymonthday=None, byyearday=None, byeaster=None, byweekno=None, byweekday=None, byhour=None, byminute=None, bysecond=None, cache=False)
其中:
更多參考:http://dateutil.readthedocs.io/en/stable/index.html
Arrow 提供了一個友好而且非常易懂的方法,用于創(chuàng)建時間、計算時間、格式化時間,還可以對時間做轉(zhuǎn)化、提取、兼容 python datetime 類型。它包括dateutil模塊,根據(jù)其文檔描述Arrow旨在“幫助你使用更少的代碼來處理日期和時間”。
使用utcnow()功能創(chuàng)建 UTC 時間。
使用to()方法,我們將 UTC 時間轉(zhuǎn)換為本地時間。
import arrow
utc = arrow.utcnow()
print(utc)
print(utc.to('local'))
本地時間是特定區(qū)域或時區(qū)中的時間。
import arrow
now = arrow.now()
print(now)
print(now.to('UTC'))
使用now()功能創(chuàng)建本地時間。to()方法用于將本地時間轉(zhuǎn)換為 UTC 時間。
get()方法用于解析時間。
import arrow
d1 = arrow.get('2012-06-05 16:20:03', 'YYYY-MM-DD HH:mm:ss')
print(d1)
d2 = arrow.get(1504384602)
print(d2)
該示例從日期和時間字符串以及時間戳解析時間。
import arrow
utc = arrow.utcnow()
print(utc)
unix_time = utc.timestamp
print(unix_time)
date = arrow.Arrow.fromtimestamp(unix_time)
print(date)
該示例顯示本地時間和 Unix 時間。然后,它將 Unix 時間轉(zhuǎn)換回 date 對象。
使用fromtimestamp()方法,我們將 Unix 時間轉(zhuǎn)換回 Arrow 日期對象。
也可以將日期格式化為 Unix 時間。
import arrow
utc = arrow.utcnow()
print(utc.format('X'))
通過將’X’說明符傳遞給format()方法,我們將當(dāng)前本地日期打印為 Unix 時間。
日期和時間可以用format()方法格式化。
import arrow
now = arrow.now()
year = now.format('YYYY')
print("Year: {0}".format(year))
date = now.format('YYYY-MM-DD')
print("Date: {0}".format(date))
date_time = now.format('YYYY-MM-DD HH:mm:ss')
print("Date and time: {0}".format(date_time))
date_time_zone = now.format('YYYY-MM-DD HH:mm:ss ZZ')
print("Date and time and zone: {0}".format(date_time_zone))
格式說明:
import arrow
utc = arrow.utcnow()
print(utc.to('US/Pacific').format('HH:mm:ss'))
print(utc.to('Europe/Bratislava').format('HH:mm:ss'))
print(utc.to('Europe/Moscow').format('HH:mm:ss'))
可以使用weekday()或format()方法找到日期的工作日。
import arrow
d1 = arrow.get('1948-12-13')
print(d1.weekday())
print(d1.format('dddd'))
shift()方法用于移動時間。
import arrow
now = arrow.now()
print(now.shift(hours=5).time())
print(now.shift(days=5).date())
print(now.shift(years=-8).date())
import arrow
now = arrow.now()
print(now.format("YYYY-MM-DD HH:mm:ss ZZ"))
print(now.dst())
該示例使用dst()顯示夏令時。
在社交網(wǎng)站上,我們經(jīng)常可以看到諸如“一個小時前”或“ 5 分鐘前”之類的術(shù)語,這些術(shù)語可以為人們提供有關(guān)帖子創(chuàng)建或修改時間的快速信息。Arrow 包含humanize()方法來創(chuàng)建此類術(shù)語。
import arrow
now = arrow.now()
d1 = now.shift(minutes=-15).humanize()
print(d1)
d2 = now.shift(hours=5).humanize()
print(d2)
國際標(biāo)準(zhǔn)ISO 8601,是國際標(biāo)準(zhǔn)化組織的日期和時間的表示方法,全稱為《數(shù)據(jù)存儲和交換形式·信息交換·日期和時間的表示方法》,在API接口開發(fā)中涉及的比較多。
>>> import dateutil.parser
>>> dateutil.parser.parse('2008-09-03T20:56:35.450686Z') # RFC 3339 format
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686, tzinfo=tzutc())
>>> dateutil.parser.parse('2008-09-03T20:56:35.450686') # ISO 8601 extended format
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686)
>>> dateutil.parser.parse('20080903T205635.450686') # ISO 8601 basic format
datetime.datetime(2008, 9, 3, 20, 56, 35, 450686)
>>> dateutil.parser.parse('20080903') # ISO 8601 basic format, date only
datetime.datetime(2008, 9, 3, 0, 0)
或者使用如下方式解析:
>>> datetime.datetime.strptime("2008-09-03T20:56:35.450686Z", "%Y-%m-%dT%H:%M:%S.%fZ")
另外還可以使用iso8601模塊:http://pyiso8601.readthedocs.io/en/latest/
其他日期與時間工具:
atejs 是一個開源的JavaScript庫,用來解析、格式化和處理日期數(shù)據(jù),支持多種語言的日期格式處理;官網(wǎng):www.datejs.com/
Moment.js 是一個簡單易用的輕量級JavaScript日期處理類庫,提供了日期格式化、日期解析等功能。它支持在瀏覽器和NodeJS兩種環(huán)境中運行;
date-fns庫:
現(xiàn)代 JavaScript 日期實用程序庫。date-fns 提供了最全面,最簡單和一致的工具集,用于在瀏覽器和 Node.js 中操作 JavaScript 日期;官網(wǎng):date-fns.org
Prettydate 是一個 jQuery 用來顯示一些用戶友好的日期格式的插件,例如Posted 2 days ago by John Resig;
Countdown是jQuery的一個用于顯示倒計時的插件;
XDate是一個對Javascirpt本地Date對象的輕度包裝,它提供對日期的解析、格式化以及其他操作的較強功能;
DP_DateExtensions庫繼承了JavaScript的Date對象,并添加了一些新特性和功能。
組件類:
layDate 日期與時間組件,layDate 是 layui 獨立維護的三大組件之一;官網(wǎng):www.layui.com/laydate/
Datejs 日期庫:是一個開源的JavaScript庫,用來解析、格式化和處理日期數(shù)據(jù),支持多種語言的日期格式處理;
官網(wǎng):www.datejs.com/
基本用法:
// 返回今天的日期,時間設(shè)置為00:00(一天的開始)
console.log(Date.today().toString("yyyy-MM-d HH:m:s"));
//返回下一個星期五的日期
console.log(Date.today().next().friday().toString("yyyy-MM-d HH:m:s"));
Date.today().last().monday() //返回上一個星期一的日期
new Date().next().march() //返回下一個三月的日期。
new Date().last().week() //返回一周前的日期。
Date.today().is().friday() //如果星期幾匹配,則返回true | false.
Date.today().is().fri() //縮寫的日期名稱.
Date.today().is().november() //月名稱
Date.today().is().nov() //月份的縮寫.
Date.today().is().weekday() //今天是工作日嗎?
Date.today().addDays(1); //添加一天(+1)
Date.today().addMonths(-3); //減去三個月內(nèi)(-3)
//添加一(+1)天。支持所有日期部分(年,月,日,時,分,秒,毫秒和周)
Date.today().add(1).day();
Date.today().add(-3).months(); //減去三(-3)個月
// (1).day().fromNow() //從現(xiàn)在起一(1)天。
// (3).months().ago() //三(3)個月前。
var n = 6;
console.log(n.months().fromNow().toString('d')); //從現(xiàn)在起六(6)個月。
Date.monday(); //返回當(dāng)前星期的星期一。
Date.mon(); // Date.monday()的縮寫版本
Date.march(); //返回今年3月1日。
Date.mar(); // Date.march()的縮寫版本
Date.today().first().thursday(); //返回當(dāng)年3月的第一個星期四。
Date.today().second().thursday();//返回當(dāng)前月份的第二個星期四。
Date.march().third().thursday(); //返回當(dāng)年3月的第三個星期四。
Date.october().fourth().sunday();//返回十月的第四個星期日。
//返回當(dāng)前月份的第五個星期日,如果當(dāng)前月份沒有5個星期日,則拋出RangeError異常。
// Date.today().fifth().sunday();
Date.october().final().sunday(); //返回十月的最后一個星期日。
Date.january().first().monday(); //返回當(dāng)年的第一個星期一。
Date.december().final().friday();//返回當(dāng)年的最后一個星期五。
Date.today().at("6:15pm"); //返回今天的日期為6:15 pm。
var time = {hour:18, minute:15};
Date.today().at(time); //使用配置對象設(shè)置時間。
var birthDayParty = {month: 1, day: 20, hour: 20, minute: 30};
Date.today().set(birthDayParty);//使用配置對象設(shè)置日期和時間。
日期解析轉(zhuǎn)換:
Date.parse("t"); //返回今天的日期
Date.parse("today"); //返回今天的日期。
Date.parse("tomorrow"); //返回明天的日期
Date.parse("yesterday"); //返回昨天的日期
Date.parse("next friday"); //返回下一個星期五的日期
Date.parse("last monday"); //返回上一個星期一的日期。
Date.parse("July 8th, 2004"); // 2004年7月8日星期四
Date.parse("15-Jan-2004"); // 2004年1月15日星期四
Date.parse("7/1/2004"); // 2004年7月1日星期四
Date.parse("7.1.2004"); // 2004年7月1日星期四
Date.parse("07.15.04"); // 2004年7月15日星期四
Date.parse("July 23rd 2004"); //周五2004年7月23日
Date.parse("Sat July 3, 2004"); // 2004年7月3日星期六
Date.parse("10:30 PM EST"); // 2007年10月31日星期三20:30:00
Date.parse("10PM"); // 2007年10月31日星期三22:00:00
Date.parse("t + 5d"); //將5天加到今天
Date.parse("today - 1 month"); //從今天開始減去1個月
Date.parse("+"); //將1天添加到今天=明天
Date.parse("- 3months"); //減去3個月
Date.parse("+1year"); //在今天加上一年
Date.parse("-12 months"); //從今天起減去12個月(1年)
Date.parse("July 4th"); //今年7月4日
Date.parse("15"); //當(dāng)前月份/年份的第15天
Date.parse("July 8th, 2004, 10:30 PM");// 2004年7月8日,星期四
Date.parse("2004-07-15T06:45:00"); // 2004年7月15日星期四
Date.parse("Thu, 1 July 2004 22:30:00 GMT");//星期四,2004年7月1日16:30:00
Date.parse("1997-07-16T19:20:15"); // ISO 8601格式
Date.parse("1997-07-16T19:20:30+01:00");//具有時區(qū)偏移
Date.parse("1985-04-12T23:20:50Z"); // RFC 3339格式
鏈接操作:
//添加1個月零5天,然后檢查該日期是否為星期五
Date.today().add({ months: 1, days: 5 }).is().fri();
//輸入日期,然后移至下一個星期五,減去一個月
Date.parse("10-July-2004").next().friday().add(-1).month();
日期比較:
Date.today().equals( Date.parse("today")); // true|false
Date.parse("last Tues").equals(Date.today()); // true|false
Date.equals(Date.today(), Date.parse("today")); // true|false
Date.compare(Date.today(), Date.parse("today")); // 1 = greater, -1 = less than,
Date.today().compareTo(Date.parse("yesterday")); // 1 = greater, -1 = less than, 0 = equal
Date.today().between(startDate, endDate); // true|false
轉(zhuǎn)換為字符串:
注意該format參數(shù)對于該.toString()功能是可選的。如果未提供format,.toString()則將調(diào)用本地JavaScript Date 函數(shù)。
標(biāo)準(zhǔn)日期和時間格式說明符
自定義日期和時間格式說明符
分隔符:
/ 正斜杠、空格、- 連字號、逗號
new Date().toString(); //星期三2007年10月31日格林尼治標(biāo)準(zhǔn)時間0700(太平洋夏令時間)
new Date().toString("M/d/yyyy"); //2007年10月31日
Date.today().toString("d-MMM-yyyy"); //2007年10月31日
new Date().toString("HH:mm"); // 16:18
Date.today().toString("MMMM dS, yyyy"); // April 12th, 2008
Date.today().toShortDateString();// "10/31/2007". 根據(jù)Date.CultureInfo.shortDatePattern特定于區(qū)域性
Date.today().toLongDateString();// "Wednesday, October 31, 2007". 根據(jù)Date.CultureInfo.longDatePattern特定于區(qū)域性
new Date().toShortTimeString();// "4:18 PM". 根據(jù)Date.CultureInfo.shortTimePattern特定于區(qū)域性
new Date().toLongTimeString();// "4:18:34 PM". 根據(jù)Date.CultureInfo.longTimePattern特定于區(qū)域性
核心用法:
//將日期設(shè)置為當(dāng)前月份和年份的15號;
//其他對象值包括year|month|day|hour|minute|second。
Date.today().set({ day: 15 });
Date.today().set({ year: 2007, month: 1, day: 20 });
//將Date添加2天。其他對象值包括 year|month|day|hour|minute|second.
Date.today().add({ days: 2 });
Date.today().add({ years: -1, months: 6, hours: 3 });
Date.today().addYears(1); //增加1年
Date.today().addMonths(-2); //相減2個月
Date.today().addWeeks(1); //增加1周
Date.today().addDays(4); //增加4天
Date.today().addHours(6); //增加6小時
Date.today().addMinutes(-30); //相減30分鐘
Date.today().addSeconds(15); //增加15秒
Date.today().addMilliseconds(200); //增加200毫秒
Date.today().moveToFirstDayOfMonth();//返回當(dāng)前月份的第一天
Date.today().moveToLastDayOfMonth();//返回當(dāng)前月份的最后一天
new Date().clearTime(); //將時間設(shè)置為00:00(一天的開始)
Date.today().setTimeToNow();//將時間重置為當(dāng)前時間;與clearTime()的功能相反
ISO 8601:
其他用法:
Date.getMonthNumberFromName("March");// 2-特定于CultureInfo。<static>
Date.getDayNumberFromName("sat");// 6-特定于CultureInfo。<靜態(tài)>
Date.isLeapYear(2008) // true|false. <static>
Date.getDaysInMonth(2007, 9) // 31 <static>
Date.today().getWeek();//返回一年中的第幾周。根據(jù)年份Date 返回1到(52 | 53)
Date.today().setWeek(1); //將一年中的星期幾設(shè)置為星期幾
var test = new Date(); // Do something... like run a test...
test.getElapsed(); //返回距現(xiàn)在的毫秒數(shù)
Date.today().isDaylightSavingTime();// true|false. 在夏令時之內(nèi)
Date.today().hasDaylightSavingTime();// true|false. 是否遵守夏令時
Web前端開發(fā)之Javascript-零點程序員-王唯
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。