Courses
Trong Python, chuỗi là một kiểu dữ liệu phổ biến để biểu diễn ngày và giờ, nhưng với vai trò là nhà khoa học dữ liệu và kỹ sư, chúng ta thường cần chuyển các chuỗi này thành đối tượng datetime để thực hiện nhiều thao tác như sắp xếp hoặc so sánh.
Chuyển chuỗi thành đối tượng datetime có thể khó khăn, đặc biệt với những người mới học Python. Vì vậy, trong bài viết này, tôi sẽ hướng dẫn bạn các bước cần thiết để sử dụng những phương pháp này, đồng thời cung cấp các ví dụ mã minh họa. Dù bạn là nhà phát triển giàu kinh nghiệm hay mới bắt đầu, hãy cùng khám phá thế giới đối tượng datetime trong Python!
Để tự mình chạy dễ dàng toàn bộ mã ví dụ trong hướng dẫn này, bạn có thể tạo một sổ tay DataLab miễn phí với Python cài sẵn và chứa mọi đoạn mã mẫu. Để luyện tập thêm cách chuyển chuỗi thành đối tượng datetime, hãy xem bài tập thực hành trên DataCamp này.
TL;DR
Dùng datetime.strptime(date_string, format) để chuyển chuỗi thành đối tượng datetime trong Python. Với nhu cầu phân tích linh hoạt không cần chuỗi định dạng, dùng dateutil.parser.parse(). Với DataFrame, pd.to_datetime() xử lý hiệu quả cả cột. Mã định dạng chủ chốt: %Y (năm 4 chữ số), %m (tháng), %d (ngày), %H (giờ), %M (phút), %S (giây).
Giới thiệu về mô-đun datetime của Python
Mô-đun datetime, vốn được tích hợp sẵn trong Python, có thể dùng bất cứ khi nào bạn cần làm việc với ngày, giờ hoặc khoảng thời gian cho mọi ứng dụng viết bằng Python. Nó cung cấp các lớp và phương thức tiện lợi để biểu diễn và thao tác dữ liệu ngày giờ.
Bảng 1: Tóm tắt các lớp và phương thức trong mô-đun datetime
| Lớp/Phương thức | Mục đích | Tình huống sử dụng phổ biến |
|---|---|---|
| datetime.date | Biểu diễn một ngày (năm, tháng, ngày). | Tính chênh lệch giữa các ngày, định dạng ngày thành chuỗi, trích xuất thành phần ngày. |
| datetime.time | Biểu diễn thời điểm trong ngày (giờ, phút, giây, microsecond). | So sánh thời điểm, định dạng thời gian thành chuỗi, trích xuất thành phần thời gian. |
| datetime.datetime | Biểu diễn ngày và giờ. Kết hợp chức năng của date và time. | Làm việc với dữ liệu chuỗi thời gian, trích xuất thành phần ngày và giờ, định dạng thành chuỗi. |
| datetime.timedelta | Biểu diễn chênh lệch giữa hai mốc ngày hoặc giờ (khoảng thời gian). | Cộng/trừ khoảng thời gian với ngày hoặc giờ, tính khoảng thời gian. |
| datetime.strptime() | Phân tích một chuỗi thành đối tượng datetime dựa trên định dạng chỉ định. | Chuyển chuỗi thành đối tượng datetime để tiếp tục thao tác và phân tích. |
| datetime.strftime() | Định dạng đối tượng datetime thành chuỗi dựa trên định dạng chỉ định. | Chuyển đối tượng datetime thành chuỗi dễ đọc cho hiển thị hoặc báo cáo. |
Hãy hiểu các lớp chính trong mô-đun này, vì chúng ta sẽ chuyển chúng thành các đối tượng datetime:
1. datetime.date
Lớp này biểu diễn một ngày (năm, tháng, ngày) và cung cấp các phương thức làm việc với ngày, chẳng hạn tính chênh lệch giữa hai ngày và định dạng ngày thành chuỗi.
Giả sử chúng ta có bộ dữ liệu chứa giá cổ phiếu hằng ngày của một công ty. Ta có thể dùng lớp date để trích xuất các ngày từ bộ dữ liệu và vẽ đồ thị giá cổ phiếu theo thời gian.
Dưới đây là đoạn mã minh họa cách dùng lớp date:
from datetime import date
# create a date object representing March 1, 2023
start_date = date(2023, 3, 1)
# extract information such as the year, month, and day
year = start_date.year
month = start_date.month
day = start_date.day
# get the day of the week (Note: Monday is coded as 0, and Sunday as 6)
weekday = start_date.weekday()
# the date can be formatted as a string if needed
date_str = start_date.strftime('%Y-%m-%d')
2. datetime.time
Lớp này biểu diễn thời điểm trong ngày (giờ, phút, giây, microsecond) và cung cấp các phương thức làm việc với thời gian như so sánh và định dạng thời gian thành chuỗi.
Giả sử chúng ta có một bộ dữ liệu chứa thời gian về đích của một cuộc đua; ta có thể dùng lớp time để trích xuất giờ và phút khi mỗi vận động viên về đích.
from datetime import time
# create a time object with the microsecond granularity
end_time = time(15, 45, 30, 500000)
# get the hour and minute
hour = end_time.hour
minute = end_time.minute
second = end_time.second
microsecond = end_time.microsecond
3. datetime.datetime
Lớp này biểu diễn cả ngày và giờ, cung cấp các phương thức làm việc với cả hai. Nó kết hợp chức năng của các lớp date và time.
Lớp này thường dùng trong các tác vụ phân tích dữ liệu liên quan đến dữ liệu chuỗi thời gian có độ phân giải thời gian cao, như dữ liệu theo giờ hoặc theo phút. Giả sử ta có bộ dữ liệu chứa nhu cầu điện năng theo giờ của một thành phố. Ta có thể dùng lớp datetime để trích xuất ngày và giờ từ bộ dữ liệu và vẽ đồ thị nhu cầu điện theo thời gian. Để trực quan hóa loại dữ liệu này, xem hướng dẫn đồ thị đường chuỗi thời gian với Matplotlib của chúng tôi.
from datetime import datetime
# create a datetime object representing March 1, 2023 at 9:30 AM
start_datetime = datetime(2023, 3, 1, 9, 30)
# get the year, month, day, hour, and minute
year = start_datetime.year
month = start_datetime.month
day = start_datetime.day
hour = start_datetime.hour
minute = start_datetime.minute
4. datetime.timedelta
Lớp này biểu diễn một khoảng thời lượng hoặc khoảng thời gian và cung cấp các phương thức làm việc với khoảng thời gian, như cộng hoặc trừ khoảng thời gian với ngày hoặc giờ.
Giả sử ta có bộ dữ liệu chứa thời gian bắt đầu và kết thúc của một tập hợp sự kiện, và ta muốn tính tổng thời lượng của tất cả sự kiện. Ta có thể dùng lớp timedelta để tính thời lượng từng sự kiện rồi cộng lại.
from datetime import timedelta
# create a timedelta object representing 3 hours and 15 minutes
event_duration = timedelta(hours=3, minutes=15)
# get the total duration in seconds
event_duration_seconds = event_duration.total_seconds()
# add the duration to a start time to get an end time
event_start_time = datetime(2023, 3, 1, 18, 15)
event_end_time = event_start_time + event_duration
Trong tất cả các ví dụ trên, chúng ta đã dùng các đối tượng datetime, nhưng dữ liệu trong thực tế thường ở dạng chuỗi. Việc chuyển sang đối tượng datetime sẽ mở khóa toàn bộ các chức năng mạnh mẽ nêu trên cho phân tích và ứng dụng khoa học dữ liệu.
Sử dụng datetime.strptime() để chuyển đổi Datetime
Trong Python, ta có thể dùng phương thức datetime.strptime() để chuyển một chuỗi thành đối tượng datetime. Phương thức strptime() nhận hai đối số: chuỗi cần chuyển và chuỗi định dạng chỉ rõ định dạng của chuỗi đầu vào.
Chuỗi định dạng dùng kết hợp các mã định dạng để biểu diễn các thành phần khác nhau của ngày và giờ. Dưới đây là một số mã định dạng thường dùng (các khái niệm tương tự cũng áp dụng trong định dạng chuỗi trong Python):
Bảng 2: Các mã định dạng datetime phổ biến
| Mã định dạng | Mô tả | Ví dụ đầu vào | Ví dụ đầu ra |
|---|---|---|---|
| %Y | Năm 4 chữ số | 2023 | 2023 |
| %y | Năm 2 chữ số | 23 | 23 |
| %m | Tháng 2 chữ số (01-12) | 03 | 03 |
| %d | Ngày trong tháng 2 chữ số (01-31) | 15 | 15 |
| %H | Giờ 2 chữ số (00-23) | 14 | 14 |
| %I | Giờ 2 chữ số (01-12) | 02 | 02 |
| %M | Phút 2 chữ số (00-59) | 45 | 45 |
| %S | Giây 2 chữ số (00-59) | 30 | 30 |
| %f | Microsecond (000000-999999) | 123456 | 123456 |
| %p | AM hoặc PM | PM | PM |
| %z | Độ lệch UTC | +0530 | +0530 |
| %a | Tên viết tắt thứ trong tuần | Tue | Tue |
| %A | Tên đầy đủ thứ trong tuần | Tuesday | Tuesday |
| %b | Tên viết tắt tháng | Mar | Mar |
| %B | Tên đầy đủ tháng | March | March |
| %j | Ngày thứ bao nhiêu trong năm (001-366) | 074 | 074 |
| %U | Tuần thứ bao nhiêu trong năm (Chủ nhật là ngày đầu) | 10 | 10 |
| %W | Tuần thứ bao nhiêu trong năm (Thứ hai là ngày đầu) | 09 | 09 |
Giờ đây khi đã hiểu các chỉ thị strptime, quá trình chuyển chuỗi thành đối tượng datetime sẽ được đơn giản hóa.
- Bước 01: Phân tích chuỗi ngày-giờ có thể chuyển đổi để tìm mẫu khớp với các mã định dạng.
- Bước 02: Tạo định dạng ngày-giờ từ các chỉ thị strptime().
- Bước 03: Truyền chuỗi và định dạng vào hàm và nhận đối tượng làm đầu ra.
Hãy áp dụng các bước này vào thực tế.
Chuyển một chuỗi theo định dạng cụ thể thành đối tượng datetime
from datetime import datetime
# Example with the standard date and time format
date_str = '2023-02-28 14:30:00'
date_format = '%Y-%m-%d %H:%M:%S'
date_obj = datetime.strptime(date_str, date_format)
print(date_obj)
# Example with a different format
date_str = '02/28/2023 02:30 PM'
date_format = '%m/%d/%Y %I:%M %p'
date_obj = datetime.strptime(date_str, date_format)
print(date_obj)
Trong ví dụ đầu tiên, chúng ta có một chuỗi biểu diễn ngày và giờ theo định dạng ‘YYYY-MM-DD HH:MM:SS’, và ở ví dụ thứ hai là một định dạng khác, ‘MM/DD/YYYY HH:MM AM/PM’.
Ở cả hai trường hợp, sau khi chỉ định chính xác chuỗi định dạng làm đối số thứ hai cho strptime(), ta sẽ nhận được đối tượng datetime đúng.
Chuyển một chuỗi có thông tin múi giờ thành đối tượng datetime
from datetime import datetime
date_str = '2023-02-28 14:30:00+05:30'
date_format = '%Y-%m-%d %H:%M:%S%z'
date_obj = datetime.strptime(date_str, date_format)
print(date_obj)
Trong ví dụ này, ta có một chuỗi biểu diễn ngày và giờ kèm thông tin múi giờ theo định dạng ‘YYYY-MM-DD HH:MM:SS+TZOFFSET’, trong đó TZOFFSET là độ lệch múi giờ theo giờ và phút so với UTC. Ta chỉ định chuỗi định dạng làm đối số thứ hai cho strptime(), bao gồm mã định dạng %z để phân tích độ lệch múi giờ.
Mặc dù hàm ở trên có vẻ dễ về mặt lý thuyết, nhưng trong thực tế nó cũng có thể gây khó chịu khi xảy ra lỗi.
Phân tích ngày không cần chuỗi định dạng bằng dateutil
Một lựa chọn linh hoạt khác là thư viện dateutil, đặc biệt là hàm parser.parse(). Nó tự động phát hiện định dạng ngày, cho phép bạn phân tích chuỗi mà không cần chỉ định chuỗi định dạng.
from dateutil.parser import parse
# Automatically infers the format
date_obj = parse("March 1, 2023 9:30 AM")
print(date_obj)
Điều này đặc biệt hữu ích khi xử lý các định dạng ngày không đoán trước được hoặc không nhất quán.
Xử lý múi giờ
Để xử lý datetime có nhận biết múi giờ, Python cung cấp hai lựa chọn phổ biến:
-
pytz (được dùng rộng rãi và tương thích với các phiên bản cũ)
-
zoneinfo (giới thiệu trong Python 3.9, là một phần của thư viện chuẩn)
from datetime import datetime
from zoneinfo import ZoneInfo
# Using zoneinfo
dt = datetime(2023, 3, 1, 9, 30, tzinfo=ZoneInfo("America/New_York"))
print(dt)
# Using pytz (alternative)
import pytz
tz = pytz.timezone("America/New_York")
dt_pytz = tz.localize(datetime(2023, 3, 1, 9, 30))
print(dt_pytz)
Những công cụ này cho phép bạn gán múi giờ, chuyển đổi giữa các múi giờ và tự động tính đến giờ mùa hè (DST).
Các lưu ý về giờ mùa hè (DST)
Khi làm việc với datetime có nhận biết múi giờ, giờ mùa hè (DST) có thể gây phức tạp—đặc biệt khi đồng hồ được chỉnh tiến hoặc lùi.
Các thư viện như zoneinfo và pytz quản lý việc chuyển đổi DST tự động khi bạn gán đúng múi giờ:
from datetime import datetime
from zoneinfo import ZoneInfo
# Before and after DST starts
before_dst = datetime(2023, 3, 12, 1, 30, tzinfo=ZoneInfo("America/New_York"))
after_dst = datetime(2023, 3, 12, 3, 30, tzinfo=ZoneInfo("America/New_York"))
print(before_dst)
print(after_dst)
Điều này đảm bảo các phép tính datetime vẫn chính xác khi qua các mốc thay đổi DST.
Dùng pandas để chuyển đổi Datetime
Dù mô-đun datetime tích hợp của Python rất mạnh, nhiều nhà khoa học dữ liệu thích dùng thư viện pandas để chuyển đổi datetime vì tính đơn giản và khả năng xử lý hiệu quả cả cột ngày bằng DataFrame.
import pandas as pd
# Converting a column of strings to datetime objects
date_series = pd.to_datetime(['2023-02-28', '2023-03-01', '2023-03-02'])
print(date_series)
Pandas tự suy luận định dạng và xử lý khéo léo các điểm không nhất quán thường gặp, khiến nó trở thành lựa chọn hàng đầu khi làm việc với dữ liệu dạng bảng. Tìm hiểu thêm trong hướng dẫn Chuẩn bị dữ liệu với pandas của chúng tôi.
Định dạng đối tượng datetime thành chuỗi với strftime()
Sau khi bạn đã chuyển chuỗi thành đối tượng datetime và thực hiện các thao tác cần thiết, có thể bạn sẽ cần chuyển chúng lại thành chuỗi. Bạn có thể dùng datetime.strftime() cho mục đích này.
from datetime import datetime
now = datetime.now()
formatted = now.strftime('%Y-%m-%d %H:%M:%S')
print(formatted)
Phương thức này cho bạn toàn quyền kiểm soát cách đối tượng datetime được hiển thị dưới dạng chuỗi.
Khắc phục các lỗi strptime() thường gặp
Dưới đây là một số lỗi phổ biến bạn có thể gặp và cách khắc phục. Để tìm hiểu thêm về xử lý ngoại lệ trong Python, hãy xem hướng dẫn chuyên biệt của chúng tôi:
ValueError: time data 'date_string' does not match format '%Y-%m-%d %H:%M:%S'
Lỗi phổ biến nhất xảy ra khi chuỗi đầu vào không khớp với chuỗi định dạng. Hãy kiểm tra kỹ để đảm bảo chuỗi đầu vào và chuỗi định dạng khớp chính xác.
import datetime
# When using 4-digit year format but input has 2-digit year
date_str = '23-03-01'
date_obj = datetime.datetime.strptime(date_str, '%Y-%m-%d') # Wrong: %Y expects 4 digits
# Raises ValueError: time data '23-03-01' does not match format '%Y-%m-%d'
# When format doesn't match separator in string
time_str = '08:30:00'
time_obj = datetime.datetime.strptime(time_str, '%H-%M-%S') # Wrong: using - instead of :
# Raises ValueError: time data '08:30:00' does not match format '%H-%M-%S'
TypeError: strptime() argument 1 must be str, not 'int'
Lỗi phổ biến tiếp theo xảy ra khi bạn truyền một số nguyên vào datetime.strptime() hoặc time.strptime() thay vì chuỗi. Hãy đảm bảo tất cả giá trị bạn truyền vào hàm đều là chuỗi.
# Example 1: Integer instead of string
date_int = 20230301
date_obj = datetime.datetime.strptime(date_int, '%Y%m%d')
# Raises TypeError: strptime() argument 1 must be str, not int
# Example 2: List instead of string
date_list = [2023, 3, 1]
date_obj = datetime.datetime.strptime(date_list, '%Y-%m-%d')
# Raises TypeError: strptime() argument 1 must be str, not list
ValueError: unconverted data remains: ':00'
Lỗi này xảy ra khi còn ký tự thừa trong chuỗi đầu vào không khớp với chuỗi định dạng. Ví dụ, lỗi sẽ xảy ra nếu chuỗi định dạng chỉ chỉ định năm, tháng và ngày, nhưng chuỗi đầu vào còn chứa thời điểm trong ngày. Để gỡ lỗi, hãy đảm bảo chuỗi định dạng khớp với toàn bộ chuỗi đầu vào.
# when input string contains time of day
date_str = '2023-03-01 12:30:00'
date_obj = datetime.datetime.strptime(date_str, '%Y-%m-%d')
# Raises ValueError: unconverted data remains: 12:30:00
# When input string contains extra characters
date_str = '2023-03-01T00:00:00Z'
date_obj = datetime.datetime.strptime(date_str, '%Y-%m-%d')
# Raises ValueError: unconverted data remains: T00:00:00Z
Kết luận
Có thể nói phương thức datetime.strptime() cung cấp một cách linh hoạt và mạnh mẽ để chuyển chuỗi thành đối tượng datetime trong Python và có thể xử lý nhiều định dạng ngày giờ khác nhau. Tại sao bạn không tải về cheatsheet Ngày và Giờ của chúng tôi để tham khảo sau?
Sau khi hiểu về ngày và giờ, bước tiếp theo là luyện tập trong một dự án. Chúng tôi khuyến nghị bạn chọn một trong số này để củng cố kiến thức:
Chúng tôi đồng ý rằng dữ liệu ngày giờ trong thế giới thực rất phức tạp, nhưng tất cả những gì bạn cần là hiểu các định dạng và mẫu đằng sau từng loại ngày giờ trong dữ liệu của bạn và sử dụng các thư viện một cách khôn ngoan.
Câu hỏi thường gặp
Làm sao xử lý chuỗi có lẫn nhiều định dạng ngày trong cùng một bộ dữ liệu?
Khi làm việc với các bộ dữ liệu có lẫn nhiều định dạng ngày, bạn có thể dùng mô-đun dateutil của Python. Hàm dateutil.parser.parse() linh hoạt hơn datetime.strptime() vì nó có thể tự động phát hiện và phân tích nhiều định dạng ngày mà không cần chuỗi định dạng xác định trước:
from dateutil.parser import parse
date_str1 = '2023-03-01'
date_str2 = 'March 1, 2023'
date_obj1 = parse(date_str1)
date_obj2 = parse(date_str2)
print(date_obj1) # Output: 2023-03-01 00:00:00
print(date_obj2) # Output: 2023-03-01 00:00:00Tôi có thể chuyển chuỗi thành đối tượng datetime đồng thời xét đến các múi giờ khác nhau không?
Có, bạn có thể xử lý múi giờ bằng cách dùng thư viện pytz kết hợp với datetime. Trước hết, chuyển chuỗi thành đối tượng datetime, sau đó gắn múi giờ bằng pytz.timezone():
from datetime import datetime
import pytz
date_str = '2023-03-01 14:30:00'
date_format = '%Y-%m-%d %H:%M:%S'
date_obj = datetime.strptime(date_str, date_format)
# Set time zone
timezone = pytz.timezone('US/Eastern')
date_obj_tz = timezone.localize(date_obj)
print(date_obj_tz) # Output: 2023-03-01 14:30:00-05:00Sự khác nhau giữa datetime.strptime() và datetime.fromisoformat() là gì?
datetime.strptime() cho phép bạn chỉ định một chuỗi định dạng tùy chỉnh để phân tích các định dạng ngày không chuẩn hoặc đa dạng.
datetime.fromisoformat() được thiết kế riêng để phân tích các chuỗi ngày theo chuẩn ISO 8601 (ví dụ: '2023-03-01T14:30:00'). Nó đơn giản hơn nếu chuỗi của bạn tuân thủ nghiêm ngặt chuẩn ISO 8601:
from datetime import datetime
iso_date_str = '2023-03-01T14:30:00'
date_obj = datetime.fromisoformat(iso_date_str)
print(date_obj) # Output: 2023-03-01 14:30:00Làm thế nào để chuyển một đối tượng datetime về chuỗi trong Python?
Dùng phương thức strftime() để chuyển một đối tượng datetime về chuỗi. Truyền vào một chuỗi định dạng chỉ cách bạn muốn hiển thị kết quả:
from datetime import datetime
dt = datetime(2023, 3, 1, 14, 30)
date_string = dt.strftime('%Y-%m-%d %H:%M:%S')
print(date_string) # Output: 2023-03-01 14:30:00Các mã định dạng giống với những mã dùng cùng strptime(), giúp bạn dễ dàng chuyển đổi hai chiều giữa chuỗi và đối tượng datetime.
Sự khác nhau giữa strptime() và strftime() trong Python là gì?
strptime() và strftime() là hai thao tác ngược nhau:
strptime()("string parse time") chuyển chuỗi thành đối tượng datetime. Nó nhận chuỗi và định dạng làm đối số.strftime()("string format time") chuyển đối tượng datetime thành chuỗi. Nó định dạng datetime theo chuỗi định dạng chỉ định.
Mẹo ghi nhớ: strptime() dùng để phân tích chuỗi, còn strftime() dùng để định dạng ra chuỗi.
Với vai trò nhà khoa học dữ liệu cao cấp, tôi thiết kế, phát triển và triển khai các giải pháp học máy quy mô lớn để giúp doanh nghiệp ra quyết định dựa trên dữ liệu hiệu quả hơn. Với vai trò tác giả về khoa học dữ liệu, tôi chia sẻ những bài học kinh nghiệm, lời khuyên nghề nghiệp và các hướng dẫn thực hành chuyên sâu.
