在 Python/ target=_blank class=infotextkey>Python 中處理日期和時間可能很麻煩。值得慶幸的是,有一種內置的方法可以讓它變得更容易:Python datetime 模塊。
datetime 幫助我們識別和處理與時間相關的元素,如日期、小時、分鐘、秒、星期幾、月份、年份等。它提供各種服務,如管理時區和夏令時。它可以處理時間戳數據。它可以從字符串中提取星期幾、月份中的某一天以及其他日期和時間格式。
簡而言之,它是處理 Python 中與日期和時間相關的任何內容的非常強大的方法。讓我們開始吧!
在本教程中,我們將詳細了解 Python 日期時間函數,包括:
- 創建日期對象
- 從日期獲取年和月
- 從日期獲取月日和工作日
- 從日期獲取小時和分鐘
- 從日期獲取一年中的周數
- 將日期對象轉換為時間戳
- 將 UNIX 時間戳字符串轉換為日期對象
- 處理 timedelta 對象
- 獲取兩個日期和時間之間的差異
- 格式化日期:strftime() 和 strptime()
- 處理時區
- 使用 Pandas 日期時間對象獲取年、月、日、小時和分鐘獲取工作日和一年中的某一天將日期對象轉換為 DataFrame 索引
Python 日期時間類
在開始編寫代碼之前,有必要了解一下datetime 模塊中使用的五個主要對象類 。根據我們嘗試做的事情,我們可能需要使用這些不同的類中的一個或多個:
- datetime – 允許我們一起操作時間和日期(月、日、年、小時、秒、微秒)。
- date – 允許我們獨立于時間(月、日、年)操作日期。
- time – 允許我們獨立于日期(小時、分鐘、秒、微秒)操縱時間。
- timedelta — 用于操作日期和測量的持續時間。
- tzinfo — 處理時區的抽象類。
如果這些區別還沒有意義,請不要擔心!讓我們深入研究 datetime 并開始使用它,以更好地了解這些是如何應用的。
創建日期對象
首先,讓我們仔細看看一個 datetime 對象。由于 datetime 既是模塊又是該模塊中的類,我們將從datetime 從datetime 模塊中導入類 開始 。
然后,我們將打印當前日期和時間以仔細查看datetime 對象中包含的內容 。我們可以使用datetime的 .now() 函數來做到這一點 。我們將打印 datetime 對象,然后使用 using 打印其類型, type() 以便我們可以仔細查看。
# import datetime class from datetime module
from datetime import datetime
# get current date
datetime_object = datetime.now()
print(datetime_object)
print('Type :- ',type(datetime_object))
2019-10-25 10:24:01.521881
Type :-
從上面的結果我們可以看出datetime_object 確實是一個 類的 datetime 對象 datetime。這包括年、月、日、小時、分鐘、秒和微秒。
從日期中提取年和月
現在我們已經看到了是什么讓一個 datetime 對象,我們可能已經猜到了如何 date 和 time 對象看,因為我們知道, date 物體就像 datetime 沒有時間數據和 time 對象就像 datetime 沒有最新數據。
我們也可以預見一些問題。例如,在大多數數據集中,日期和時間信息以字符串格式存儲!此外,我們可能不 想要 所有這些日期和時間數據——如果我們正在做諸如每月銷售分析之類的事情,那么以微秒為單位進行細分將不會很有用。
所以現在,讓我們開始深入研究數據科學中的一個常見任務:使用 datetime.
為此,我們需要做一些事情。
使用 strptime() 和 strftime() 處理日期和時間字符串
值得慶幸的是,datetime 包括兩個方法, strptime() 和 strftime(),用于將對象從字符串轉換為 datetime 對象,反之亦然。 strptime() 可以讀取帶有日期和時間信息的字符串并將它們轉換為 datetime 對象, strftime() 并將日期時間對象轉換回字符串。
當然, strptime() 這不是魔法——它不能將 任何 字符串轉換為日期和時間,它需要我們的一些幫助來解釋它所看到的!但它能夠讀取日期和時間數據的大多數傳統字符串格式(有關更多詳細信息,請參閱 文檔)。讓我們給它一個 YYYY-MM-DD 格式的日期字符串,看看它能做什么!
my_string = '2019-10-31'
# Create date object in given time format yyyy-mm-dd
my_date = datetime.strptime(my_string, "%Y-%m-%d")
print(my_date)
print('Type: ',type(my_date))
2019-10-31 00:00:00 Type:
請注意,它strptime() 采用了兩個參數:字符串 ( my_string) 和 "%Y-%m-%d",另一個字符串告訴 strptime() 如何解釋輸入字符串 my_string。 %Y例如,告訴它期望字符串的前四個字符是年份。
文檔中提供了這些模式的完整列表 ,我們將在本教程后面更深入地介紹這些方法。
您可能還注意到 00:00:00 日期中添加了時間。那是因為我們創建了一個 datetime 對象,其中必須包含日期 和 時間。 00:00:00 如果在我們輸入的字符串中沒有指定時間,則是默認時間。
無論如何,我們希望為我們的分析分離出日期的特定元素。一種方法可以使用 datetime 對象的內置類屬性來做到這一點,例如 .month 或 .year:
print('Month: ', my_date.month) # To Get month from date
print('Year: ', my_date.year) # To Get month from year
Month: 10 Year: 2019
從日期獲取月份中的某天和一周中的某天
讓我們再做一些提取,因為這是一項非常常見的任務。這一次,我們將嘗試從 my_date. Datetime 將使用其.weekday() 函數為我們提供星期幾作為數字,但我們可以使用calendar 模塊和名為 的方法 將其 轉換為文本格式(即星期一、星期二、星期三……) day_name。
我們將從導入開始 calendar,然后使用 .day 和 .weekday() on my_date。從那里,我們可以像這樣以文本格式獲取星期幾:
# import calendar module
import calendar
print('Day of Month:', my_date.day)
# to get name of day(in number) from date
print('Day of Week (number): ', my_date.weekday())
# to get name of day from date
print('Day of Week (name): ', calendar.day_name[my_date.weekday()])
Day of Month: 31 Day of Week (number): 3 Day of Week (name): Thursday
等等,這看起來有點奇怪!一周的第三天應該是周三,而不是周四吧?
讓我們day_name 使用 for 循環仔細查看該 變量:
j = 0
for i in calendar.day_name:
print(j,'-',i)
j+=1
0 - Monday 1 - Tuesday 2 - Wednesday 3 - Thursday 4 - Friday 5 - Saturday 6 - Sunday
現在我們可以看到 Python 從星期一開始,從索引 0 開始計數,而不是從 1 開始。所以數字 3 被轉換為“星期四”是有道理的,正如我們上面看到的。
從 Python 日期時間對象獲取小時和分鐘
現在讓我們深入研究時間并從 datetime 對象中提取小時和分鐘。就像我們用月和年以上了,我們就可以使用類屬性 .hour ,并 .minute 拿到小時,一天分鐘。
讓我們使用該.now() 函數設置新的日期和時間 。在撰寫本文時,時間是 2019 年 10 月 25 日上午 10:25。當然,根據您選擇運行此代碼的時間,您將獲得不同的結果!
from datetime import datetime todays_date = datetime.now()
# to get hour from datetime
print('Hour: ', todays_date.hour)
# to get minute from datetime
print('Minute: ', todays_date.minute)
Hour: 10
Minute: 25
從日期時間對象獲取一年中的一周
我們還可以用 datetime. 例如,如果我們想知道今年是哪一周怎么辦?
我們可以datetime 使用該.isocalendar() 函數從對象中 獲取年、年中的一周和一周中的哪一天 。
具體來說, isocalendar() 返回一個包含 ISO 年份、周數和工作日的元組。在 ISO日歷 是基于公歷廣泛使用的標準日歷。您可以在該鏈接上更詳細地了解它,但出于我們的目的,我們只需要知道它作為一個常規日歷工作,從每周一開始。
# Return a 3-tuple, (ISO year, ISO week number, ISO weekday).
todays_date.isocalendar()
(2019, 43, 5)
請注意,在 ISO 日歷中,一周從 1 開始計數,因此這里的 5 代表一周中的正確日期:星期五。
我們可以從上面看到這是一年中的第 43 周,但是如果我們想隔離這個數字,我們可以像對任何其他 Python 列表或元組一樣使用索引來做到這一點:
todays_date.isocalendar()[1]
43
將日期對象轉換為 Unix 時間戳,反之亦然
在編程中,經常會遇到存儲為時間戳的時間和日期數據,或者想要以Unix 時間戳格式存儲自己的數據 。
我們可以使用 datetime 的內置timestamp() 函數來做到這一點 ,它接受一個 datetime 對象作為參數并以時間戳格式返回該日期和時間:
#import datetime
from datetime import datetime
# get current date
now = datetime.now()
# convert current date into timestamp
timestamp = datetime.timestamp(now)
print("Date and Time :", now)
print("Timestamp:", timestamp)
Date and Time : 2019-10-25 10:36:32.827300
Timestamp: 1572014192.8273
同樣,我們可以使用fromtimestamp(). 這是一個 datetime 以時間戳(浮點格式)為參數并返回一個 datetime 對象的函數,如下所示:
#import datetime
from datetime import datetime
timestamp = 1572014192.8273
#convert timestamp to datetime object
dt_object = datetime.fromtimestamp(timestamp)
print("dt_object:", dt_object)
print("type(dt_object): ", type(dt_object))
dt_object: 2019-10-25 10:36:32.827300
type(dt_object): <class 'datetime.datetime'>
使用 Timedelta 對象測量時間跨度
通常,我們可能希望使用 Python 日期時間來測量時間跨度或持續時間。我們可以用它的內置timedelta 類來做到這一點 。甲 timedelta 對象表示的兩個日期或時間之間的時間量。我們可以使用它來測量時間跨度,或者通過添加和減去它們等來操縱日期或時間。
默認情況下,timedelta 對象的所有參數都設置為零。讓我們創建一個兩周長的新 timedelta 對象,看看它看起來如何:
#import datetime
from datetime import timedelta
# create timedelta object with difference of 2 weeks
d = timedelta(weeks=2)
print(d)
print(type(d))
print(d.days)
14 days, 0:00:00
<class 'datetime.timedelta'>
14
請注意,我們可以使用timedelta class 屬性 獲取以天為單位的持續時間.days。正如我們在其文檔中所見 ,我們還可以以秒或微秒為單位獲取此持續時間。
讓我們創建另一個 timedelta 持續時間以獲得更多練習:
year = timedelta(days=365)
print(year)
365 days, 0:00:00
現在讓我們開始使用 timedelta 對象和 datetime 對象來做一些數學運算!具體來說,讓我們為當前時間和日期添加一些不同的持續時間,以查看 15 天后的日期,兩周前的日期。
為此,我們可以使用 + or - 運算符將 timedelta 對象添加到 datetime 對象或從 datetime 對象中減去。結果將是 datetime 對象加上或減去我們的 timedelta 對象中指定的持續時間。酷,對吧?
(注意:在下面的代碼中,時間是 10 月 25 日上午 11 點 12 分;您的結果將因運行代碼的時間而異,因為我們datetime 使用該.now() 函數獲取 對象 )。
#import datetime
from datetime import datetime, timedelta
# get current time
now = datetime.now()
print ("Today's date: ", str(now))
#add 15 days to current date
future_date_after_15days = now + timedelta(days = 15)
print('Date after 15 days: ', future_date_after_15days)
#subtract 2 weeks from current date
two_weeks_ago = now - timedelta(weeks = 2)
print('Date two weeks ago: ', two_weeks_ago)
print('two_weeks_ago object type: ', type(two_weeks_ago))
Today's date: 2019-10-25 11:12:24.863308 Date after 15 days: 2019-11-09 11:12:24.863308 Date two weeks ago: 2019-10-11 11:12:24.863308
two_weeks_ago object type: <class 'datetime.datetime'>
請注意,這些數學運算的輸出仍然是一個datetime 對象。
找出兩個日期和時間之間的差異
與我們上面所做的類似,我們還可以使用 datetime 從另一個日期中減去一個日期以找到它們之間的時間跨度。
因為這個數學運算的結果是一個 持續時間,當我們從另一個日期中減去一個日期時產生的對象將是一個 timedelta 對象。
在這里,我們將創建兩個 date 對象(請記住,它們的工作方式與datetime 對象相同 ,只是不包含時間數據)并從另一個中減去一個以找到持續時間:
# import datetime
from datetime import date
# Create two dates
date1 = date(2008, 8, 18)
date2 = date(2008, 8, 10)
# Difference between two dates
delta = date2 - date1
print("Difference: ", delta.days)
print('delta object type: ', type(delta))
Difference: -8
delta object type: <class 'datetime.timedelta'>
上面,為了清楚起見,我們只使用了日期,但我們可以對datetime 物體做同樣的事情,以獲得更精確的測量,包括小時、分鐘和秒:
# import datetime
from datetime import datetime
# create two dates with year, month, day, hour, minute, and second
date1 = datetime(2017, 6, 21, 18, 25, 30)
date2 = datetime(2017, 5, 16, 8, 21, 10)
# Difference between two dates
diff = date1-date2
print("Difference: ", diff)
Difference: 36 days, 10:04:20
格式化日期:更多關于 strftime() 和 strptime()
我們談到簡要地 strftime() 和 strptime() 較早,但讓我們在這些方法仔細看,因為他們是在Python數據分析工作往往是重要的。
strptime() 是我們之前使用的方法,您會記得它可以將格式化為文本字符串的日期和時間轉換為日期時間對象,格式如下:
time.strptime(string, format)
請注意,它需要兩個參數:
- string - 我們要轉換的字符串格式的時間
- format - 字符串中時間的特定格式,以便 strptime() 可以正確解析它
這次讓我們嘗試轉換不同類型的日期字符串。 該站點 是查找幫助strptime() 解釋我們的字符串輸入所需的格式代碼的非常有用的參考 。
# import datetime
from datetime import datetime
date_string = "1 August, 2019"
# format date
date_object = datetime.strptime(date_string, "%d %B, %Y")
print("date_object: ", date_object)
date_object: 2019-08-01 00:00:00
現在讓我們做一些更高級的事情來練習到目前為止我們學到的一切!我們將從字符串格式的日期開始,將其轉換為日期時間對象,然后查看幾種不同的格式化方式(dd/mm 和 mm/dd)。
然后,堅持使用 mm/dd 格式,我們將其轉換為 Unix 時間戳。然后,我們將它轉換成一個 datetime 對象,并轉換 是 使用一些不同的回字符串 的strftime模式 來控制輸出:
# import datetime
from datetime import datetime
dt_string = "12/11/2018 09:15:32"
# Considering date is in dd/mm/yyyy format
dt_object1 = datetime.strptime(dt_string, "%d/%m/%Y %H:%M:%S")
print("dt_object1:", dt_object1)
# Considering date is in mm/dd/yyyy format
dt_object2 = datetime.strptime(dt_string, "%m/%d/%Y %H:%M:%S")
print("dt_object2:", dt_object2)
# Convert dt_object2 to Unix Timestamp
timestamp = datetime.timestamp(dt_object2)
print('Unix Timestamp: ', timestamp)
# Convert back into datetime
date_time = datetime.fromtimestamp(timestamp)
d = date_time.strftime("%c")
print("Output 1:", d)
d = date_time.strftime("%x")
print("Output 2:", d)
d = date_time.strftime("%X")
print("Output 3:", d)
dt_object1: 2018-11-12 09:15:32
dt_object2: 2018-12-11 09:15:32
Unix Timestamp: 1544537732.0
Output 1: Tue Dec 11 09:15:32 2018
Output 2: 12/11/18
Output 3: 09:15:32
這是一張圖片,您可以將其與常用的有用 strptime 和 strftime 模式的備忘單一起保存:
讓我們使用這些進行更多練習:
# current date and time
now = datetime.now()
# get year from date
year = now.strftime("%Y")
print("Year:", year)
# get month from date
month = now.strftime("%m")
print("Month;", month)
# get day from date
day = now.strftime("%d")
print("Day:", day)
# format time in HH:MM:SS
time = now.strftime("%H:%M:%S")
print("Time:", time)
# format date
date_time = now.strftime("%m/%d/%Y, %H:%M:%S")
print("Date and Time:",date_time)
Year: 2019
Month; 10
Day: 25
Time: 11:56:41
Date and Time: 10/25/2019, 11:56:41
處理時區
當涉及時區時,在 Pythin 中處理日期和時間會變得更加復雜。幸運的是,該 pytz 模塊的存在是為了幫助我們處理跨時區轉換。它還處理使用夏令時的地方的夏令時。
我們可以使用該 localize 函數將時區位置添加到 Python 日期時間對象。然后我們可以使用該函數 astimezone() 將現有的本地時區轉換為我們指定的任何其他時區(它將我們想要轉換為的時區作為參數)。
例如:
# import timezone from pytz module
from pytz import timezone
# Create timezone US/Eastern
east = timezone('US/Eastern')
# Localize date
loc_dt = east.localize(datetime(2011, 11, 2, 7, 27, 0))
print(loc_dt)
# Convert localized date into Asia/Kolkata timezone
kolkata = timezone("Asia/Kolkata")
print(loc_dt.astimezone(kolkata))
# Convert localized date into Australia/Sydney timezone
au_tz = timezone('Australia/Sydney')
print(loc_dt.astimezone(au_tz))
2011-11-02 07:27:00-04:00
2011-11-02 16:57:00+05:30
2011-11-02 22:27:00+11:00
在處理包含多個不同時區的數據集時,此模塊可以幫助簡化生活。
使用 pandas 日期時間對象
數據科學家喜歡 pandas 的原因有很多。其中之一是它包含用于處理時間序列數據的廣泛功能和特性。就像datetime 它本身一樣 ,pandas 有 datetime 和 timedelta 對象,分別用于指定日期、時間和持續時間。
我們可以使用以下函數將日期、時間和持續時間文本字符串轉換為 Pandas Datetime 對象:
- to_datetime():將字符串日期和時間轉換為 Python 日期時間對象。
- to_timedelta():根據天、小時、分鐘和秒查找時間差異。
正如我們將看到的,這些函數實際上非常擅長通過自動檢測格式將字符串轉換為 Python 日期時間對象,而無需我們使用 strftime 模式定義它。
讓我們看一個簡單的例子:
# import pandas module as pd
import pandas as pd
# create date object using to_datetime() function
date = pd.to_datetime("8th of sep, 2019")
print(date)
2019-09-08 00:00:00
請注意,即使我們給它一個帶有一些復雜因素的字符串,例如“th”和“sep”而不是“Sep”。或“September”,pandas 能夠正確解析字符串并返回格式化的日期。
我們還可以使用 pandas(及其一些附屬的 numpy 功能)自動創建日期范圍作為 pandas 系列。例如,下面我們從上面定義的那一天開始創建一系列十二個日期。然后我們使用pd.date_range()以下命令從預定義日期開始創建一系列不同的日期 :
# Create date series using numpy and to_timedelta() function
date_series = date + pd.to_timedelta(np.arange(12), 'D')
print(date_series)
# Create date series using date_range() function
date_series = pd.date_range('08/10/2019', periods = 12, freq ='D')
print(date_series)
DatetimeIndex(['2019-09-08', '2019-09-09', '2019-09-10', '2019-09-11', '2019-09-12', '2019-09-13', '2019-09-14', '2019-09-15', '2019-09-16', '2019-09-17', '2019-09-18', '2019-09-19'], dtype='datetime64[ns]', freq=None)
DatetimeIndex(['2019-08-10', '2019-08-11', '2019-08-12', '2019-08-13', '2019-08-14', '2019-08-15', '2019-08-16', '2019-08-17', '2019-08-18', '2019-08-19', '2019-08-20', '2019-08-21'], dtype='datetime64[ns]', freq='D')
在 Pandas 中獲取年、月、日、時、分
我們可以使用dt 所有列的屬性輕松地從 Pandas 數據框列中的日期中獲取年、月、日、小時或分鐘 。例如,我們可以使用 df['date'].dt.year 從包含完整日期的 Pandas 列中僅提取年份。
為了探索這一點,讓我們使用上面創建的系列之一制作一個快速的 DataFrame:
# Create a DataFrame with one column date
df = pd.DataFrame()
df['date'] = date_series df.head()
|
日期 |
0 |
2019-08-10 |
1 |
2019-08-11 |
2 |
2019-08-12 |
3 |
2019-08-13 |
4 |
2019-08-14 |
現在,讓我們使用相關的 Python 日期時間(通過 訪問dt)屬性為日期的每個元素創建單獨的列 :
# Extract year, month, day, hour, and minute. Assign all these date component to new column.
df['year'] = df['date'].dt.year
df['month'] = df['date'].dt.month
df['day'] = df['date'].dt.day
df['hour'] = df['date'].dt.hour
df['minute'] = df['date'].dt.minute
df.head()
|
日期 |
年 |
月 |
日 |
小時 |
分鐘 |
0 |
2019-08-10 |
2019年 |
8 |
10 |
0 |
0 |
1 |
2019-08-11 |
2019年 |
8 |
11 |
0 |
0 |
2 |
2019-08-12 |
2019年 |
8 |
12 |
0 |
0 |
3 |
2019-08-13 |
2019年 |
8 |
13 |
0 |
0 |
4 |
2019-08-14 |
2019年 |
8 |
14 |
0 |
0 |
獲取工作日和一年中的某一天
Pandas 還能夠從它的 datetime 對象中獲取其他元素,比如星期幾和一年中的哪一天。同樣,我們可以使用 dt 屬性來做到這一點。請注意,此處,與 Python 中的一般情況一樣,一周從周一的索引 0 開始,因此一周中的第 5 天是 周六。
# get Weekday and Day of Year. Assign all these date component to new column.
df['weekday'] = df['date'].dt.weekday
df['day_name'] = df['date'].dt.weekday_name
df['dayofyear'] = df['date'].dt.dayofyear
df.head()
|
日期 |
年 |
月 |
日 |
小時 |
分鐘 |
工作日 |
日期名稱 |
一年中的一天 |
0 |
2019-08-10 |
2019年 |
8 |
10 |
0 |
0 |
5 |
周六 |
222 |
1 |
2019-08-11 |
2019年 |
8 |
11 |
0 |
0 |
6 |
星期日 |
223 |
2 |
2019-08-12 |
2019年 |
8 |
12 |
0 |
0 |
0 |
周一 |
224 |
3 |
2019-08-13 |
2019年 |
8 |
13 |
0 |
0 |
1 |
周二 |
225 |
4 |
2019-08-14 |
2019年 |
8 |
14 |
0 |
0 |
2 |
周三 |
226 |
將日期對象轉換為數據幀索引
我們還可以使用 pandas 將日期時間列放入我們的 DataFrame 的索引中。這對于探索性數據可視化等任務非常有幫助,因為 matplotlib 會識別出 DataFrame 索引是一個時間序列并相應地繪制數據。
為此,我們所要做的就是重新定義 df.index:
# Assign date column to dataframe index
df.index = df.date
df.head()
日期 |
年 |
月 |
日 |
小時 |
分鐘 |
工作日 |
日期名稱 |
一年中的一天 |
|
|
|
|
|
|
|
|
|
|
日期 |
2019-08-10 |
2019-08-10 |
2019年 |
8 |
10 |
0 |
0 |
5 |
周六 |
222 |
2019-08-11 |
2019-08-11 |
2019年 |
8 |
11 |
0 |
0 |
6 |
星期日 |
223 |
2019-08-12 |
2019-08-12 |
2019年 |
8 |
12 |
0 |
0 |
0 |
周一 |
224 |
2019-08-13 |
2019-08-13 |
2019年 |
8 |
13 |
0 |
0 |
1 |
周二 |
225 |
2019-08-14 |
2019-08-14 |
2019年 |
8 |
14 |
0 |
0 |
2 |
周三 |
226 |
結論
在本教程中,我們深入研究了 Python 日期時間,并且還對 Pandas 和日歷模塊進行了一些工作。我們已經介紹了很多,但請記住:學習某些東西的最佳方式是親自編寫代碼!
如果您想練習datetime 使用交互式答案檢查編寫代碼,請查看我們的 Python 中級課程, 了解有關 Python 中日期時間 的課程,其中包含交互式答案檢查和瀏覽器內代碼運行。