Python時間處理之datetime類

datetime類是Python處理日期和時間的標準庫。datetime是date與time的結合體,包括date與time的所有信息。

它的構造函數如下:

datetime.datetime(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])
import time
from datetime import datetime, timedelta, timezone

1 datetime類定義的類屬性與方法

1.1 datetime.min、datetime.max

datetime所能表示的最小值與最大值。

print('datetime.max:' + str(datetime.max))  
#datetime.max: 9999-12-31 23:59:59.999999
print('datetime.min:' + str(datetime.min))  
#datetime.min: 0001-01-01 00:00:00

1.2 datetime.resolution

datetime最小單位。

print('datetime.resolution:' + str(datetime.resolution)) 
#datetime.resolution: 0:00:00.000001

1.3 datetime.today()

返回一個表示當前本地時間的datetime對象。

print('today():' + str(datetime.today())) 
#today(): 2017-07-16 18:00:05.346294

1.4 datetime.now([tz])

返回一個表示當前本地時間的datetime對象,如果提供了參數tz,則獲取tz參數所指時區的本地時間。

print('now():' + str(datetime.now())) 
#now(): 2017-07-16 18:00:05.346293

1.5 datetime.utcnow()

返回一個當前utc時間(世界標準時間)的datetime對象。(utc時間與北京時區相差8小時)

print('utcnow():' + str(datetime.utcnow())) 
#utcnow(): 2017-07-16 10:00:05.346293

1.6 datetime.fromtimestamp(timestamp[,tz])

根據時間戮,創建一個datetime對象,參數tz指定時區信息。

print('fromtimestamp(tmstmp):' + str(datetime.fromtimestamp(time.time())))
#fromtimestamp(tmstmp): 2017-07-16 18:00:05.346294

1.7 datetime.utcfromtimestamp(timestamp)

根據時間戮,創建一個datetime對象。

print('utcfromtimestamp(tmstmp):'  + str(datetime.utcfromtimestamp(time.time())))
#utcfromtimestamp(tmstmp):2017-07-16 10:00:05.346294

1.8 datetime.combine(date, time)

根據date和time,創建一個datetime對象。

d = date(2017,6,12)
t = time(18,04,25)
print('datetime.combine(date,time):' + str(datetime.combine(d,t)))
#datetime.combine(date,time): 2017-06-12 18:04:25

1.9 datetime.strptime(date_string, format)

將格式字符串轉換為datetime對象。

print(datetime.strptime("2017-07-16 18:06:19", "%Y-%m-%d %H:%M:%S"))
#2017-07-16 18:06:19

2 datetime類提供的實例方法與屬性

dt = datetime.strptime("2017-07-16 19:14:36", "%Y-%m-%d %H:%M:%S")
print(dt.year)                  # 2017
print(dt.month)                 # 7
print(dt.day)                   # 16
print(dt.hour)                  # 19
print(dt.minute)                # 14
print(dt.second)                # 36
print(dt.microsecond)           # 0
print(dt.tzinfo)                # None
print(dt.date())                # 2017-07-16
print(dt.time())                # 19:14:36
print(dt.replace(year=2018))    # 2018-07-16 19:14:36
print(dt.weekday())             # 6
print(dt.isocalendar())         # (2017, 28, 7)

print(dt.timetuple())
#返回日期對應的time.struct_time對象(類似于time模塊的time.localtime())
#time.struct_time(tm_year=2017, tm_mon=7, tm_mday=16, tm_hour=19, tm_min=14, tm_sec=36, tm_wday=6, tm_yday=197, tm_isdst=-1)

print(dt.utctimetuple())
#返回UTC日期對應的time.struct_time對象
#time.struct_time(tm_year=2017, tm_mon=7, tm_mday=16, tm_hour=19, tm_min=14, tm_sec=36, tm_wday=6, tm_yday=197, tm_isdst=0)

print(dt.toordinal()) 
#736526,返回日期對應的Gregorian Calendar日期

3 格式字符串datetime.strftime(format)

變量 說明
%a 星期的簡寫。如星期三為Web
%A 星期的全寫。如星期三為Wednesday
%b 月份的簡寫。如4月份為Apr
%B 月份的全寫。如4月份為April
%c 日期時間的字符串表示。(如:04/07/10 10:43:39)
%d 日在這個月中的天數(是這個月的第幾天)
%f 微秒(范圍[0,999999])
%H 小時(24小時制,[0,23])
%I 小時(12小時制,[0,11])
%j 日在年中的天數 [001,366](是當年的第幾天)
%m 月份([01,12])
%M 分鐘([00,59])
%p AM或者PM
%S 秒(范圍為[00,61])
%U 周在當年的周數當年的第幾周,星期天作為周的第一天
%w 今天在這周的天數,范圍為[0,6],6表示星期天
%W 周在當年的周數(是當年的第幾周),星期一作為周的第一天
%x 日期字符串(如:04/07/10)
%X 時間字符串(如:10:43:39)
%y 2個數字表示的年份
%Y 4個數字表示的年份
%z 與utc時間的間隔(如果是本地時間,返回空字符串)
%Z 時區名稱(如果是本地時間,返回空字符串)
%% %% => %
dt = datetime.now()
print('(%Y-%m-%d %H:%M:%S %f):'+ str(dt.strftime('%Y-%m-%d %H:%M:%S %f')))
#(%Y-%m-%d %H:%M:%S %f): 2017-07-16 20:32:19 033740

print('(%Y-%m-%d %H:%M:%S %p):'+str(dt.strftime('%y-%m-%d %I:%M:%S %p')))
#(%Y-%m-%d %H:%M:%S %p): 17-07-16 08:32:19 PM

print('%%a: %s' % dt.strftime('%a'))
#%a: Sun 

print('%%A: %s' % dt.strftime('%A'))
#%A: Sunday

print('%%b: %s' % dt.strftime('%b'))
#%b: Jul

print('%%B: %s' % dt.strftime('%B'))
#%B: July

print('日期時間%%c: %s' % dt.strftime('%c'))
#日期時間%c: Sun Jul 16 20:32:19 2017

print('日期%%x:%s' % dt.strftime('%x'))
#日期%x:07/16/17

print('時間%%X:%s' % dt.strftime('%X'))
#時間%X:20:32:19

print('今天是這周的第%s天' % dt.strftime('%w'))
#今天是這周的第0天

print('今天是今年的第%s天' % dt.strftime('%j'))
#今天是今年的第197天

print('今周是今年的第%s周' % dt.strftime('%U'))
#今周是今年的第29周

4 日期和時間的常用操作

4.1 獲取當前、指定日期和時間

now = datetime.now()           # 獲取當前datetime
print(now)
#2017-07-19 00:19:26.661741
print(type(now))
#<class 'datetime.datetime'>

datetime.now()返回當前日期和時間,其類型是datetime。

要指定某個日期和時間,我們直接用參數構造一個datetime:

dt = datetime(2017,7,19,8,30) # 用指定日期時間創建datetime
print(dt)
#2017-07-19 08:30:00

4.2 datetime和timestamp互相轉換

在計算機中,時間實際上是用數字表示的。我們把1970年1月1日 00:00:00 UTC+00:00時區的時刻稱為epoch time,記為0(1970年以前的時間timestamp為負數),當前時間就是相對于epoch time的秒數,稱為timestamp。

可認為:timestamp = 0 = 1970-1-1 00:00:00 UTC+0:00。對應的北京時間是:timestamp = 0 = 1970-1-1 08:00:00 UTC+8:00。

可見timestamp的值與時區毫無關系,因為timestamp一旦確定,其UTC時間就確定了,轉換到任意時區的時間也是完全確定的,這就是為什么計算機存儲的當前時間是以timestamp表示的,因為全球各地的計算機在任意時刻的timestamp都是完全相同的。

把一個datetime類型轉換為timestamp只需要簡單調用timestamp()方法:

dt = datetime(2017,7,19,8,30)   # 用指定日期時間創建datetime
dt.timestamp()                  # 把datetime轉換為timestamp
#1500424200.0

將1500424200.0秒轉換為年份,得到47.57813926940639年,對應的就是1970+47=2017年。

要把timestamp轉換為datetime,使用datetime提供的fromtimestamp()方法:

t = 1500424200.0
print(datetime.fromtimestamp(t))
#2017-07-19 08:30:00

timestamp是一個浮點數,它沒有時區的概念,而datetime是有時區的。上述轉換是在timestamp和本地時間做轉換。本地時間是指當前操作系統設定的時區。

例如北京時區是東8區,則本地時間:2017-07-19 08:30:00,實際上就是UTC+8:00時區的時間:2017-07-19 08:30:00 UTC+8:00。而此刻的格林威治標準時間與北京時間差了8小時,也就是UTC+0:00時區的時間應該是:2017-07-19 00:30:00 UTC+0:00。

timestamp也可以直接被轉換到UTC標準時區的時間:

t = 1500424200.0
print(datetime.fromtimestamp(t))      # 本地時間
#2017-07-19 08:30:00
print(datetime.utcfromtimestamp(t))   # UTC時間
#2017-07-19 00:30:00

注意:某些編程語言(如Java和JavaScript)的timestamp使用整數表示毫秒數,這種情況下只需要把timestamp除以1000就得到Python的浮點表示方法。


4.3 str和datetime互相轉換

很多時候,用戶輸入的日期和時間是字符串,要處理日期和時間,首先必須把str轉換為datetime。轉換方法是通過datetime.strptime()實現,需要一個日期和時間的格式化字符串:

str2day = datetime.strptime('2017-7-19 12:20:30', '%Y-%m-%d %H:%M:%S')
print(str2day)
#2017-07-19 12:20:30

轉換后的datetime是沒有時區信息的,只是根據給定的字符串,進行轉換而已。

如果已經有了datetime對象,要把它格式化為字符串顯示給用戶,就需要轉換為str,轉換方法是通過strftime()實現的,同樣需要一個日期和時間的格式化字符串:

now = datetime.now()
print(now.strftime('%a, %b %d %H:%M'))
#Wed, Jul 19 00:49

4.4 datetime加減

對日期和時間進行加減實際上就是把datetime往后或往前計算,得到新的datetime。加減可以直接用+和-運算符,不過需要導入timedelta這個類:

now = datetime.now()
#now
datetime.datetime(2017, 7, 19, 0, 53, 2, 335063)
now + timedelta(hours=10)
#datetime.datetime(2017, 7, 19, 5, 53, 2, 335063)
now - timedelta(days=2)
#datetime.datetime(2017, 7, 17, 0, 53, 2, 335063)
now + timedelta(days=3, hours=10)
#datetime.datetime(2017, 7, 22, 10, 53, 2, 335063)

可見,使用timedelta你可以很容易地算出前幾天和后幾天的時刻。


4.5 本地時間轉換為UTC時間

本地時間是指系統設定時區的時間,例如北京時間是UTC+8:00時區的時間,而UTC時間指UTC+0:00時區的時間。

一個datetime類型有一個時區屬性tzinfo,但是默認為None,所以無法區分這個datetime到底是哪個時區,除非強行給datetime設置一個時區:

tz_utc_8 = timezone(timedelta(hours=8))  # 創建時區UTC+8:00
now = datetime.now()
now
#datetime.datetime(2017, 7, 19, 1, 17, 59, 785108)
dt = now.replace(tzinfo=tz_utc_8)        # 強制設置為UTC+8:00
dt
#datetime.datetime(2017, 7, 19, 1, 17, 59, 785108, tzinfo=datetime.timezone(datetime.timedelta(0, 28800)))

如果系統時區恰好是UTC+8:00,那么上述代碼就是正確的,否則,不能強制設置為UTC+8:00時區。


4.6 時區轉換

先通過utcnow()拿到當前的UTC時間,再轉換為任意時區的時間:

  1. 拿到UTC時間,并強制設置時區為UTC+0:00:
utc_dt = datetime.utcnow().replace(tzinfo=timezone.utc)
print(utc_dt)
#2017-07-18 17:21:31.636243+00:00
  1. astimezone()將轉換時區為北京時間:
bj_dt = utc_dt.astimezone(timezone(timedelta(hours=8)))
print(bj_dt)
#2017-07-19 01:21:31.636243+08:00
  1. astimezone()將轉換時區為東京時間:
tokyo_dt = utc_dt.astimezone(timezone(timedelta(hours=9)))
print(tokyo_dt)
#2017-07-19 02:21:31.636243+09:00
  1. astimezone()將bj_dt轉換時區為東京時間:
tokyo_dt2 = bj_dt.astimezone(timezone(timedelta(hours=9)))
print(tokyo_dt2)
#2017-07-19 02:21:31.636243+09:00

時區轉換的關鍵在于,拿到一個datetime時,要獲知其正確的時區,然后強制設置時區,作為基準時間。利用帶時區的datetime,通過astimezone()方法,可以轉換到任意時區。

注意:不是必須從UTC+0:00時區轉換到其他時區,任何帶時區的datetime都可以正確轉換,例如上述bj_dt到tokyo_dt的轉換。


如果您發現文中有不清楚或者有問題的地方,請在下方評論區留言,我會根據您的評論,更新文中相關內容,謝謝!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,533評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,055評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,365評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,561評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,346評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,889評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,978評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,118評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,637評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,558評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,739評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,246評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,980評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,619評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,347評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,702評論 2 370

推薦閱讀更多精彩內容