Xử lý các vấn đề về ngày và giờ trong Python
By hientd, at: 17:22 Ngày 01 tháng 12 năm 2022
Thời gian đọc ước tính: __READING_TIME__ minutes


Xử lý ngày và giờ trong Python đôi khi có thể khó khăn do nhiều vấn đề có thể phát sinh. Trong hầu hết các trường hợp, các vấn đề là do trả lời sai các câu hỏi Gì, Tại sao và Như thế nào.
1. Vấn đề 1: Phân tích chuỗi ngày và giờ
1.1 Sử dụng hàm datetime strptime
from datetime import datetime
date_string = "2023-05-28"
date_object = datetime.strptime(date_string, "%Y-%m-%d")
print(date_object) # datetime.datetime(2023, 5, 28, 0, 0)
Ưu điểm
- Cung cấp tính linh hoạt trong việc phân tích và định dạng ngày tháng theo các mẫu cụ thể.
- Xử lý một loạt các định dạng ngày.
Nhược điểm
- Yêu cầu quen thuộc với các chỉ thị định dạng được sử dụng trong
strptime()
vàstrftime()
.
- Không xử lý múi giờ hoặc giờ tiết kiệm ánh sáng ban ngày.
1.2 Sử dụng dateutil.parser.parse
from dateutil.parser import parse
dt = parse('Sun May 28 2023')
print(dt)
# datetime.datetime(2023, 5, 28, 0, 0)
print(dt.strftime('%d/%m/%Y'))
# 28/05/2023
Ưu điểm
- Tính linh hoạt:
dateutil.parser.parse
có thể xử lý nhiều định dạng ngày và giờ, bao gồm ISO 8601, RFC 2822, và nhiều định dạng khác. Nó có thể phân tích cú pháp ngày được biểu diễn ở các định dạng khác nhau mà không cần chỉ định định dạng cụ thể.
- Phân tích trực quan: Nó có thể giải thích các định dạng ngày tháng mơ hồ, chẳng hạn như "10/11/12", có thể được hiểu là ngày 11 tháng 10 năm 2012, hoặc ngày 10 tháng 11 năm 2012, tùy thuộc vào ngôn ngữ của người dùng.
dateutil.parser.parse
sử dụng ngữ cảnh và phép ước lượng để xác định cách giải thích chính xác dựa trên đầu vào đã cho.
- Phân tích một phần: Nó cho phép phân tích cú pháp ngày hoặc giờ một phần, chẳng hạn như "2021-05" hoặc "14:30", bằng cách điền vào các phần còn thiếu bằng các giá trị mặc định hợp lý. Tính năng này có thể hữu ích khi xử lý đầu vào không đầy đủ hoặc do người dùng cung cấp.
- Nhận biết múi giờ:
dateutil.parser.parse
cũng có thể xử lý các múi giờ được chỉ định trong chuỗi đầu vào. Nó có thể phân tích cú pháp ngày và giờ ở các múi giờ khác nhau và trả về các đối tượng datetime nhận biết múi giờ.
Nhược điểm
- Hiệu suất:
dateutil.parser.parse
là một trình phân tích cú pháp mạnh mẽ và linh hoạt, nhưng nó đi kèm với chi phí về hiệu suất. Việc phân tích các chuỗi ngày tháng phức tạp hoặc mơ hồ có thể chậm hơn so với các phương pháp phân tích cú pháp chuyên dụng hơn. Tuy nhiên, điều này không xảy ra thường xuyên.
- Phụ thuộc: dateutil không phải là mô-đun tích hợp sẵn trong thư viện chuẩn Python. Do đó, nếu bạn muốn sử dụng dateutil.parser.parse, bạn cần đảm bảo rằng thư viện dateutil được cài đặt như một phụ thuộc riêng biệt.
- Giải quyết sự mơ hồ: Mặc dù
dateutil.parser.parse
cố gắng giải thích các định dạng ngày tháng mơ hồ, nhưng nó không phải lúc nào cũng cung cấp kết quả mong muốn. Trình phân tích cú pháp dựa trên ngữ cảnh và phép ước lượng, điều này có thể dẫn đến các cách giải thích không mong muốn trong một số trường hợp.
- Thiếu điều khiển định dạng: Không giống như các phương pháp phân tích cú pháp khác yêu cầu chỉ định định dạng rõ ràng,
dateutil.parser.parse
dựa vào thuật toán phân tích cú pháp của nó để tự động xác định định dạng. Việc thiếu điều khiển này có thể là một nhược điểm khi bạn cần kiểm soát chặt chẽ định dạng đầu vào.
2. Vấn đề 2: Xử lý múi giờ
2.1 Sử dụng pytz
import pytz
from datetime import datetime
# Lấy thời gian hiện tại trong một múi giờ cụ thể
tz = pytz.timezone('America/New_York')
current_time = datetime.now(tz)
# Chuyển đổi datetime sang múi giờ khác
new_tz = pytz.timezone('Asia/Tokyo')
converted_time = current_time.astimezone(new_tz)
Ưu điểm
- Hỗ trợ múi giờ toàn diện bao gồm một phạm vi rộng lớn các múi giờ.
- Xử lý các thay đổi múi giờ trong quá khứ và tương lai.
- Cho phép chuyển đổi giữa các múi giờ khác nhau một cách chính xác.
Nhược điểm
- Yêu cầu một thư viện bên ngoài (
pytz
) cần được cài đặt riêng.
- Thư viện pytz có thể có những hạn chế trong các trường hợp ngoại lệ hiếm gặp hoặc với các múi giờ kỳ lạ.
2.2 Sử dụng dateutil
from dateutil import tz
from datetime import datetime
# Lấy thời gian hiện tại trong múi giờ cục bộ
current_time = datetime.now(tz.tzlocal())
# Chuyển đổi datetime sang múi giờ khác
new_tz = tz.gettz('Europe/London')
converted_time = current_time.astimezone(new_tz)
Ưu điểm
- Giản lược việc xử lý múi giờ với việc phát hiện múi giờ tự động.
- Cho phép chuyển đổi giữa các múi giờ khác nhau mà không cần thư viện bên ngoài.
Nhược điểm
- Thư viện dateutil có thể không hỗ trợ tất cả các trường hợp hiếm gặp hoặc ngoại lệ.
- Hiệu suất có thể chậm hơn so với các thư viện chuyên dụng hơn như
pytz
.
2.3 Sử dụng mô-đun zoneinfo (Python 3.9+)
from datetime import datetime
from zoneinfo import ZoneInfo
# Lấy thời gian hiện tại trong một múi giờ cụ thể
tz = ZoneInfo('America/New_York')
current_time = datetime.now(tz)
# Chuyển đổi datetime sang múi giờ khác
new_tz = ZoneInfo('Asia/Tokyo')
converted_time = current_time.astimezone(new_tz)
Ưu điểm
- Cung cấp khả năng xử lý múi giờ mà không cần thư viện bên ngoài.
- Sử dụng Cơ sở dữ liệu Múi giờ IANA, được công nhận rộng rãi và được cập nhật thường xuyên.
Nhược điểm
- Hạn chế đối với Python 3.9 trở lên.
- Có thể không xử lý các thay đổi múi giờ trong lịch sử ở các phiên bản Python cũ hơn.
3. Vấn đề: Toán tử ngày
3.1 Sử dụng lớp timedelta của mô-đun datetime
from datetime import datetime, timedelta
# Cộng/trừ ngày vào/từ ngày
current_date = datetime.now()
new_date = current_date + timedelta(days=7)
# Tính toán sự khác biệt giữa hai ngày
date1 = datetime(2023, 5, 1)
date2 = datetime(2023, 5, 15)
difference = date2 - date1
Ưu điểm
- Đơn giản và dễ sử dụng.
- Hỗ trợ các phép toán cơ bản như cộng và trừ.
- Cung cấp tính toán chính xác cho sự khác biệt về ngày.
Nhược điểm
- Hạn chế đối với các phép toán cơ bản.
- Không xử lý các trường hợp phức tạp như ngày làm việc hoặc ngày lễ.
3.2 Sử dụng lớp relativedelta của thư viện dateutil
from datetime import datetime
from dateutil.relativedelta import relativedelta
# Cộng/trừ tháng vào/từ ngày
current_date = datetime.now()
new_date = current_date + relativedelta(months=3)
# Tính toán sự khác biệt giữa hai ngày với khoảng thời gian
date1 = datetime(2023, 5, 1)
date2 = datetime(2023, 8, 15)
difference = relativedelta(date2, date1)
Ưu điểm
- Hỗ trợ các thao tác nâng cao như cộng hoặc trừ tháng hoặc năm.
- Xử lý các trường hợp phức tạp với các khoảng thời gian linh hoạt.
- Cung cấp khả năng kiểm soát chi tiết đối với toán tử ngày.
Nhược điểm
- Yêu cầu thư viện dateutil (không phải là một phần của thư viện chuẩn).
- Có thể gặp sự cố về hiệu suất khi làm việc với các khoảng ngày lớn.
3.3 Sử dụng thư viện Pendulum
import pendulum
# Cộng/trừ ngày vào/từ ngày
current_date = pendulum.now()
new_date = current_date.add(days=7)
# Tính toán sự khác biệt giữa hai ngày
date1 = pendulum.datetime(2023, 5, 1)
date2 = pendulum.datetime(2023, 5, 15)
difference = date2 - date1
dt = pendulum.now()
# Một khoảng thời gian là sự khác biệt giữa 2 thời điểm
period = dt - dt.subtract(days=3)
period.in_weekdays()
# Một khoảng thời gian là có thể lặp lại
for dt in period:
print(dt)
dur = pendulum.duration(days=15)
# Các thuộc tính khác
dur.weeks
dur.hours
# Các phương pháp tiện ích
dur.in_hours()
dur.in_words(locale="en_us")
# '2 weeks 1 day'
Ưu điểm
- Cung cấp một API biểu cảm và trực quan để thực hiện toán tử ngày.
- Xử lý múi giờ, DST và các hoạt động ngày phức tạp một cách liền mạch.
- Cung cấp các tính năng nâng cao như ngày làm việc và ngày lễ.
Nhược điểm
- Yêu cầu thư viện Pendulum (không phải là một phần của thư viện chuẩn).
- Sự phụ thuộc bổ sung và đường cong học tập tiềm năng so với các giải pháp tích hợp sẵn.
4. Vấn đề: Định dạng ngày và giờ
4.1 Sử dụng phương thức datetime strftime()
from datetime import datetime
current_time = datetime.now()
# Định dạng thời gian hiện tại thành "May 28, 2023"
formatted_time = current_time.strftime("%B %d, %Y")
# Định dạng thời gian hiện tại thành "Sunday, May 28, 2023 09:30 AM"
formatted_time = current_time.strftime("%A, %B %d, %Y %I:%M %p")
Ưu điểm
- Cung cấp khả năng kiểm soát chính xác đối với việc định dạng ngày và giờ.
- Hỗ trợ nhiều chỉ thị định dạng để tùy chỉnh đầu ra.
Nhược điểm
- Yêu cầu quen thuộc với các chỉ thị định dạng.
- Không phù hợp với tất cả các yêu cầu bản địa hóa, vì nó không tự động xử lý bản dịch.
4.2 Sử dụng các phương thức datetime strptime() và strftime() với mô-đun locale
import locale
from datetime import datetime
current_time = datetime.now()
# Đặt ngôn ngữ thành mặc định của người dùng
locale.setlocale(locale.LC_TIME, '')
# Định dạng thời gian hiện tại dựa trên ngôn ngữ của người dùng
formatted_time = current_time.strftime(locale.nl_langinfo(locale.D_T_FMT))
Ưu điểm
- Cung cấp định dạng bản địa hóa dựa trên cài đặt của người dùng.
- Cho phép tùy chỉnh định dạng ngày và giờ theo các ngôn ngữ cụ thể.
Nhược điểm
- Dựa vào cài đặt hệ thống của người dùng để lấy thông tin ngôn ngữ.
- Có thể không cung cấp kết quả nhất quán trên các nền tảng hoặc môi trường khác nhau.
4.3 Sử dụng thư viện arrow
import arrow
current_time = arrow.now()
# Định dạng thời gian hiện tại thành "May 28, 2023"
formatted_time = current_time.format("MMMM DD, YYYY")
# Định dạng thời gian hiện tại thành "Sunday, May 28, 2023 09:30 AM"
formatted_time = current_time.format("dddd, MMMM DD, YYYY hh:mm A")
Ưu điểm
- Cung cấp một API thân thiện với người dùng và biểu cảm để làm việc với ngày và giờ.
- Hỗ trợ nhiều tùy chọn định dạng bằng cách sử dụng mã thông báo để dễ dàng tùy chỉnh.
Nhược điểm
- Yêu cầu một thư viện bổ sung (arrow) cần được cài đặt riêng.
- Việc giới thiệu một thư viện mới có thể làm tăng chi phí về bảo trì và phụ thuộc.
5. Vấn đề: Giờ tiết kiệm ánh sáng ban ngày (DST)
5.1 Sử dụng thư viện pytz
import pytz
from datetime import datetime
# Lấy thời gian hiện tại trong một múi giờ cụ thể (với sự xem xét DST)
tz = pytz.timezone('America/New_York')
current_time = datetime.now(tz)
# Chuyển đổi datetime sang múi giờ khác (với sự xem xét DST)
new_tz = pytz.timezone('Europe/London')
converted_time = current_time.astimezone(new_tz)
Ưu điểm
- Tự động xử lý các chuyển đổi DST dựa trên múi giờ đã chỉ định.
- Cung cấp các chuyển đổi chính xác giữa các múi giờ khi xem xét các thay đổi DST.
Nhược điểm
- Yêu cầu một thư viện bên ngoài (pytz) cần được cài đặt riêng.
- Có thể có những hạn chế trong các trường hợp ngoại lệ hiếm gặp hoặc với các múi giờ kỳ lạ.
5.2 Sử dụng thư viện dateutil
from dateutil import tz
from datetime import datetime
# Lấy thời gian hiện tại trong múi giờ cục bộ (với sự xem xét DST)
current_time = datetime.now(tz.tzlocal())
# Chuyển đổi datetime sang múi giờ khác (với sự xem xét DST)
new_tz = tz.gettz('Europe/London')
converted_time = current_time.astimezone(new_tz)
Ưu điểm
- Tính đến các chuyển đổi DST bằng cách sử dụng Cơ sở dữ liệu Múi giờ IANA.
- Giản lược việc xử lý DST mà không cần thư viện bên ngoài.
Nhược điểm
- Thư viện dateutil có thể không hỗ trợ tất cả các trường hợp hiếm gặp hoặc ngoại lệ.
- Hiệu suất có thể chậm hơn so với các thư viện chuyên dụng hơn như pytz.
5.3 Sử dụng mô-đun zoneinfo (Python 3.9+)
from datetime import datetime
from zoneinfo import ZoneInfo
# Lấy thời gian hiện tại trong một múi giờ cụ thể (với sự xem xét DST)
tz = ZoneInfo('America/New_York')
current_time = datetime.now(tz)
# Chuyển đổi datetime sang múi giờ khác (với sự xem xét DST)
new_tz = ZoneInfo('Europe/London')
converted_time = current_time.astimezone(new_tz)
Ưu điểm
- Cung cấp khả năng xử lý DST mà không cần thư viện bên ngoài.
- Sử dụng Cơ sở dữ liệu Múi giờ IANA được công nhận rộng rãi và được cập nhật thường xuyên.
Nhược điểm
- Hạn chế đối với Python 3.9 trở lên.
- Có thể không xử lý các chuyển đổi DST trong lịch sử ở các phiên bản Python cũ hơn.
Kết luận
Làm việc với ngày và giờ trong Python có thể phức tạp, nhưng việc hiểu và giải quyết các vấn đề phổ biến có thể giúp quản lý dễ dàng hơn. Có 4 gói chính mà chúng ta có thể sử dụng để cuộc sống của chúng ta tốt hơn: