2019-05-25 重新編輯了一下
以下基本我在日常寫代碼中,最常用的一些日期相關部分。
1、當前時間轉文本strftime()
無論是time
或datetime
,哪個模塊都可以,具體怎么輸出,自行調整格式參數'%Y-%m-%d %H:%M:%S'
%字符 | 表意 | 數值范圍 | |
---|---|---|---|
%y | 年(2位) | 00, 01, …, 99 | |
%Y | 年(4位) | 0001, 0002, …, 2013, 2014, …, 9998, 9999 | |
%m | 月 | 01, 02, …, 12 | |
%d | 日 | 01, 02, …, 31 | |
%H | 時(24小時制) | 00, 01, …, 23 | |
%M | 分 | 00, 01, …, 59 | |
%S | 秒 | 00, 01, …, 59 | |
%f | 毫秒 | 000000, 000001, …, 999999 | |
%z | 時區 | (empty), +0000, -0400, +1030, +063415, -030712.345216 | |
%a |
工作日作為語言環境的縮寫名稱。 |
太陽,周一,......,周六(en_US);
所以,Mo,...,Sa(de_DE)
|
|
%A |
平日作為語言環境的全名。 |
星期日,星期一,......,星期六(en_US);
Sonntag,Montag,......,Samstag(de_DE)
|
|
%w |
工作日為十進制數,其中0表示星期日,6表示星期六。 | 0,1,...,6 | |
%d |
作為零填充十進制數的月中的某一天。 | 01,02,...,31 | |
%b |
月份為區域設置的縮寫名稱。 |
Jan,Feb,...,Dec(en_US);
Jan,Feb,...,Dez(de_DE)
|
|
%B |
月份為區域設置的全名。 |
1月,2月,...,12月(en_US);
Januar,Februar,...,Dezember(de_DE)
|
|
%m |
月份為零填充十進制數。 | 01,02,...,12 | |
%y |
沒有世紀的年份為零填充十進制數。 | 00,01,...,99 | |
%Y |
年份以世紀為十進制數。 | 1970年,1988年,2001年,2013年 | |
%H |
小時(24小時制)作為零填充十進制數。 | 00,01,...,23 | |
%I |
小時(12小時制)作為零填充十進制數。 | 01,02,...,12 | |
%p |
Locale相當於AM或PM。 |
AM,PM(en_US);
上午,下午(de_DE)
|
|
%M |
分鍾為零填充十進制數。 | 00,01,...,59 | |
%S |
其次是零填充十進制數。 | 00,01,...,59 | |
%f |
Microsecond為十進制數,左側為零填充。 | 000000,000001,...,999999 | |
%z |
UTC偏移量,格式為+ HHMM或-HHMM(如果對象是天真的,則為空字符串)。 | (空),+ 0000,-0400,+ 1030 | |
%Z |
時區名稱(如果對象是天真的,則為空字符串)。 | (空),UTC,EST,CST | |
%j |
一年中的一天作為零填充十進制數。 | 001,002,...,366 | |
%U |
作為零填充十進制數的一年中的周數(星期日作為一周的第一天)。在第一個星期日之前的新年中的所有日子都被認為是在第0周。 | 00,01,...,53 | |
%W |
一年中的周數(星期一作為一周的第一天)作為十進制數。在第一個星期一之前的新年中的所有日子被認為是在第0周。 | 00,01,...,53 | |
%c |
Locale的適當日期和時間表示。 |
1988年8月16日星期二21:30:00(en_US);
Di 16 Aug 21:30:00 1988(de_DE)
|
|
%x |
Locale的適當日期表示。 |
08/16/88(無);
1988年8月16日(en_US);
19.08.1988(de_DE)
|
|
%X |
Locale的適當時間表示。 |
21:30:00(zh_);
21:30:00(de_DE)
|
|
%% |
文字'%' 字符。 |
% |
這里只列一下我用到的,更多可以看官方文檔:
https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior
【注意】:
time、datetime兩種時間模塊雖然都有strftime
,但是(格式,時間)
參數位置正好相反。
time模塊(格式在前,時間在后)
import time
t = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())
print(type(t),t)
# 輸出結果
<class 'str'> 2019-05-25 08:56:45
datetime模塊(格式在后,時間在前)
import datetime
dt = datetime.datetime.strftime(datetime.datetime.now(),'%Y-%m-%d %H:%M:%S')
print(type(dt),dt)
# 輸出結果
<class 'str'> 2019-05-25 08:56:45
2、文本轉日期
(1)常規方法strptime("日期時間文本","文本格式")
制定時間格式,進行解析
import datetime
dt = datetime.datetime.strptime('2019-05-25T07:46:45.743+0000','%Y-%m-%dT%H:%M:%S.%f%z')
print(type(dt),dt)
# 輸出結果
<class 'datetime.datetime'> 2019-05-25 07:46:45.743000+00:00
(2)萬能方法parse("日期時間文本")
自動解析
easy_install python-dateutil
pip install python-dateutil
from dateutil.parser import parse
dt = parse('2019-05-25 07:46:45')
print(type(dt),dt)
# 輸出結果
<class 'datetime.datetime'> 2019-05-25 07:46:45
該方法適用於很多類型時間格式,建議使用前自行測試
dt = ["2001.07.04 AD at 12:08:56 PDT",
"Wed, 4 Jul 2001 12:08:56 -0700",
"190525","2018-08-06T10:00:00.000Z",
"Wed, Jul 4",
"12:08 PM",
"02001.July.04 AD 12:08 PM",
"20190525083855-0700",
"2001-07-04T12:08:56.235-0700",
"Thu Oct 16 07:13:48 GMT 2014"]
for i in dt:
print(parse(i))
# 輸出結果
2001-07-04 12:08:56
2001-07-04 12:08:56-07:00
2025-05-19 00:00:00
2018-08-06 10:00:00+00:00
2019-07-04 00:00:00
2019-05-25 12:08:00
2001-07-04 12:08:00
2019-05-25 08:38:55-07:00
2001-07-04 12:08:56.235000-07:00
2014-10-16 07:13:48+00:00
但是注意,國外日期時間的常用格式和國內不一樣。單寫19-05-25
會被解析成2025年5月19日
print(parse("19-05-25"))
# 輸出結果
2025-05-19 00:00:00
如果是2019-05-25
就不會錯了
print(parse("2019-05-25"))
# 輸出結果
2019-05-25 00:00:00
3、時間戳相關
生成10或13位時間戳(做一些網頁爬蟲或構造提交時候可能用到)
import time
t = time.time()
print(type(t),t)
print('10位時間戳:',str(int(t)))
print('13位時間戳:',str(int(t*1000)))
# 輸出結果
<class 'float'> 1558750679.0872486
10位時間戳: 1558750679
13位時間戳: 1558750679087
時間戳轉日期時間
import datetime
ts = '1517302458364'
dt1 = datetime.datetime.fromtimestamp(float(ts)/10**(len(ts)-10))
print(type(dt1),dt1)
# 輸出結果
<class 'datetime.datetime'> 2018-01-30 16:54:18.364000
4、時間差計算
定義兩個日期時間dt1
和dt2
,計算一下差值
import datetime
dt1 = datetime.datetime.fromtimestamp(1517302458)
dt2 = datetime.datetime.now()
td = '相差%d天零%.1f個小時'%((dt2-dt1).days,(dt2-dt1).seconds/60/60)
print('%s\n%s\n%s'%(dt1,dt2,td))
# 輸出結果
2018-01-30 16:54:18
2019-05-25 09:31:11.750390
相差479天零16.6個小時
5、時區轉換
時區並非東八區的時間,比如2018-12-10T07:46:45.743+0000
from datetime import datetime,timezone,timedelta
dt1 = datetime.utcnow().replace(tzinfo=timezone.utc)
dt2 = dt1.astimezone(timezone(timedelta(hours=8))) # 轉換時區到東八區
print('UTC協調世界時 \t%s\nUTC+8北京時間\t%s'%(dt1,dt2))
# 輸出結果
UTC協調世界時 2019-05-25 02:48:54.281741+00:00
UTC+8北京時間 2019-05-25 10:48:54.281741+08:00
Python 時間戳的坑
在使用 datetime
的 timestamp()
方法獲取時間戳時遇到一點問題
1 |
#!/usr/bin/env python |
理論上兩個輸出應該都返回當前時間戳,但是 utcnow()
方法的時間戳並不正確,網上查找資料沒一個能說明白的,后來查看官方文檔發現這么一句話
There is no method to obtain the POSIX timestamp directly from a naive datetime instance representing UTC time. If your application uses this convention and your system timezone is not set to UTC, you can obtain the POSIX timestamp by supplying tzinfo=timezone.utc:
我們不能通過 UTC 得到的 datetime
實例直接獲取時間戳,如果系統的時區不是 UTC 則需要 timezone.utc
來幫忙轉換。我暈,我們不提供,但是給你指條路。好吧,先試試
1 |
#!/usr/bin/env python |
OK,這次可以了,但是呢,難道每次獲取一次時間戳都這樣麻煩或者修改系統時區嗎?當然不是,我們還可以通過 time
模塊來輕松搞定
1 |
#!/usr/bin/env python |
時間戳轉為地區時間
如果想要將時間戳轉為某個地區的時間,比如北京時間,需要引入 pytz
模塊,首先下載 pip install pytz
1 |
#!/usr/bin/env python |
討論¶
datetime.strptime()
方法支持很多的格式化代碼, 比如 %Y
代表4位數年份, %m
代表兩位數月份。 還有一點值得注意的是這些格式化占位符也可以反過來使用,將日期輸出為指定的格式字符串形式。
比如,假設你的代碼中生成了一個 datetime
對象, 你想將它格式化為漂亮易讀形式后放在自動生成的信件或者報告的頂部:
>>> z
datetime.datetime(2012, 9, 23, 21, 37, 4, 177393)
>>> nice_z = datetime.strftime(z, '%A %B %d, %Y')
>>> nice_z
'Sunday September 23, 2012'
>>>
還有一點需要注意的是, strptime()
的性能要比你想象中的差很多, 因為它是使用純Python實現,並且必須處理所有的系統本地設置。 如果你要在代碼中需要解析大量的日期並且已經知道了日期字符串的確切格式,可以自己實現一套解析方案來獲取更好的性能。 比如,如果你已經知道所以日期格式是 YYYY-MM-DD
,你可以像下面這樣實現一個解析函數:
from datetime import datetime
def parse_ymd(s):
year_s, mon_s, day_s = s.split('-')
return datetime(int(year_s), int(mon_s), int(day_s))
實際測試中,這個函數比 datetime.strptime()
快7倍多。 如果你要處理大量的涉及到日期的數據的話,那么最好考慮下這個方案!