CodeGym /Các khóa học /SQL SELF /Những lỗi thường gặp khi làm việc với ngày và thời gian

Những lỗi thường gặp khi làm việc với ngày và thời gian

SQL SELF
Mức độ , Bài học
Có sẵn

Hôm nay tụi mình lại nói về lỗi nữa. Bởi vì làm việc với ngày giờ giống như đi trên bãi mìn vậy: mọi thứ đều ổn cho đến khi bạn bước nhầm một phát.

Lỗi khi chọn kiểu dữ liệu

Đây thường là nguồn gốc của mọi rắc rối. Chọn sai kiểu dữ liệu có thể làm công sức xử lý ngày giờ của bạn đổ sông đổ biển.

Tình huống 1: Dùng DATE thay vì TIMESTAMP

Khi bạn lưu lại một sự kiện mà có cả ngày lẫn giờ, chỉ dùng DATE thôi thì sẽ mất thông tin quan trọng.

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    order_date DATE -- chỉ có ngày thôi
);

Thiết kế như này thì bạn sẽ không biết được hai đơn hàng đặt vào buổi sáng hay buổi tối. Tại sao lại bỏ lỡ cơ hội vừa uống cà phê vừa ngắm timestamp đẹp nhỉ?

Tình huống 2: Quên mất múi giờ

Nếu app của bạn phục vụ người dùng quốc tế, mà bạn chỉ lưu ngày giờ bằng TIMESTAMP mà không quan tâm đến múi giờ, thì dữ liệu của bạn sẽ thành kiểu "vô gia cư". TIMESTAMPTZ sẽ giải quyết vụ này cho bạn.

CREATE TABLE events (
    event_time TIMESTAMP -- không có múi giờ
);

Không ai muốn nhầm event buổi tối ở New York thành buổi sáng ở Tokyo đâu. Dùng TIMESTAMPTZ đi nhé!

Lỗi khi dùng function

Tình huống 1: Định dạng sai trong TO_CHAR()

Rắc rối bắt đầu nếu bạn chỉ định sai định dạng. Ví dụ:

SELECT TO_CHAR(NOW(), 'YYYY-DD-MM'); -- Ôi, nhầm tháng với ngày rồi

Ở đây thay vì năm-tháng-ngày quen thuộc, bạn lại ra năm-ngày-tháng. Điều này có thể dẫn đến những tình huống hài hước (nhưng không phải lúc nào cũng vui) cho user của bạn. Luôn kiểm tra lại định dạng nhé.

Tình huống 2: Lỗi khi dùng TO_DATE()

Ngược lại, nếu bạn cố chuyển string thành ngày mà định dạng không khớp, PostgreSQL sẽ báo lỗi.

SELECT TO_DATE('10/31/2023', 'YYYY-MM-DD'); -- Lỗi! Định dạng không khớp.

Định dạng của string phải khớp hoàn toàn với cái bạn chỉ định. Ví dụ:

SELECT TO_DATE('2023-10-31', 'YYYY-MM-DD'); -- Chuẩn luôn.

Lỗi với khoảng thời gian (interval)

Tình huống 1: Ép kiểu ngầm không rõ ràng

Đôi khi bạn quên mất đặc điểm của việc ép kiểu. Ví dụ:

SELECT NOW() + '1'; -- LỖI! Không rõ '1' là gì.

PostgreSQL không hiểu bạn muốn cộng thêm một ngày. Cách đúng là:

SELECT NOW() + INTERVAL '1 day';

Tình huống 2: Lẫn lộn khi trừ interval

Cẩn thận khi cộng hoặc trừ interval nhé:

SELECT NOW() - INTERVAL '-1 day'; -- Cái này lại cộng thêm một ngày thay vì trừ!

Ở đây hai dấu trừ tạo ra hiệu ứng ngược lại. Tốt nhất là tránh kiểu này.

Lỗi khi làm tròn và cắt dữ liệu

Tình huống 1: Cắt sai với DATE_TRUNC()

Khi dùng DATE_TRUNC() để group dữ liệu, luôn kiểm tra xem bạn đã chọn đúng mức chưa. Ví dụ:

SELECT DATE_TRUNC('hour', NOW()); -- Cắt về đầu giờ
SELECT DATE_TRUNC('minute', NOW()); -- Cắt về đầu phút

Nếu bạn mong đợi một kết quả mà lại ra cái khác, có thể bạn đã chọn sai mức rồi.

Tình huống 2: Quên múi giờ với DATE_TRUNC()

Nếu bạn làm việc với thời gian ở nhiều múi giờ khác nhau, kết quả có thể bất ngờ lắm:

SELECT DATE_TRUNC('day', NOW() AT TIME ZONE 'UTC');

Hãy chắc chắn bạn chỉ định đúng múi giờ, không là lạc trôi trong thời gian luôn đó (theo nghĩa đen).

Unix-time: những giây bị mất

Unix-time (EPOCH) — tiện thật nhưng cũng tricky lắm. Lỗi phổ biến nhất là nhầm giữa giây và mili giây.

SELECT TO_TIMESTAMP(1680000000); -- Đúng rồi (giây).
SELECT TO_TIMESTAMP(1680000000000); -- Sai nhé! Nhiều số 0 quá.

Kiểm tra kỹ đơn vị timestamp của bạn, kẻo lại lưu thừa cả triệu giây.

Lỗi với múi giờ

Tình huống 1: Múi giờ rối rắm

Khi bạn làm việc với user ở nhiều múi giờ khác nhau, dữ liệu có thể bị lẫn lộn. Ví dụ:

SELECT TIMESTAMP '2023-10-01 10:00:00' AT TIME ZONE 'UTC';

Hãy chắc chắn bạn hiểu rõ dữ liệu của mình đang ở múi giờ nào nhé.

Tình huống 2: Nhân đôi múi giờ

Lưu ngày giờ rồi lại cố gắng xử lý múi giờ lần nữa — không nên đâu:

SELECT TIMESTAMP '2023-10-01 10:00:00 UTC' AT TIME ZONE 'UTC'; -- Đừng làm vậy!

Cái này dễ dẫn đến tính toán sai lắm.

Khuyến nghị để tránh lỗi

Chọn đúng kiểu dữ liệu. Nếu bạn làm việc với dữ liệu thời gian quốc tế, hãy dùng TIMESTAMPTZ. Nếu chỉ cần ngày thôi thì DATE là đủ.

Test query của bạn. Đảm bảo kết quả đúng như mong đợi, nhất là khi làm với interval, định dạng hoặc làm tròn.

Lưu dữ liệu thời gian theo UTC. Đây là cách tốt nhất để tránh rối múi giờ.

Kiểm tra định dạng. Đảm bảo định dạng trong TO_CHAR()TO_DATE() khớp với dữ liệu của bạn.

Dùng function cẩn thận. Đọc kỹ docs PostgreSQL về function thời gian để tránh bất ngờ không mong muốn.

Làm việc với dữ liệu thời gian không phải lúc nào cũng dễ, nhưng nếu chú ý và làm đúng cách thì mọi thứ sẽ mượt mà thôi. Ngày giờ là phần quan trọng của app, quên nó nguy hiểm như quên đặt báo thức sáng thứ hai vậy đó!

2
Nhiệm vụ
SQL SELF, mức độ, bài học
Đã khóa
Làm việc với khoảng thời gian
Làm việc với khoảng thời gian
1
Khảo sát/đố vui
, cấp độ , bài học
Không có sẵn
Làm việc với múi giờ
Làm việc với múi giờ
Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION