日期文本互轉,時間戳,時間差 以及 時區變換

2019-05-25 從新編輯了一下html

如下基本我在平常寫代碼中,最經常使用的一些日期相關部分。python

一、當前時間轉文本strftime()

不管是timedatetime,哪一個模塊均可以,具體怎麼輸出,自行調整格式參數'%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-behaviormarkdown

【注意】:
time、datetime兩種時間模塊雖然都有strftime,可是(格式,時間)參數位置正好相反。
app

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

二、文本轉日期

(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("日期時間文本")

自動解析this

easy_install python-dateutilatom

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
 

三、時間戳相關

生成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

 

四、時間差計算

定義兩個日期時間dt1dt2,計算一下差值

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個小時

五、時區轉換

時區並不是東八區的時間,好比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 時間戳的坑

 

在使用 datetimetimestamp() 方法獲取時間戳時遇到一點問題

1
2
3
4
5
6
7
#!/usr/bin/env python
# -*- coding:utf-8 -*-


from datetime import datetime
print(datetime.now().timestamp() # ==> 1512393482.510263
print(datetime.utcnow().timestamp()) # ==> 1512364682.510288

理論上兩個輸出應該都返回當前時間戳,可是 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
2
3
4
5
6
7
8
9
10
#!/usr/bin/env python
# -*- coding:utf-8 -*-


from datetime import datetime
from datetime import timezone

dt = datetime.utcnow()
print(dt.replace(tzinfo=timezone.utc).timestamp()) # ==> 1512454062.906826
print(datetime.now().timestamp()) # ==> 1512454062.906826

 

OK,此次能夠了,可是呢,難道每次獲取一次時間戳都這樣麻煩或者修改系統時區嗎?固然不是,咱們還能夠經過 time 模塊來輕鬆搞定

1
2
3
4
5
6
7
#!/usr/bin/env python
# -*- coding:utf-8 -*-


import time

print(time.time()) # ==> 1512454270.614852

 

時間戳轉爲地區時間

若是想要將時間戳轉爲某個地區的時間,好比北京時間,須要引入 pytz 模塊,首先下載 pip install pytz

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/env python
# -*- coding:utf-8 -*-


import time
from datetime import datetime
import pytz

tz = pytz.timezone('Asia/Shanghai') #東八區
t = datetime.fromtimestamp(int(time.time()),
pytz.timezone('Asia/Shanghai')).strftime('%Y-%m-%d %H:%M:%S %Z%z')
print(t) # ==> 2017-12-05 18:39:45 CST+0800

 

討論

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倍多。 若是你要處理大量的涉及到日期的數據的話,那麼最好考慮下這個方案!

相關文章
相關標籤/搜索