2011-11-12 28 views
5

Tôi nghĩ rằng Django tạo ra các cột datetime là thời gian bất khả tri, nhưng khi tôi nhìn vào bảng Postgres của tôi, tôi thấy rằng các giá trị được ghi lại có thông tin múi giờ.Tại sao Django tạo cột dấu thời gian Postgres với múi giờ?

Đi xa hơn tôi thấy rằng phụ trợ Postgres hướng Django để tạo cột sử dụng múi giờ.

Từ django/db/backends/postgresql/creation.py:

data_types = { 
     ... 
     'DateTimeField':  'timestamp with time zone', 
     ... 

Giản đồ cho thấy cột tạo ra được quy định như "timestamp với múi giờ".

CREATE TABLE notification_notice 
(
    ... 
    created timestamp with time zone NOT NULL, 
    ... 

Nhật ký Postgres hiển thị câu lệnh cập nhật đã được gửi. Django đã xây dựng một câu lệnh SQL sử dụng UTC làm múi giờ theo chỉ dẫn của tệp cài đặt Django của tôi.

UPDATE "notification_notice" SET "sender_id" = 1, "group_id" = NULL, "notice_type_id" = 1, "content_type_id" = 21, "object_id" = 3, "created" = E'2011-11-11 22:31:08.022148' WHERE "notification_notice"."id" = 14 

Đây là bảng của tôi. Cột được tạo có một timestame có "-08" cho múi giờ của nó. Postgres phải kiểm tra múi giờ của đồng hồ hệ thống của tôi để tìm múi giờ.

my_db=# select * from notification_notice limit 1; 
id | sender_id | group_id | notice_type_id | content_type_id | object_id |   created   | last_interaction_time 
----+-----------+----------+----------------+-----------------+-----------+------------------------------+----------------------- 
    1 |   |  3 |    21 |    53 |   6 | 2011-11-11 14:31:02.98882-08 | 
(1 row) 

Câu hỏi:
Không Django có một bàn tay ra chính sách để các múi giờ?
Tại sao phụ trợ Postgres sử dụng múi giờ cho mô hình.DateTimeField? Đây có phải là yêu cầu của Postgres không?
Có cách nào để buộc Django tạo cột dấu thời gian trong Postgres không sử dụng múi giờ không?

+0

Câu trả lời có thể có: [tại đây] (http://stackoverflow.com/questions/1869419/django-datetime-field-to-generate-timestamp-fields-without-timezone/1869568#1869568) – unutbu

Trả lời

16

Tin xấu là gốc của vấn đề nằm trong triển khai datetime của Python.

Tin vui là Django có an open ticket về sự cố này.

Tin xấu là các vé được khai trương vào năm 2006.

Các tin tốt là một recent proposal là đọc hữu ích hơn và có vẻ là trong phát triển. Chủ đề chứa đề xuất dài nhưng rất thông tin.

Tin xấu là đề xuất tóm tắt "đây là một mớ hỗn độn thực sự". (Tuy nhiên, nó đang được phát triển.)

Đi xa hơn tôi thấy rằng phụ trợ Postgres hướng Django đến tạo cột sử dụng múi giờ.

Không, đó là quyết định thiết kế của Django. PostgreSQL chỉ lưu trữ UTC; nó không lưu trữ múi giờ, và nó không lưu trữ bù đắp. Múi giờ là khái niệm giống như biến môi trường được áp dụng cho dấu thời gian khi chúng được chèn vào hoặc được chọn để truy xuất.

Từ django developer's mail archive. . .

Trong trường hợp không hỗ trợ múi giờ thực tế trong cơ sở dữ liệu, bất kỳ hành động chụp bởi django sẽ bất tiện ai đó, và có khả năng sẽ không tương thích với mục đích phi django của cơ sở dữ liệu tương tự.

Đó là một vấn đề lớn - một bản sửa lỗi có thể làm cho cơ sở dữ liệu không tương thích với các ngôn ngữ hoặc khung công tác khác. Đó là một cái nút hiển thị tuyệt đối nơi tôi làm việc; nhiều ngôn ngữ lập trình và khung công tác truy cập cơ sở dữ liệu.

SQLite, Microsoft Access và MySQL (kiểu dữ liệu datetime, không dấu thời gian) được trích dẫn trong chuỗi đó vì thiếu hỗ trợ múi giờ trong cơ sở dữ liệu.

+0

Có, tôi hiểu rằng đó là một thiết kế Django descion. Bởi "Postgres phụ trợ", tôi có nghĩa là phụ trợ Postgres của ORM Django. – hekevintran

+0

Nếu múi giờ giống như một biến môi trường, thì điều đó có nghĩa là tôi chỉ phải đặt múi giờ (thành UTC chẳng hạn) trong kết nối cơ sở dữ liệu của tôi? – hekevintran

+2

@hekevintran: Tôi vẫn đang đọc (một lần nữa) những tài liệu tham khảo mà tôi đã đăng. Khi tôi làm việc với múi giờ và nhiều ứng dụng, đột nhiên tên tôi là "Alice", và tôi rơi xuống hố thỏ: Tôi không còn chắc chắn những gì tôi biết và những gì tôi không biết. Tôi sẽ nói, "Không", bởi vì ứng dụng Django của bạn sẽ vẫn phải bình thường hóa mỗi một trong các dấu thời gian của bạn để UTC trước khi lưu trữ chúng. Mỗi người trong số họ, mãi mãi. Tôi cũng sẽ nói, "Không", bởi vì tôi khá chắc chắn có một số điểm tinh tế cho điều này mà tôi đang thiếu. Có lẽ tôi mệt. –

0

Thực tế là Postgresql có khả năng lưu trữ dấu thời gian với múi giờ là một điều tốt. Dấu thời gian được cho là đại diện cho một điểm trong thời gian. Nếu bạn đọc "2013-03-15 14:38:00", có đủ để biết chính xác điểm nào trong thời gian được biểu diễn không? Không! Có thể là 14:38 ở New York hoặc 14:38 ở Berlin, và đây là hai thời điểm khác nhau. Vì vậy, có thực sự không bao giờ nên được dấu thời gian mà không có múi giờ (chúng được gọi là "ngây thơ" datetimes), trừ khi một múi giờ cụ thể được ngụ ý (ví dụ UTC).

Thực tế là Django tạo dấu thời gian với múi giờ do đó, theo điều kiện của tôi là tốt. Bạn có thể ghi đè hành vi mặc định đó theo writing your own DatetimeField, nhưng tôi sẽ không đề xuất nó, trừ khi bạn có lý do rất tốt để loại bỏ múi giờ trong cơ sở dữ liệu (vì nó phá vỡ một số chương trình cũ khác chẳng hạn).

Nếu bạn sử dụng Django < 1.4 thì mã khách hàng postgresql giả định rằng tất cả các khoảng thời gian đều nằm trong múi giờ của hệ thống. Vì vậy, nếu múi giờ máy chủ django của bạn là Berlin, thì "2013-03-15 14:38:00" sẽ được hiểu là 14:38 ở múi giờ Berlin và tất cả thông tin đó sẽ được lưu trữ trong cơ sở dữ liệu. Nếu bạn xóa thông tin múi giờ, thì bạn sẽ gặp sự cố tại số DST thay đổi thời gian. Ví dụ: "2013-10-26 02:30:00" không rõ ràng: đây có phải là lần xuất hiện đầu tiên hoặc thứ hai của 2:30 sáng không? Nếu bạn đi tuyến đường đó, bạn phải chuyển đổi tất cả các datetimes đến/từ UTC trong mã Django của bạn, và lưu trữ dữ liệu UTC trong cơ sở dữ liệu.

Nếu bạn sử dụng Django> = 1,4, thì theo mặc định, đó là nhận biết múi giờ và dự kiến ​​mọi datetime sẽ có múi giờ. Kể từ khi dữ liệu mã vạch không may làm không có múi giờ theo mặc định, bạn nên sử dụng pytz package để đảm bảo rằng mọi datetime bạn thao tác là nhận biết múi giờ.

Django documentation about timezones là một nội dung rất tốt.

1

Tôi nghĩ bạn có giả định không chính xác. PostgreSQL does not store time zone information:

Đối timestamp with time zone, các giá trị được lưu trữ nội bộ luôn ở UTC (Universal Coordinated Time, theo truyền thống được gọi là Greenwich Mean Time, GMT). Giá trị đầu vào có múi giờ rõ ràng được chỉ định được chuyển thành UTC bằng cách sử dụng chênh lệch thích hợp cho múi giờ đó. Nếu không có múi giờ được ghi trong chuỗi đầu vào, thì nó được giả định là trong múi giờ được chỉ ra bởi tham số TimeZone của hệ thống và được chuyển thành UTC bằng cách sử dụng bù đắp cho múi giờ.

Vì vậy, thực tế, thông tin múi giờ bị mất. Nhưng thời gian tức thời của được giữ nguyên.

Có nghĩa là khi bạn nhận được thông tin dấu thời gian, bất kỳ múi giờ nào bạn hoặc máy chủ của bạn hiện tại, sẽ luôn chính xác. Đối với hầu hết các ứng dụng, đây chính xác là những gì bạn muốn.

Các vấn đề liên quan