time模組
Comparing Clocks
time.clock():在Unix 上,返回當前的處理器時間,以浮點數秒數表示。
time.monotonic():返回一個單調時鐘的值(在分秒內),也就是不能倒回去的時鐘。時鐘不受系統時鐘更新的影響。返回值的引用點是未定義的,因此只有連續呼叫的結果之間的差異是有效的。
time.perf_counter():返回一個性能計數器的值(在分秒內),即一個具有最高可用解析度的時鐘,以測量短時間。它包括了在睡眠期間的時間,並且是系統範圍的。返回值的引用點是未定義的,因此只有連續呼叫的結果之間的差異是有效的。
time.process_time():返回當前程序的系統和使用者CPU時間的值(在分秒內)。它不包括sleep時的時間。它是整個過程的定義。返回值的引用點是未定義的,因此只有連續呼叫的結果之間的差異是有效的。
time.time():返回自epoch以來時間的秒數,為浮點數。注意,即使返回的時間永遠是浮點數,但是不是所有的系統都提供精度大於1秒的時間。雖然這個函式通常返回非遞減值,如果在兩次呼叫期間系統時鐘被往回設定了,它可能返回比前一次呼叫小的值。
time.get_clock_info(name):獲取指定時鐘上的資訊作為名稱空間物件。支援的時鐘名稱和相應的函式來讀取它們的值:
- 'clock': time.clock()
- 'monotonic': time.monotonic()
- 'perf_counter': time.perf_counter()
- 'process_time': time.process_time()
- 'time': time.time()
其結果如下:
- adjustable:True 如果時鐘可以自動改變 (e.g. by a NTP daemon)或者由系統管理員手動操作。否則為False。
- implementation:用於獲得時鐘值的底層C函式的名稱
- monotonic:True 如果時鐘不能倒轉。否則為False。
- resolution:The resolution of the clock in seconds (float)
舉例
import textwrap
import time
available_locks = [
('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_locks:
print(textwrap.dedent('''\
{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())
)
輸出:
clock:
adjustable : False
implementation : QueryPerformanceCounter()
monotonic : True
resolution : 3.0917042772491994e-07
current : 3.7100451326990392e-06
monotonic:
adjustable : False
implementation : GetTickCount64()
monotonic : True
resolution : 0.015600099999999999
current : 11395.483
perf_counter:
adjustable : False
implementation : QueryPerformanceCounter()
monotonic : True
resolution : 3.0917042772491994e-07
current : 0.00010171707072149866
process_time:
adjustable : False
implementation : GetProcessTimes()
monotonic : True
resolution : 1e-07
current : 0.031200199999999997
time:
adjustable : True
implementation : GetSystemTimeAsFileTime()
monotonic : False
resolution : 0.015600099999999999
current : 1498969586.3116002
Wall Clock Time
time.time():返回自epoch以來時間的秒數,為浮點數。注意,即使返回的時間永遠是浮點數,但是不是所有的系統都提供精度大於1秒的時間。雖然這個函式通常返回非遞減值,如果在兩次呼叫期間系統時鐘被往回設定了,它可能返回比前一次呼叫小的值。
time.ctime([secs]):將自epoch以來的時間秒數轉換成一個表示當前時間的字串。如果secs沒有提供或者為None,則使用time()返回的當前時間。ctime(secs)等同於asctime(localtime(secs))。ctime()沒有使用區域資訊。
舉例
print('The time is :', time.time())
print('The ctime is :', time.ctime())
later = time.time() + 15
print('15 sec from now :', time.ctime(later))
輸出:
The time is : 1498969949.1106
The ctime is : Sun Jul 2 12:32:29 2017
15 sec from now : Sun Jul 2 12:32:44 2017
Monotonic Clocks
因為time() 檢視系統時鐘,系統時鐘可以由使用者或系統服務改變,以便跨多臺計算機同步時鐘,所以重複呼叫time()可能產生向前和向後的值。 這可能導致在嘗試測量持續時間或以其他方式使用那些計算時的意外行為。 通過使用monotonic()來避免這些情況,它總是返回向前推的值。
time.monotonic():返回一個單調時鐘的值(在分秒內),也就是不能倒回去的時鐘。時鐘不受系統時鐘更新的影響。返回值的引用點是未定義的,因此只有連續呼叫的結果之間的差異是有效的。
time.sleep(secs):掛起執行,時間為給出的秒數。引數可以是浮點數以指明更精確的睡眠時間。真正掛起的時間可能小於要求的時間,因為根據訊號捕獲程式的執行任何捕獲的訊號都將終止sleep()。另外,由於系統中其它活動的調動,掛起的時間也可能比要求的時間長一段隨機的時間。
舉例
start = time.monotonic()
time.sleep(0.1)
end = time.monotonic()
print('start : {:>9.2f}'.format(start))
print('end : {:>9.2f}'.format(end))
print('span : {:>9.2f}'.format(end - start))
輸出:
start : 12063.65
end : 12063.76
span : 0.11
Processor Clock Time
time()函式返回的是現實世界的時間, 而clock()函式返回的是cpu時鐘. clock()函式返回值常用作效能測試, benchmarking等. 它們常常反映了程式執行的真實時間, 比time()函式返回的值要精確.
time.clock():在Unix 上,返回當前的處理器時間,以浮點數秒數表示。
舉例
data = open(__file__, 'rb').read()
for i in range(5):
h = hashlib.sha1()
print(time.ctime(), ': {:0.3f} {:0.3f}'.format(
time.time(), time.clock()))
for i in range(1000000):
h.update(data)
cksum = h.digest()
輸出:
Sun Jul 2 12:42:02 2017 : 1498970522.676 0.000
Sun Jul 2 12:42:06 2017 : 1498970526.690 4.015
Sun Jul 2 12:42:10 2017 : 1498970530.747 8.072
Sun Jul 2 12:42:14 2017 : 1498970534.858 12.182
Sun Jul 2 12:42:18 2017 : 1498970538.882 16.206
在這個例子中, ctime()把time()函式返回的浮點型表示轉化為標準時間, 每個迭代迴圈使用了clock(). 如果想在機器上測試這個例子, 那麼可以增加迴圈次數, 或者處理大一點的資料, 這樣才能看到不同點.
一般, 如果程式沒有做任何事情, 處理器時鐘是不會計時.
template = '{} - {:0.2f} - {:0.2f}'
print(template.format(time.ctime(), time.time(), time.clock()))
for i in range(3, 0, -1):
print('Sleeping', i)
time.sleep(i)
print(template.format(time.ctime(), time.time(), time.clock()))
Windows輸出:
Sun Jul 2 12:46:10 2017 - 1498970770.79 - 0.00
Sleeping 3
Sun Jul 2 12:46:13 2017 - 1498970773.79 - 3.00
Sleeping 2
Sun Jul 2 12:46:15 2017 - 1498970775.79 - 5.00
Sleeping 1
Sun Jul 2 12:46:16 2017 - 1498970776.79 - 6.00
Unix輸出:
Sun Jul 2 12:49:29 2017 - 1498970969.64 - 0.03
Sleeping 3
Sun Jul 2 12:49:32 2017 - 1498970972.65 - 0.03
Sleeping 2
Sun Jul 2 12:49:34 2017 - 1498970974.65 - 0.03
Sleeping 1
Sun Jul 2 12:49:35 2017 - 1498970975.65 - 0.03
Performance Counter
有一個高解析度的單調時鐘來測量效能是很重要的。確定最佳的時鐘資料來源需要特定於平臺的知識,而Python提供了perfcounter()。
time.perf_counter():返回一個性能計數器的值(在分秒內),即一個具有最高可用解析度的時鐘,以測量短時間。它包括了在睡眠期間的時間,並且是系統範圍的。返回值的引用點是未定義的,因此只有連續呼叫的結果之間的差異是有效的。
舉例
data = open(__file__, 'rb').read()
loop_start = time.perf_counter()
for i in range(5):
iter_start = time.perf_counter()
h = hashlib.sha1()
for i in range(100000):
h.update(data)
cksum = h.digest()
now = time.perf_counter()
loop_elapsed = now - loop_start
iter_elapsed = now - iter_start
print(time.ctime(), ': {:0.3f} {:0.3f}'.format(iter_elapsed, loop_elapsed))
輸出:
Sun Jul 2 12:51:39 2017 : 0.409 0.409
Sun Jul 2 12:51:40 2017 : 0.407 0.816
Sun Jul 2 12:51:40 2017 : 0.400 1.216
Sun Jul 2 12:51:40 2017 : 0.408 1.624
Sun Jul 2 12:51:41 2017 : 0.400 2.025
與monotonic()一樣,perfcounter()的時間是沒有定義的,並且這些值是用來比較和計算值的,而不是絕對的時間.
Time Components
在某些情況下將儲存時間作為秒數是有用的,但有時候,程式需要訪問日期(年,月等)的各個欄位。 時間模組定義了用於儲存日期和時間值的struct_time,其中元件被分解,因此它們易於訪問。 有幾個函式可以使用struct_time值而不是float。
class time.struct_time:由gmtime()、localtime()和strptime()返回的時間值序列的型別。它是一個具有名為tuple介面的物件:值可以通過索引和屬性名訪問。存在以下值:
Index | Attribute | Values |
---|---|---|
0 | tm_year | (for example, 1993) |
1 | tm_mon | range [1, 12] |
2 | tm_mday | range [1, 31] |
3 | tm_hour | range [0, 23] |
4 | tm_min | range [0, 59] |
5 | tm_sec | range [0, 61]; see (2) in strftime() description |
6 | tm_wday | range [0, 6], Monday is 0 |
7 | tm_yday | range [1, 366] |
8 | tm_isdst | 0, 1 or -1; see below |
N/A | tm_zone | abbreviation of timezone name |
N/A | tm_gmtoff | offset east of UTC in seconds |
time.gmtime([secs]):將自epoch 以來的時間秒數轉換為UTC 的struct_time,它的dst 標記永遠為零。如果secs沒有提供或者為None,則使用time() 返回的當前時間。秒數的小數部分被忽略。
time.localtime([secs]):類似gmtime() 但是轉換成當地時間。如果secs沒有提供或者為None,則使用time() 返回的當前時間。當給的時間使用了DST時,dst 標記被設定為1。
time.mktime(t):localtime()相反的函式。它的引數為struct_time 或者表示當地時間 而不是UTC 時間的完整9-元組(因為需要dst 標記;如果不知道就使用-1作為dst 標記)。它返回一個浮點數,以與time()保持一致。如果輸入的值不能表示成一個合法的時間,那麼將丟擲OverflowError或者ValueError(這依賴於非法的值是被Python還是底層的C庫捕獲)。它能生成的最早日期依賴於具體的平臺。
舉例
def show_struct(s):
print(' tm_year :', s.tm_year)
print(' tm_mon :', s.tm_mon)
print(' tm_mday :', s.tm_mday)
print(' tm_hour :', s.tm_hour)
print(' tm_min :', s.tm_min)
print(' tm_sec :', s.tm_sec)
print(' tm_wday :', s.tm_wday)
print(' tm_yday :', s.tm_yday)
print(' tm_isdst:', s.tm_isdst)
print('gmtime:')
show_struct(time.gmtime())
print('\nlocaltime:')
show_struct(time.localtime())
print('\nmktime:', time.mktime(time.localtime()))
輸出:
gmtime:
tm_year : 2017
tm_mon : 7
tm_mday : 2
tm_hour : 10
tm_min : 20
tm_sec : 25
tm_wday : 6
tm_yday : 183
tm_isdst: 0
localtime:
tm_year : 2017
tm_mon : 7
tm_mday : 2
tm_hour : 18
tm_min : 20
tm_sec : 25
tm_wday : 6
tm_yday : 183
tm_isdst: 0
mktime: 1498990825.0
Working with Time Zones
無論是你的程式, 還是為系統使用一個預設的時區, 檢測當前時間的函式依賴於當前Time Zone(時間域)的設定. 改變時區設定是不會改變實際時間, 只會改變表示時間的方法.
通過設定環境變數TZ可以改變時區, 然後呼叫tzset(). 環境變數TZ可以對時區來詳細的設定, 比如白天儲存時間的起始點. 通常使用時區名稱是比較簡單的, 如果需要了解更多資訊可以參考庫.
time.timezone:本地(非DST)時區的偏移量,以UTC以內的秒為單位(西歐大部分地區為負,美國為正,英國為零)。
time.tzname:兩個字串的元組:第一個是本地非DST時區的名稱,第二個是本地DST時區的名稱。如果未定義DST時區,則不應使用第二個字串。
time.tzset():重置庫例程使用的時間轉換規則。環境變數 TZ指定如何完成此操作。
time.daylight:如果定義了DST時區,則為非零。
舉例
def show_zone_info():
print(' TZ :', os.environ.get('TZ', '(not set)'))
print(' tzname:', time.tzname)
print(' Zone : {} ({})'.format(time.timezone, (time.timezone/3600)))
print(' DST :', time.daylight)
print(' Time :', time.ctime())
print()
print('Default :')
show_zone_info()
ZONES = ['GMT', 'Asia/Shanghai',]
for zone in ZONES:
os.environ['TZ'] = zone
time.tzset()
print(zone, ':')
show_zone_info()
Unix輸出:
Default :
TZ : (not set)
tzname: ('CST', 'CST')
Zone : -28800 (-8.0)
DST : 0
Time : Sun Jul 2 18:59:51 2017
GMT :
TZ : GMT
tzname: ('GMT', 'GMT')
Zone : 0 (0.0)
DST : 0
Time : Sun Jul 2 10:59:51 2017
Asia/Shanghai :
TZ : Asia/Shanghai
tzname: ('CST', 'CST')
Zone : -28800 (-8.0)
DST : 0
Time : Sun Jul 2 18:59:51 2017
Parsing and Formatting Times
函式strptime()和strftime()可以使struct_time和時間值字串相互轉化. 有一個很長的格式化說明列表可以用來支援輸入和輸出不同的風格. 完整的列表在time模組的的庫文件中有介紹.
time.strptime(string[, format]):根據格式解析表示時間的字串。返回值是由gmtime()或localtime()返回的struct_time。
time.strftime(format[, t]):將表示由gmtime()或localtime()返回的時間的元組或struct_time轉換為由格式指定的字串引數。如果未提供t,則使用localtime()返回的當前時間。格式必須是字串。如果t中的任何欄位超出允許範圍,則會引發ValueError。
以下指令可以嵌入格式字串中。它們沒有可選的欄位寬度和精度規範,並由strftime()結果中指示的字元替換:
指示 | 含義 |
---|---|
%a | Locale的縮寫工作日名稱。 |
%A | Locale的整個工作日名稱。 |
%b | 語言環境的縮寫月份名稱。 |
%B | Locale的完整月份名稱。 |
%c | 語言環境的適當日期和時間表示。 |
%d | 一個十進位制數字[01,31]。 |
%H | 小時(24小時制),十進位制數[00,23]。 |
%I | 小時(12小時制)十進位制數[01,12]。 |
%j | 一年中的十進位制數[001,366]。 |
%m | 月為十進位制數[01,12]。 |
%M | 以十進位制數分鐘[00,59]。 |
%p | Locale相當於AM或PM。 |
%S | 秒為十進位制數[00,61]。 |
%U | 年的星期數(星期日為星期的第一天)為十進位制數[00,53]。在第一個星期日之前的新的一年的所有天被認為是在第0周。 |
%w | 工作日為十進位制數[0(星期日),6]。 |
%W | 年的星期數(星期一作為星期的第一天)作為十進位制數[00,53]。在第一個星期一之前的新的一年中的所有天被認為是在第0周。 |
%x | 語言環境的適當日期表示。 |
%X | 語言環境的適當時間表示。 |
%y | 年,無世紀作為十進位制數[00,99]。 |
%Y | 年份以世紀為十進位制數。 |
%z | 指示與+ HHMM或-HHMM形式的UTC / GMT的正或負時差的時區偏移,其中H表示十進位制小時數字,M表示十進位制分數字[-23:59,+23:59]。 |
%Z | 時區名稱(如果沒有時區,則不包含字元)。 |
%% | 字面值'%'字元。 |
舉例
def show_struct(s):
print(' tm_year :', s.tm_year)
print(' tm_mon :', s.tm_mon)
print(' tm_mday :', s.tm_mday)
print(' tm_hour :', s.tm_hour)
print(' tm_min :', s.tm_min)
print(' tm_sec :', s.tm_sec)
print(' tm_wday :', s.tm_wday)
print(' tm_yday :', s.tm_yday)
print(' tm_isdst:', s.tm_isdst)
now = time.ctime(1483391847.433716)
print('Now:', now)
parsed = time.strptime(now)
print('\nParsed:')
show_struct(parsed)
print('\nFormatted:', time.strftime("%a %b %d %H:%M:%S %Y", parsed))
Unix輸出:
('Now:', 'Tue Jan 3 05:17:27 2017')
Parsed:
(' tm_year :', 2017)
(' tm_mon :', 1)
(' tm_mday :', 3)
(' tm_hour :', 5)
(' tm_min :', 17)
(' tm_sec :', 27)
(' tm_wday :', 1)
(' tm_yday :', 3)
(' tm_isdst:', -1)
('\nFormatted:', 'Tue Jan 03 05:17:27 2017')