2014-09-29 13 views
7

Tôi có tình huống sau đây: - Postgres backend với một lĩnh vựcSQLAlchemy chuyển đổi UTC DateTime để giờ địa phương trước khi lưu

timestamp without time zone 
  • Ngay trước khi lưu giá trị datetime, nó trông giống như: 2014/09/29 06: 00: 00 + 00: 00
  • sau đó tôi tải cùng hàng từ db và giá trị là: 2014-09-29 09:00:00

Vì vậy, trong cơ sở dữ liệu được lưu trữ ngày là không còn 6AM .. nhưng 9AM - nó được chuyển đổi theo múi giờ địa phương của tôi.

Tôi không hiểu điều gì đang xảy ra. Tại sao ngày đã lưu được chuyển đổi thành địa phương?

Cảm ơn.

Sửa

Vì vậy, sau khi trả lời @ univerio của tôi đã cố gắng một cái gì đó: tôi loại bỏ các tzinfo kể từ thời điểm cập nhật bằng cách làm

.replace(tzinfo = None) 

Và bây giờ ngày được lưu một cách chính xác - nó không điều chỉnh nó đến giờ địa phương. Tôi không hiểu tại sao vì vậy tôi sẽ để câu hỏi mở ngay bây giờ trong trường hợp ai đó có một lời giải thích.

Cảm ơn.

+2

Re chỉnh sửa của bạn: có vẻ như một dấu thời gian với thông tin múi giờ sẽ được chuyển đổi sang múi giờ của kết nối khi được lưu trữ dưới dạng 'dấu thời gian không có múi giờ' bởi PostgreSQL. Bằng cách làm cho 'datetime's ngây thơ, bạn đang yêu cầu PostgreSQL lưu dấu thời gian như hiện tại. Đây là một giải pháp ổn nếu bạn ổn với 'datetime' ngây thơ. Cá nhân, tôi nghĩ tốt hơn là tránh những gotchas này bằng cách luôn làm việc với 'datetime's /' timestamp 'và luôn luôn sử dụng UTC. – univerio

Trả lời

17

Điều tôi nghi ngờ đang xảy ra là bạn đang lưu trữ chính xác datetime s, nhưng không đọc lại theo múi giờ vì cột là WITHOUT TIME ZONE. Mỗi kết nối PostgreSQL có một múi giờ liên kết mặc định theo múi giờ của hệ thống, vì vậy khi bạn lấy một số TIMESTAMP cụ thể, nó sẽ được trả lại thành một không gian datetime chưa từng có trong múi giờ của hệ thống. Vì lý do này, tôi luôn khuyên bạn nên lưu trữ TIMESTAMP WITH TIME ZONE thay thế.

Nếu bạn muốn thay đổi múi giờ của các kết nối trong SQLAlchemy để UTC, làm như sau khi bạn tạo động cơ:

engine = create_engine("...", connect_args={"options": "-c timezone=utc"}) 

này nên làm cho bạn đọc giá trị trở lại như một ngây thơ datetime trong UTC .

EDIT: @Peter Tài liệu không rõ ràng cách thực hiện việc này; Tôi đã phải đọc tài liệu khác nhau và kết nối các dấu chấm:

  1. tài liệu SQLAlchemy về connect_args cho phép bạn vượt qua đối số trực tiếp đến DBAPI connect()
  2. tài liệu psycopg2 trên connect, mà nói với bạn về các thông số thêm bạn có thể vượt qua để libpq
  3. tài liệu libpq trên tham số options cho phép bạn vượt qua tùy chọn dòng lệnh khi kết nối với libpq
  4. các tài liệu PostgreSQL về -c Command- chuyển đổi dòng cho phép bạn sửa đổi cài đặt cấu hình
  5. cuối cùng, các tài liệu khách hàng PostgreSQL về các thiết lập timezone khách hàng mà bạn có thể thiết lập
+0

Sau một vài giờ tìm kiếm một cách để kết nối bằng UTC như mặc định, tôi đã tìm thấy giải pháp của bạn. Cảm ơn bạn! Rất hữu dụng. Bạn đã học được điều này ở đâu? Tôi không thể tìm thấy nó trong tài liệu SQLAlchemy. – Peter

+0

@Peter Câu trả lời của tôi quá dài để nhận xét; xem chỉnh sửa trong câu trả lời của tôi. – univerio

+0

Điều này có vẻ là những gì tôi đang tìm kiếm. Tuy nhiên trong dự án của tôi, chúng tôi sử dụng phương pháp engine_from_config để tạo công cụ. Tôi không chắc liệu tôi có thể thêm đối số connect_args vào hàm engine_from_config không? Điều này không được giải thích trực tiếp trong tài liệu. –

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