1 điểm bởi GN⁺ 2025-04-14 | Chưa có bình luận nào. | Chia sẻ qua WhatsApp
  • Whenever là thư viện ngày giờ cho Python, ngăn việc trộn naive/aware và các lỗi tính toán DST trong datetime bằng hệ thống kiểu, đồng thời có thể dùng dưới dạng triển khai Rust hoặc triển khai thuần Python
  • Thư viện chuẩn datetime không phải lúc nào cũng phản ánh DST, và bài viết đưa ra ví dụ datetime(2023, 3, 25, 22, tzinfo=ZoneInfo("Europe/Paris")) + timedelta(hours=8) trả về 6 giờ thay vì 7 giờ dù một giờ đã bị bỏ qua do DST
  • Hệ thống kiểu không thể phân biệt naive và aware chỉ với một datetime, nhưng Whenever tách ra các kiểu theo từng mục đích sử dụng như Instant, ZonedDateTime, PlainDateTime để trình kiểm tra kiểu có thể phát hiện lỗi
  • Trong bảng so sánh, Arrow và Pendulum không đồng thời đáp ứng được tính an toàn với DST, phân biệt aware/naive bằng kiểu, và hiệu năng; còn Whenever được giới thiệu là hỗ trợ đầy đủ DST-safe, typed aware/naive và fast
  • Vẫn còn trước phiên bản 1.0, nên API có thể thay đổi ở các bản phát hành minor; các thay đổi được mô tả trong changelog, và trình kiểm tra kiểu hoặc IDE có thể hỗ trợ điều chỉnh

Vấn đề Whenever muốn giải quyết

  • Whenever là thư viện giúp viết mã ngày giờ đúng đắn và có thể kiểm tra kiểu trong Python
  • Thư viện cung cấp triển khai Rust, đồng thời cũng có phiên bản thuần Python cho người dùng không muốn dùng Rust
  • Được thiết kế dựa trên các khái niệm đã được kiểm chứng từ thư viện ngày giờ của các ngôn ngữ hiện đại khác
  • Được giới thiệu là nhanh hơn rất nhiều so với các thư viện bên thứ ba khác, và thường còn nhanh hơn cả thư viện chuẩn
  • Bản phát hành 1.0 đang được hoãn lại để tiếp tục tinh chỉnh API dài hạn, đặc biệt nhóm phát triển đang thu thập phản hồi về duration

Giới hạn của thư viện chuẩn datetime

  • datetime của Python đã phát triển hơn 20 năm và có những điểm không còn phù hợp với kỳ vọng dành cho thư viện ngày giờ hiện đại
  • Vấn đề tính toán DST

    • datetime không phải lúc nào cũng tính đến Daylight Saving Time (DST)
    • Trong ví dụ mã, khi cộng 8 giờ vào thời điểm 22 giờ ngày 25/03/2023 ở múi giờ Europe/Paris, kết quả đúng ra phải là 7 giờ vì DST đã làm mất một giờ, nhưng thư viện lại trả về 6 giờ
    • Đây không phải lỗi mà là quyết định thiết kế: chỉ tính đến DST trong các phép tính có liên quan tới hai múi giờ
  • Vấn đề phân biệt kiểu naive/aware

    • Chỉ với một kiểu datetime, hệ thống kiểu không thể phân biệt naive datetimeaware datetime
    • Một chữ ký hàm như def schedule_meeting(at: datetime) -> None: ... không cho biết nó mong đợi naive hay aware

So sánh với Arrow và Pendulum

  • Theo bảng so sánh, Whenever đáp ứng đầy đủ DST-safe, typed aware/naive và fast
  • datetime chỉ đáp ứng tiêu chí fast, còn DST-safe và typed aware/naive thì không
  • Arrow cố cung cấp API thân thiện hơn thư viện chuẩn, nhưng không giải quyết được vấn đề cốt lõi
    • Vẫn giữ nguyên những “footgun” tương tự
    • Quyết định gom mọi thứ vào một kiểu arrow.Arrow khiến trình kiểm tra kiểu càng khó phát hiện lỗi hơn
  • Pendulum từng quảng bá khả năng xử lý DST tốt hơn và cải thiện hiệu năng vào năm 2016, nhưng chỉ sửa được một phần các bẫy liên quan đến DST
    • Hiệu năng đã suy giảm đáng kể theo thời gian
    • Trong 4 năm gần đây chỉ có 2 bản phát hành, cho thấy giai đoạn trì trệ bảo trì kéo dài, và còn nhiều issue nghiêm trọng, tồn đọng lâu năm

Tính năng chính

  • Hỗ trợ DST-safe arithmetic
  • API an toàn về kiểu để ngăn các lỗi phổ biến
  • Khắc phục những vấn đề mà Arrow và Pendulum chưa sửa được
  • Dựa trên các khái niệm đã được kiểm chứng và quen thuộc
  • Cung cấp hiệu năng cao
  • Có kiểm thử và tài liệu đầy đủ
  • Hỗ trợ số học ngày tháng
  • Hỗ trợ độ chính xác nano giây
  • Cung cấp hỗ trợ SQLAlchemy
  • Hỗ trợ Pydantic đang ở trạng thái beta
  • Cung cấp triển khai Rust và tùy chọn thuần Python
  • Hỗ trợ free-threading đang ở trạng thái beta
  • Hỗ trợ per-interpreter GIL

Luồng ví dụ sử dụng

  • Import các kiểu tường minh như Instant, ZonedDateTime, PlainDateTime để biểu đạt các trường hợp sử dụng khác nhau
  • Instant.now() xác định một thời điểm cụ thể mà không cần xử lý độ phức tạp của múi giờ hay lịch
  • Chuyển đổi múi giờ một cách tường minh như now.to_tz("Europe/Paris")
  • PlainDateTime("2023-10-28 22:00") sẽ không vô tình bị trộn với các kiểu khác
    • Khi gọi add(hours=6), nó phát ra NaiveArithmeticWarning để cảnh báo rằng việc điều chỉnh giờ địa phương đang bỏ qua DST
    • Cần giả định múi giờ một cách tường minh bằng assume_tz("Europe/Amsterdam")
  • Khi thực hiện add(hours=6) trên ZonedDateTime, kết quả sẽ phản ánh quá trình chuyển DST và trả về 2023-10-29 03:00:00+01:00[Europe/Amsterdam]
  • Hỗ trợ so sánh, làm tròn và cắt bớt, phân tích định dạng ISO8601·RFC3339·RFC2822, và định dạng theo mẫu tùy chỉnh
  • Khi cần, có thể chuyển đổi sang thư viện chuẩn datetime hoặc chuyển ngược lại
  • Cách dùng chi tiết có thể xem tại feature overviewAPI reference

Giới hạn và chính sách ổn định

  • Phạm vi hỗ trợ là lịch Gregory kéo dài từ năm 1 đến năm 9999
  • Độ lệch múi giờ bị giới hạn ở số nguyên theo giây, nhất quán với IANA TZ DB
  • Whenever tuân theo semantic versioning
  • Trước phiên bản 1.0, API có thể thay đổi trong các bản phát hành minor
  • Các breaking change được mô tả chi tiết trong changelog
  • API được type đầy đủ, nên trình kiểm tra kiểu hoặc IDE có thể hỗ trợ thích ứng với thay đổi API

Giấy phép và ảnh hưởng thiết kế

  • Whenever được phát hành theo MIT License
  • Binary wheel bao gồm các phụ thuộc Rust với giấy phép tương tự, dễ dãi như MIT, Apache-2.0, v.v.
  • Noda TimeJoda Time là những thư viện tiên phong với cách tiếp cận phân tách kiểu theo khái niệm, và hệ phân cấp kiểu của Noda Time là nguồn cảm hứng trực tiếp cho thiết kế của Whenever
  • Temporal truyền cảm hứng cho cách xử lý các trường hợp phức tạp quanh tính mơ hồ của DST và việc làm tròn
  • Mô-đun datetime của Python được dùng rộng rãi cho xử lý ngày giờ mức thấp trong triển khai thuần Python của Whenever
  • Một số ý tưởng cũng được mượn từ Jiff
  • Biểu đồ benchmark so sánh được phỏng theo từ dự án Ruff

Chưa có bình luận nào.

Chưa có bình luận nào.