Làm cách nào để nhận được sự khác biệt về số ngày giữa 2 ngày trong SQLite? Tôi đã thử một cái gì đó như thế này:
SELECT Date('now') - DateCreated FROM Payment
Nó trả về 0 mọi lúc.
Làm cách nào để nhận được sự khác biệt về số ngày giữa 2 ngày trong SQLite? Tôi đã thử một cái gì đó như thế này:
SELECT Date('now') - DateCreated FROM Payment
Nó trả về 0 mọi lúc.
Câu trả lời:
SELECT julianday('now') - julianday(DateCreated) FROM Payment;
DateCreated
đang ở UTC. Thay vào đó, nếu đó là giờ địa phương, bạn phải chuyển đổi julianday('now')
sang giờ địa phương. Tôi không thể tìm thấy bất cứ nơi nào có thông tin này. Nếu bạn julianday('now') - julianday(DateCreated)
thích bài đăng này đề xuất với ngày được lưu trữ theo giờ địa phương, câu trả lời của bạn sẽ bị lệch so với thời gian bù giờ so với GMT và sẽ sai. Mặc dù có thể không phải là phương pháp hay nhất để lưu trữ ngày tháng theo giờ địa phương, nhưng nó vẫn có thể xảy ra trong các ứng dụng có múi giờ không quan trọng (ngoại trừ khi công cụ bạn đang làm việc buộc chúng vào bạn, như ở đây).
julianday('now') - julianday(DateCreated, 'utc')
, để tạo cả hai UTC, nó không hoạt động giống như cách làm julianday('now', 'localtime') - julianday(DateCreated)
. Trước đây không tính đến ngày DST và sẽ thêm một giờ vào các ngày đã tạo trong tháng 3-tháng 11. Điều sau thực sự giải thích cho nó. stackoverflow.com/questions/41007455/…
Sự khác biệt trong ngày
Select Cast ((
JulianDay(ToDate) - JulianDay(FromDate)
) As Integer)
Sự khác biệt trong giờ
Select Cast ((
JulianDay(ToDate) - JulianDay(FromDate)
) * 24 As Integer)
Sự khác biệt trong vài phút
Select Cast ((
JulianDay(ToDate) - JulianDay(FromDate)
) * 24 * 60 As Integer)
Sự khác biệt trong vài giây
Select Cast ((
JulianDay(ToDate) - JulianDay(FromDate)
) * 24 * 60 * 60 As Integer)
Cả hai câu trả lời đều cung cấp các giải pháp phức tạp hơn một chút, khi chúng cần phải như vậy. Giả sử thanh toán đã được tạo vào January 6, 2013
. Và chúng tôi muốn biết sự khác biệt giữa ngày này và ngày hôm nay.
sqlite> SELECT julianday() - julianday('2013-01-06');
34.7978485878557
Sự khác biệt là 34 ngày. Chúng tôi có thể sử dụng julianday('now')
để rõ ràng hơn. Nói cách khác, chúng ta không cần đặt
date()
hoặc datetime()
hàm như các tham số để julianday()
hoạt động.
Tài liệu SQLite là một tài liệu tham khảo tuyệt vời và trang DateAndTimeFunctions là một trang tốt để đánh dấu.
Cũng hữu ích khi nhớ rằng khá dễ dàng để thực hiện các truy vấn bằng tiện ích dòng lệnh sqlite:
sqlite> select julianday(datetime('now'));
2454788.09219907
sqlite> select datetime(julianday(datetime('now')));
2008-11-17 14:13:55
Câu trả lời này hơi dài dòng và tài liệu sẽ không cho bạn biết điều này (vì họ cho rằng bạn đang lưu trữ ngày của mình dưới dạng ngày UTC trong cơ sở dữ liệu), nhưng câu trả lời cho câu hỏi này phụ thuộc phần lớn vào múi giờ mà ngày của bạn được lưu trữ trong. Bạn cũng không sử dụng Date('now')
, nhưng sử dụng julianday()
hàm, để tính toán cả hai ngày ngược lại với một ngày chung, sau đó trừ chênh lệch của các kết quả đó cho nhau.
Nếu ngày của bạn được lưu trữ theo giờ UTC:
SELECT julianday('now') - julianday(DateCreated) FROM Payment;
Đây là câu trả lời được xếp hạng hàng đầu và cũng có trong tài liệu . Nó chỉ là một phần của bức tranh, và một câu trả lời rất đơn giản, nếu bạn hỏi tôi.
Nếu ngày của bạn được lưu theo giờ địa phương, việc sử dụng mã trên sẽ khiến câu trả lời của bạn SAI theo số giờ bù giờ GMT của bạn. Nếu bạn ở miền Đông Hoa Kỳ như tôi, giờ là GMT -5, kết quả của bạn sẽ có thêm 5 giờ nữa. Và nếu bạn cố gắng DateCreated
tuân theo UTC vì julianday('now')
đi ngược lại ngày GMT:
SELECT julianday('now') - julianday(DateCreated, 'utc') FROM Payment;
Điều này có một lỗi trong đó nó sẽ thêm một giờ cho một giờ DateCreated
trong Giờ tiết kiệm ánh sáng ban ngày (tháng 3 đến tháng 11). Giả sử "bây giờ" là vào buổi trưa của một ngày không phải DST và bạn đã tạo thứ gì đó hồi tháng 6 (trong DST) vào buổi trưa, kết quả của bạn sẽ cách nhau 1 giờ, thay vì 0 giờ, cho phần giờ. Bạn phải viết một hàm trong mã ứng dụng của bạn đang hiển thị kết quả để sửa đổi kết quả và trừ đi một giờ cho các ngày DST. Tôi đã làm điều đó, cho đến khi tôi nhận ra có một giải pháp tốt hơn cho vấn đề mà tôi đang gặp phải: SQLite so với Oracle - Tính toán chênh lệch ngày - giờ
Thay vào đó, như tôi đã chỉ ra, đối với các ngày được lưu trữ theo giờ địa phương, hãy làm cho cả hai khớp với giờ địa phương:
SELECT julianday('now', 'localtime') - julianday(DateCreated) FROM Payment;
Hoặc thêm 'Z'
vào giờ địa phương:
julianday(datetime('now', 'localtime')||'Z') - julianday(CREATED_DATE||'Z')
Cả hai điều này dường như bù trừ và không cộng thêm giờ cho các ngày DST và thực hiện phép trừ thẳng - do đó, mục đó được tạo vào buổi trưa của ngày DST, khi kiểm tra vào buổi trưa của ngày không phải DST, sẽ không nhận được thêm một giờ khi thực hiện phép tính.
Và mặc dù tôi nhận ra hầu hết sẽ nói rằng không lưu trữ ngày tháng theo giờ địa phương trong cơ sở dữ liệu của bạn và lưu trữ chúng theo giờ UTC để bạn không gặp phải vấn đề này, nhưng không phải mọi ứng dụng đều có đối tượng trên toàn thế giới và không phải lập trình viên nào cũng muốn để chuyển đổi MỖI ngày trong hệ thống của họ sang UTC và quay lại mỗi lần họ thực hiện GET hoặc SET trong cơ sở dữ liệu và xử lý xem có thứ gì đó là cục bộ hay ở UTC hay không.
Chỉ là một lưu ý để viết các chức năng đồng hồ thời gian. Đối với những người đang tìm kiếm giờ làm việc, một sự thay đổi rất đơn giản là số giờ cộng với số phút được hiển thị theo tỷ lệ 60 như hầu hết các công ty trả lương muốn.
CAST ((julianday(clockOUT) - julianday(clockIN)) * 24 AS REAL) AS HoursWorked
Clock In Clock Out HoursWorked
2016-08-07 11:56 2016-08-07 18:46 6.83333332836628
Nếu bạn muốn thời gian ở định dạng 00:00: Tôi đã giải quyết nó như vậy:
select strftime('%H:%M',CAST ((julianday(FinishTime) - julianday(StartTime)) AS REAL),'12:00') from something
Giả sử rằng định dạng ngày của bạn như sau: "YYYY-MM-DD HH: MM: SS", nếu bạn cần tìm sự khác biệt giữa hai ngày theo số tháng:
(strftime('%m', date1) + 12*strftime('%Y', date1)) -
(strftime('%m', date2) + 12*strftime('%Y', date2))
Thứ nhất, không rõ định dạng ngày tháng của bạn là gì. Đã có một câu trả lời liên quan strftime("%s")
.
Tôi muốn mở rộng câu trả lời đó.
SQLite chỉ có các lớp lưu trữ sau: NULL, INTEGER, REAL, TEXT hoặc BLOB. Để đơn giản hóa mọi thứ, tôi sẽ giả sử ngày tháng là THỰC có chứa giây kể từ 1970-01-01. Đây là lược đồ mẫu mà tôi sẽ đưa vào dữ liệu mẫu của "ngày 1 tháng 12 năm 2018":
CREATE TABLE Payment (DateCreated REAL);
INSERT INTO Payment VALUES (strftime("%s", "2018-12-01"));
Bây giờ chúng ta hãy tìm ra sự khác biệt về ngày giữa "ngày 1 tháng 12 năm 2018" và bây giờ (khi tôi viết điều này, đó là giữa ngày 12 tháng 12 năm 2018):
Ngày chênh lệch trong ngày:
SELECT (strftime("%s", "now") - DateCreated) / 86400.0 FROM Payment;
-- Output: 11.066875
Ngày chênh lệch theo giờ:
SELECT (strftime("%s", "now") - DateCreated) / 3600.0 FROM Payment;
-- Output: 265.606388888889
Ngày chênh lệch tính bằng phút:
SELECT (strftime("%s", "now") - DateCreated) / 60.0 FROM Payment;
-- Output: 15936.4833333333
Chênh lệch ngày tính bằng giây:
SELECT (strftime("%s", "now") - DateCreated) FROM Payment;
-- Output: 956195.0
Nếu bạn muốn có hồ sơ giữa các ngày,
select count(col_Name) from dataset where cast(julianday("now")- julianday(_Last_updated) as int)<=0;
Trong trường hợp của tôi, tôi phải tính toán sự khác biệt theo phút và julianday()
không đưa ra giá trị chính xác. Thay vào đó, tôi sử dụng strftime()
:
SELECT (strftime('%s', [UserEnd]) - strftime('%s', [UserStart])) / 60
Cả hai ngày đều được chuyển đổi thành đơn thời gian (giây), sau đó được trừ đi để nhận giá trị tính bằng giây giữa hai ngày. Tiếp theo, chia nó cho 60.