1. 程式人生 > >Python中日期和時間進行操作time和datetime

Python中日期和時間進行操作time和datetime

Python中提供了多個用於對日期和時間進行操作的內建模組:time模組、datetime模組和calendar模組。其中time模組是通過呼叫C庫實現的,所以有些方法在某些平臺上可能無法呼叫,但是其提供的大部分介面與C標準庫time.h基本一致。time模組相比,datetime模組提供的介面更直觀、易用,功能也更加強大。

一、相關術語的解釋


  • UTC time Coordinated Universal Time,世界協調時,又稱 格林尼治天文時間、世界標準時間。與UTC time對應的是各個時區的local time,東N區的時間比UTC時間早N個小時,因此UTC time + N小時 即為東N區的本地時間;而西N區時間比UTC時間晚N個小時,即 UTC time - N小時 即為西N區的本地時間; 中國在東8區,因此比UTC時間早8小時,可以以UTC+8進行表示。

  • epoch time 表示時間開始的起點;它是一個特定的時間,不同平臺上這個時間點的值不太相同,對於Unix而言,epoch time為 1970-01-01 00:00:00 UTC。

  • timestamp(時間戳) 也稱為Unix時間 或 POSIX時間;它是一種時間表示方式,表示從格林尼治時間1970年1月1日0時0分0秒開始到現在所經過的毫秒數,其值為float型別。 但是有些程式語言的相關方法返回的是秒數(Python就是這樣),這個需要看方法的文件說明。需要說明的是時間戳是個差值,其值與時區無關。

二、時間的表現形式


常見的時間表示形式為:

  • 時間戳
  • 格式化的時間字串

Python中還有其它的時間表示形式:

  • time模組的time.struct_time
  • datetime模組的datetime類

關於datetime模組的datetime類會在下面做詳細講解,這裡簡單說下time.struct_time。

time.struct_time包含如下屬性:

下標/索引 屬性名稱 描述
0 tm_year 年份,如 2017
1 tm_mon 月份,取值範圍為[1, 12]
2 tm_mday 一個月中的第幾天,取值範圍為[1-31]
3 tm_hour 小時, 取值範圍為[0-23]
4 tm_min 分鐘,取值範圍為[0, 59]
5 tm_sec 秒,取值範圍為[0, 61]
6 tm_wday 一個星期中的第幾天,取值範圍為[0-6],0表示星期一
7 tm_yday 一年中的第幾天,取值範圍為[1, 366]
8 tm_isdst 是否為夏令時,可取值為:0 , 1 或 -1

屬性值的獲取方式有兩種:

  • 可以把它當做一種特殊的有序不可變序列通過 下標/索引 獲取各個元素的值,如t[0]
  • 也可以通過 .屬性名 的方式來獲取各個元素的值,如t.tm_year。

需要說明的是struct_time例項的各個屬性都是隻讀的,不可修改。

三、 time模組


time模組主要用於時間訪問和轉換,這個模組提供了各種與時間相關的函式。

1. 函式列表

方法/屬性 描述
time.altzone 返回與utc時間的時間差,以秒為單位(西區該值為正,東區該值為負)。其表示的是本地DST 時區的偏移量,只有daylight非0時才使用。
time.clock() 返回當前程序所消耗的處理器執行時間秒數(不包括sleep時間),值為小數;該方法Python3.3改成了time.process_time()
time.asctime([t]) 將一個tuple或struct_time形式的時間(可以通過gmtime()和localtime()方法獲取)轉換為一個24個字元的時間字串,格式為: "Fri Aug 19 11:14:16 2016"。如果引數t未提供,則取localtime()的返回值作為引數。
time.ctime([secs]) 功能同上,將一個秒數時間戳表示的時間轉換為一個表示當前本地時間的字串。如果引數secs沒有提供或值為None,則取time()方法的返回值作為預設值。ctime(secs)等價於asctime(localtime(secs))
time.time() 返回時間戳(自1970-1-1 0:00:00 至今所經歷的秒數)
time.localtime([secs]) 返回以指定時間戳對應的本地時間的 struct_time物件(可以通過下標,也可以通過 .屬性名 的方式來引用內部屬性)格式
time.localtime(time.time() + n*3600) 返回n個小時後本地時間的 struct_time物件格式(可以用來實現類似crontab的功能)
time.gmtime([secs]) 返回指定時間戳對應的utc時間的 struct_time物件格式(與當前本地時間差8個小時)
time.gmtime(time.time() + n*3600) 返回n個小時後utc時間的 struct_time物件(可以通過 .屬性名 的方式來引用內部屬性)格式
time.strptime(time_str, time_format_str) 將時間字串轉換為struct_time時間物件,如:time.strptime('2017-01-13 17:07', '%Y-%m-%d %H:%M')
time.mktime(struct_time_instance) 將struct_time物件例項轉換成時間戳
time.strftime(time_format_str, struct_time_instance) 將struct_time物件例項轉換成字串

2. 練習

獲取時間戳格式的時間

 
  1. >>> time.time()

  2. 1486188022.862

獲取struct_time格式的時間

 
  1. >>> time.localtime()

  2. time.struct_time(tm_year=2017, tm_mon=2, tm_mday=4, tm_hour=14, tm_min=2, tm_sec=34, tm_wday=5, tm_yday=35, tm_isdst=0)

  3. >>> time.gmtime()

  4. time.struct_time(tm_year=2017, tm_mon=2, tm_mday=4, tm_hour=6, tm_min=2, tm_sec=56, tm_wday=5, tm_yday=35, tm_isdst=0)

獲取字串格式的時間

 
  1. >>> time.ctime()

  2. 'Sat Feb 04 14:06:42 2017'

  3. >>> time.asctime()

  4. 'Sat Feb 04 14:06:47 2017'

時間戳格式轉struct_time格式時間

 
  1. >>> t1 = time.time()

  2. >>> print(t1)

  3. 1486188476.9

  4. >>> t2 = time.localtime(t1)

  5. >>> print(t2)

  6. time.struct_time(tm_year=2017, tm_mon=2, tm_mday=4, tm_hour=14, tm_min=7, tm_sec=56, tm_wday=5, tm_yday=35, tm_isdst=0)

  7. >>> t3 = time.gmtime(t1)

  8. >>> print(t3)

  9. time.struct_time(tm_year=2017, tm_mon=2, tm_mday=4, tm_hour=6, tm_min=7, tm_sec=56, tm_wday=5, tm_yday=35, tm_isdst=0)

  10. >>>

字串格式轉struct_time格式時間

 
  1. >>> time.strptime('Sat Feb 04 14:06:42 2017')

  2. time.struct_time(tm_year=2017, tm_mon=2, tm_mday=4, tm_hour=14, tm_min=6, tm_sec=42, tm_wday=5, tm_yday=35, tm_isdst=-1)

  3. >>> time.strptime('Sat Feb 04 14:06:42 2017', '%a %b %d %H:%M:%S %Y')

  4. time.struct_time(tm_year=2017, tm_mon=2, tm_mday=4, tm_hour=14, tm_min=6, tm_sec=42, tm_wday=5, tm_yday=35, tm_isdst=-1)

  5. >>> time.strptime('2017-02-04 14:12', '%Y-%m-%d %H:%M')

  6. time.struct_time(tm_year=2017, tm_mon=2, tm_mday=4, tm_hour=14, tm_min=12, tm_sec=0, tm_wday=5, tm_yday=35, tm_isdst=-1)

  7. >>> time.strptime('2017/02/04 14:12', '%Y/%m/%d %H:%M')

  8. time.struct_time(tm_year=2017, tm_mon=2, tm_mday=4, tm_hour=14, tm_min=12, tm_sec=0, tm_wday=5, tm_yday=35, tm_isdst=-1)

  9. >>> time.strptime('201702041412', '%Y%m%d%H%M')

  10. time.struct_time(tm_year=2017, tm_mon=2, tm_mday=4, tm_hour=14, tm_min=12, tm_sec=0, tm_wday=5, tm_yday=35, tm_isdst=-1)

struct_time格式轉字串格式時間

 
  1. >>> time.strftime('%Y-%m-%d %H:%M', time.localtime())

  2. '2017-02-04 14:19'

struct_time格式轉時間戳格式時間

 
  1. >>> time.mktime(time.localtime())

  2. 1486189282.0

3. 時間格式轉換

時間戳格式的時間 與 字串格式的時間 雖然可以通過ctime([secs])方法進行轉換,但是字串格式不太適應中國國情。因此,整體而言,它們 不能直接進行轉換,需要通過struct_time作為中介,轉換關係如下:

1063221-20170204153018854-1098926175.png

說明:上面的 '%H:%M:%S' 可以直接用 '%X' 代替。

四、 datetime模組


datetime模組提供了處理日期和時間的類,既有簡單的方式,又有複雜的方式。它雖然支援日期和時間演算法,但其實現的重點是為輸出格式化和操作提供高效的屬性提取功能。

1. datetime模組中定義的類

datetime模組定義了以下幾個類:

類名稱 描述
datetime.date 表示日期,常用的屬性有:year, month和day
datetime.time 表示時間,常用屬性有:hour, minute, second, microsecond
datetime.datetime 表示日期時間
datetime.timedelta 表示兩個date、time、datetime例項之間的時間間隔,解析度(最小單位)可達到微秒
datetime.tzinfo 時區相關資訊物件的抽象基類。它們由datetime和time類使用,以提供自定義時間的而調整。
datetime.timezone Python 3.2中新增的功能,實現tzinfo抽象基類的類,表示與UTC的固定偏移量

需要說明的是:這些類的物件都是不可變的。

類之間的關係:

 
  1. object

  2. date

  3. datetime

  4. time

  5. timedelta

  6. tzinfo

  7. timezone

2. datetime模組中定義的常量

常量名稱 描述
datetime.MINYEAR datetime.date或datetime.datetime物件所允許的年份的最小值,值為1
datetime.MAXYEAR datetime.date或datetime.datetime物件所允許的年份的最大值,只為9999

3. datetime.date類

datetime.date類的定義

class datetime.date(year, month, day)

year, month 和 day都是是必須引數,各引數的取值範圍為:

引數名稱 取值範圍
year [MINYEAR, MAXYEAR]
month [1, 12]
day [1, 指定年份的月份中的天數]

類方法和屬性

類方法/屬性名稱 描述
date.max date物件所能表示的最大日期:9999-12-31
date.min date物件所能表示的最小日誌:00001-01-01
date.resoluation date物件表示的日期的最小單位:天
date.today() 返回一個表示當前本地日期的date物件
date.fromtimestamp(timestamp) 根據跟定的時間戳,返回一個date物件

物件方法和屬性

物件方法/屬性名稱 描述
d.year
d.month
d.day
d.replace(year[, month[, day]]) 生成並返回一個新的日期物件,原日期物件不變
d.timetuple() 返回日期對應的time.struct_time物件
d.toordinal() 返回日期是是自 0001-01-01 開始的第多少天
d.weekday() 返回日期是星期幾,[0, 6],0表示星期一
d.isoweekday() 返回日期是星期幾,[1, 7], 1表示星期一
d.isocalendar() 返回一個元組,格式為:(year, weekday, isoweekday)
d.isoformat() 返回‘YYYY-MM-DD’格式的日期字串
d.strftime(format) 返回指定格式的日期字串,與time模組的strftime(format, struct_time)功能相同

例項

 
  1. >>> import time

  2. >>> from datetime import date

  3. >>>

  4. >>> date.max

  5. datetime.date(9999, 12, 31)

  6. >>> date.min

  7. datetime.date(1, 1, 1)

  8. >>> date.resolution

  9. datetime.timedelta(1)

  10. >>> date.today()

  11. datetime.date(2017, 2, 4)

  12. >>> date.fromtimestamp(time.time())

  13. datetime.date(2017, 2, 4)

  14. >>>

  15. >>> d = date.today()

  16. >>> d.year

  17. 2017

  18. >>> d.month

  19. 2

  20. >>> d.day

  21. 4

  22. >>> d.replace(2016)

  23. datetime.date(2016, 2, 4)

  24. >>> d.replace(2016, 3)

  25. >>> d.replace(2016, 3, 2)

  26. datetime.date(2016, 3, 2)

  27. >>> d.timetuple()

  28. time.struct_time(tm_year=2017, tm_mon=2, tm_mday=4, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=35, tm_isdst=-1)

  29. >>> d.toordinal()

  30. 736364

  31. >>> d.weekday()

  32. 5

  33. >>> d.isoweekday()

  34. 6

  35. >>> d.isocalendar()

  36. (2017, 5, 6)

  37. >>> d.isoformat()

  38. '2017-02-04'

  39. >>> d.ctime()

  40. 'Sat Feb 4 00:00:00 2017'

  41. >>> d.strftime('%Y/%m/%d')

  42. '2017/02/04'

4. datetime.time類

time類的定義

class datetime.time(hour, [minute[, second, [microsecond[, tzinfo]]]])

hour為必須引數,其他為可選引數。各引數的取值範圍為::

引數名稱 取值範圍
hour [0, 23]
minute [0, 59]
second [0, 59]
microsecond [0, 1000000]
tzinfo tzinfo的子類物件,如timezone類的例項

類方法和屬性

類方法/屬性名稱 描述
time.max time類所能表示的最大時間:time(23, 59, 59, 999999)
time.min time類所能表示的最小時間:time(0, 0, 0, 0)
time.resolution 時間的最小單位,即兩個不同時間的最小差值:1微秒

物件方法和屬性

物件方法/屬性名稱 描述
t.hour
t.minute
t.second
t.microsecond 微秒
t.tzinfo 返回傳遞給time構造方法的tzinfo物件,如果該引數未給出,則返回None
t.replace(hour[, minute[, second[, microsecond[, tzinfo]]]]) 生成並返回一個新的時間物件,原時間物件不變
t.isoformat() 返回一個‘HH:MM:SS.%f’格式的時間字串
t.strftime() 返回指定格式的時間字串,與time模組的strftime(format, struct_time)功能相同

例項

 
  1. >>> from datetime import time

  2. >>>

  3. >>> time.max

  4. datetime.time(23, 59, 59, 999999)

  5. >>> time.min

  6. datetime.time(0, 0)

  7. >>> time.resolution

  8. datetime.timedelta(0, 0, 1)

  9. >>>

  10. >>> t = time(20, 5, 40, 8888)

  11. >>> t.hour

  12. 20

  13. >>> t.minute

  14. 5

  15. >>> t.second

  16. 40

  17. >>> t.microsecond

  18. 8888

  19. >>> t.tzinfo

  20. >>>

  21. >>> t.replace(21)

  22. datetime.time(21, 5, 40, 8888)

  23. >>> t.isoformat()

  24. '20:05:40.008888'

  25. >>> t.strftime('%H%M%S')

  26. '200540'

  27. >>> t.strftime('%H%M%S.%f')

  28. '200540.008888'

5. datetime.datetime類

datetime類的定義

class datetime.datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None)

year, month 和 day是必須要傳遞的引數, tzinfo可以是None或tzinfo子類的例項。

各引數的取值範圍為:

引數名稱 取值範圍
year [MINYEAR, MAXYEAR]
month [1, 12]
day [1, 指定年份的月份中的天數]
hour [0, 23]
minute [0, 59]
second [0, 59]
microsecond [0, 1000000]
tzinfo tzinfo的子類物件,如timezone類的例項

如果一個引數超出了這些範圍,會引起ValueError異常。

類方法和屬性

類方法/屬性名稱 描述
datetime.today() 返回一個表示當前本期日期時間的datetime物件
datetime.now([tz]) 返回指定時區日期時間的datetime物件,如果不指定tz引數則結果同上
datetime.utcnow() 返回當前utc日期時間的datetime物件
datetime.fromtimestamp(timestamp[, tz]) 根據指定的時間戳建立一個datetime物件
datetime.utcfromtimestamp(timestamp) 根據指定的時間戳建立一個datetime物件
datetime.combine(date, time) 把指定的date和time物件整合成一個datetime物件
datetime.strptime(date_str, format) 將時間字串轉換為datetime物件

物件方法和屬性

物件方法/屬性名稱 描述
dt.year, dt.month, dt.day 年、月、日
dt.hour, dt.minute, dt.second 時、分、秒
dt.microsecond, dt.tzinfo 微秒、時區資訊
dt.date() 獲取datetime物件對應的date物件
dt.time() 獲取datetime物件對應的time物件, tzinfo 為None
dt.timetz() 獲取datetime物件對應的time物件,tzinfo與datetime物件的tzinfo相同
dt.replace([year[, month[, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]]]]]) 生成並返回一個新的datetime物件,如果所有引數都沒有指定,則返回一個與原datetime物件相同的物件
dt.timetuple() 返回datetime物件對應的tuple(不包括tzinfo)
dt.utctimetuple() 返回datetime物件對應的utc時間的tuple(不包括tzinfo)
dt.toordinal() 同date物件
dt.weekday() 同date物件
dt.isocalendar() 同date獨享
dt.isoformat([sep]) 返回一個‘%Y-%m-%d
dt.ctime() 等價於time模組的time.ctime(time.mktime(d.timetuple()))
dt.strftime(format) 返回指定格式的時間字串

例項

 
  1. >>> from datetime import datetime, timezone

  2. >>>

  3. >>> datetime.today()

  4. datetime.datetime(2017, 2, 4, 20, 44, 40, 556318)

  5. >>> datetime.now()

  6. datetime.datetime(2017, 2, 4, 20, 44, 56, 572615)

  7. >>> datetime.now(timezone.utc)

  8. datetime.datetime(2017, 2, 4, 12, 45, 22, 881694, tzinfo=datetime.timezone.utc)

  9. >>> datetime.utcnow()

  10. datetime.datetime(2017, 2, 4, 12, 45, 52, 812508)

  11. >>> import time

  12. >>> datetime.fromtimestamp(time.time())

  13. datetime.datetime(2017, 2, 4, 20, 46, 41, 97578)

  14. >>> datetime.utcfromtimestamp(time.time())

  15. datetime.datetime(2017, 2, 4, 12, 46, 56, 989413)

  16. >>> datetime.combine(date(2017, 2, 4), t)

  17. datetime.datetime(2017, 2, 4, 20, 5, 40, 8888)

  18. >>> datetime.strptime('2017/02/04 20:49', '%Y/%m/%d %H:%M')

  19. datetime.datetime(2017, 2, 4, 20, 49)

  20. >>> dt = datetime.now()

  21. >>> dt

  22. datetime.datetime(2017, 2, 4, 20, 57, 0, 621378)

  23. >>> dt.year

  24. 2017

  25. >>> dt.month

  26. 2

  27. >>> dt.day

  28. 4

  29. >>> dt.hour

  30. 20

  31. >>> dt.minute

  32. 57

  33. >>> dt.second

  34. 0

  35. >>> dt.microsecond

  36. 621378

  37. >>> dt.tzinfo

  38. >>> dt.timestamp()

  39. 1486213020.621378

  40. >>> dt.date()

  41. datetime.date(2017, 2, 4)

  42. >>> dt.time()

  43. datetime.time(20, 57, 0, 621378)

  44. >>> dt.timetz()

  45. datetime.time(20, 57, 0, 621378)

  46. >>> dt.replace()

  47. datetime.datetime(2017, 2, 4, 20, 57, 0, 621378)

  48. >>> dt.replace(2016)

  49. datetime.datetime(2016, 2, 4, 20, 57, 0, 621378)

  50. >>> dt.timetuple()

  51. time.struct_time(tm_year=2017, tm_mon=2, tm_mday=4, tm_hour=20, tm_min=57, tm_sec=0, tm_wday=5, tm_yday=35, tm_isdst=-1)

  52. >>> dt.utctimetuple()

  53. time.struct_time(tm_year=2017, tm_mon=2, tm_mday=4, tm_hour=20, tm_min=57, tm_sec=0, tm_wday=5, tm_yday=35, tm_isdst=0)

  54. >>> dt.toordinal()

  55. 736364

  56. >>> dt.weekday()

  57. 5

  58. >>> dt.isocalendar()

  59. (2017, 5, 6)

  60. >>> dt.isoformat()

  61. '2017-02-04T20:57:00.621378'

  62. >>> dt.isoformat(sep='/')

  63. '2017-02-04/20:57:00.621378'

  64. >>> dt.isoformat(sep=' ')

  65. '2017-02-04 20:57:00.621378'

  66. >>> dt.ctime()

  67. 'Sat Feb 4 20:57:00 2017'

  68. >>> dt.strftime('%Y%m%d %H:%M:%S.%f')

  69. '20170204 20:57:00.621378'

6. 使用datetime.datetime類對時間戳與時間字串進行轉換

1063221-20170205083810667-126583354.png

7. datetime.timedelta類

timedelta物件表示連個不同時間之間的差值。如果使用time模組對時間進行算術執行,只能將字串格式的時間 和 struct_time格式的時間物件 先轉換為時間戳格式,然後對該時間戳加上或減去n秒,最後再轉換回struct_time格式或字串格式,這顯然很不方便。而datetime模組提供的timedelta類可以讓我們很方面的對datetime.date, datetime.time和datetime.datetime物件做算術運算,且兩個時間之間的差值單位也更加容易控制。
這個差值的單位可以是:天、秒、微秒、毫秒、分鐘、小時、周。

datetime.timedelta類的定義

class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, hours=0, weeks=0)

所有引數都是預設引數,因此都是可選引數。引數的值可以是整數或浮點數,也可以是正數或負數。內部值儲存days、seconds 和 microseconds,其他所有引數都將被轉換成這3個單位:

  • 1毫秒轉換為1000微秒
  • 1分鐘轉換為60秒
  • 1小時轉換為3600秒
  • 1週轉換為7天

然後對這3個值進行標準化,使得它們的表示是唯一的:

  • microseconds : [0, 999999]
  • seconds : [0, 86399]
  • days : [-999999999, 999999999]

類屬性

類屬性名稱 描述
timedelta.min timedelta(-999999999)
timedelta.max timedelta(days=999999999, hours=23, minutes=59, seconds=59, microseconds=999999)
timedelta.resolution timedelta(microseconds=1)

例項方法和屬性

例項方法/屬性名稱 描述
td.days 天 [-999999999, 999999999]
td.seconds 秒 [0, 86399]
td.microseconds 微秒 [0, 999999]
td.total_seconds() 時間差中包含的總秒數,等價於: td / timedelta(seconds=1)
方法/屬性 描述
datetime.datetime.now() 返回當前本地時間(datetime.datetime物件例項)
datetime.datetime.fromtimestamp(timestamp) 返回指定時間戳對應的時間(datetime.datetime物件例項)
datetime.timedelta() 返回一個時間間隔物件,可以直接與datetime.datetime物件做加減操作

例項

 
  1. >>> import datetime

  2. >>>

  3. >>> datetime.timedelta(365).total_seconds() # 一年包含的總秒數

  4. 31536000.0

  5. >>> dt = datetime.datetime.now()

  6. >>> dt + datetime.timedelta(3) # 3天后

  7. datetime.datetime(2017, 2, 8, 9, 39, 40, 102821)

  8. >>> dt + datetime.timedelta(-3) # 3天前

  9. datetime.datetime(2017, 2, 2, 9, 39, 40, 102821)

  10. >>> dt + datetime.timedelta(hours=3) # 3小時後

  11. datetime.datetime(2017, 2, 5, 12, 39, 40, 102821)

  12. >>> dt + datetime.timedelta(hours=-3) # 3小時前

  13. datetime.datetime(2017, 2, 5, 6, 39, 40, 102821)

  14. >>> dt + datetime.timedelta(hours=3, seconds=30) # 3小時30秒後

  15. datetime.datetime(2017, 2, 5, 12, 40, 10, 102821)

五、時間格式碼


time模組的struct_time以及datetime模組的datetime、date、time類都提供了strftime()方法,該方法可 以輸出一個指定格式的時間字串。具體格式由一系列的格式碼(格式字元)組成,Python最終呼叫的是各個平臺C庫的strftme()函式,因此各平臺對全套格式碼的支援會有所不同,具體情況需要參考該平臺上的strftime(3)文件。下面列出了C標準(1989版)要求的所有格式碼,它們在所有標準C實現的平臺上都可以工作:

1063221-20170205104434573-1343126060.png

六、總結


那麼Python中處理時間時,使用time模組好,還是用datetime模組好呢?就我個人而言,datetime模組基本上可以滿足需要,且用起來確實比較方便。對於time模組,我只是在取當前時間的時間戳時會用到time.time()方法,當然也可以通過datetime.datetime.now().timestamp()來獲取,只是顯得複雜一點。我覺得還是看個人習慣吧,沒有什麼絕對的好壞之分。