2011-06-27 27 views
8

Tôi biết có vài chục câu hỏi tương tự trên mạng, chưa kể đến vô số bài viết trên Interwebs nói chung, nhưng tôi vẫn gặp khó khăn khi hiểu Rails hoạt động như thế nào với Time Khu nội bộ.Giúp grokking Time và Time Zones trong Rails 3

Tôi hiện có config.time_zone = 'Eastern Time (US & Canada)' được định cấu hình trong tệp ứng dụng của mình vì đó là nơi tôi và các quản trị viên dự án khác đang sử dụng. Công ty sở hữu trang web có trụ sở tại CA, vì vậy họ sẽ ở Thái Bình Dương. Ứng dụng này có khán giả toàn cầu và trong khi chúng tôi chưa làm như vậy, chúng tôi cuối cùng sẽ triển khai các múi giờ ưa thích của người dùng.

Vì vậy, câu hỏi hiện tại của tôi:

  1. Tôi biết Rails kỳ diệu biến đổi các giá trị cột datetime đến và đi từ UTC khi lưu trữ và lấy ra tương ứng, nhưng cách thích hợp để xem phiên bản địa phương của một thuộc tính datetime nhất định là những gì ?

  2. Khi nào một người sử dụng Time.now so với Time.zone.now so với Time.now.in_time_zone so với DateTime.now so với DateTime.now.in_time_zone?

  3. Cách thích hợp để so sánh thuộc tính datetime đã cho với các phương pháp được liệt kê ở trên hoặc một số thời gian cụ thể khác liên quan đến múi giờ hiện được định cấu hình? Với UTC?

  4. Chúng tôi sẽ có một số thông tin nhạy cảm về thời gian như bài viết cần được xuất bản vào một thời điểm cụ thể theo múi giờ của ứng dụng, vì vậy làm cách nào để ứng dụng thực hiện so sánh đó trong múi giờ đã chỉ định của chúng tôi. một cấu hình (giả sử một người sử dụng các múi giờ được thực hiện?)

  5. (mới Câu hỏi) Điều gì sẽ xảy ra nếu tôi thay đổi config.time_zone-UTC vào một ngày sau? Tôi có phải đặt lại tất cả thời gian của tôi trong cơ sở dữ liệu hay không, nếu không nó ảnh hưởng đến thời gian cũ?

+0

Đây là một câu hỏi hay; Tôi cũng chưa tìm được tài liệu hay về việc triển khai đúng múi giờ. Tôi sẽ thêm hai câu hỏi vào danh sách: '6. Rails có nhạy cảm với Daylight Savings Time hay không và/hoặc làm thế nào để bạn thực hiện hỗ trợ múi giờ nhạy cảm? Và '7. Có một sự khác biệt giữa cách Rails xử lý các múi giờ và DST cho các cột ngày so với các cột datetime? 'Và có lẽ' 8. Cơ sở dữ liệu này là thuyết bất khả tri hay nó cần phải được xử lý khác với SQLite so với MySQL so với những người khác? ' – Clay

+0

@Clay: Bạn có thể tìm thêm bất kỳ thông tin nào về những câu hỏi này không? Tôi vẫn đang tìm kiếm thêm thông tin về chủ đề này. –

+0

Tôi chưa tìm thấy nhiều thông tin tốt. Làm việc với các múi giờ dễ dàng là phần khó chịu nhất và tốn thời gian của ứng dụng sở thích mà tôi đang làm việc. Đã có câu trả lời hay cho câu hỏi này mà tôi đã hỏi: http://stackoverflow.com/questions/8466903/rails-3-1-querying-postgres-for-records-within-a-time-range nhưng nó chỉ phù hợp với postgres. – Clay

Trả lời

8

Trước tiên, điều quan trọng là phải hiểu rằng nội dung múi giờ của phần lớn đường ray là phần lớn về bản trình bày. Đằng sau hậu trường, mọi thứ xảy ra trong UTC.

Q1. Tại bảng điều khiển Rails sẽ hiển thị thời gian trong múi giờ mặc định của bạn, do đó, Something.last.created_at sẽ hiển thị dấu thời gian trong vùng được cung cấp bởi Time.zone

Q2. Tất cả những điều này trả về một đối tượng đại diện cho 'bây giờ'. Sự lựa chọn DateTime so với Time không liên quan đến múi giờ. Nếu bạn cần để có thể đại diện cho thời gian bên ngoài của thời đại unix ví dụ, sử dụng DateTime. Sự khác biệt giữa Time.nowTime.zone.now là liệu bạn có lấy lại một phiên bản Thời gian (sẽ nằm trong múi giờ địa phương của máy chủ làm bộ điều khiển). Điều khiển này ví dụ như những gì to_s trả về nhưng không phải là những gì ngay lập tức được đại diện:

SomeModel.create(:time_attribute => Time.now) 
SomeModel.create(:time_attribute => Time.zone.now) 

sẽ chèn cùng một hàng vào cơ sở dữ liệu. Nếu bạn chỉ hiển thị thời gian cho người dùng (ví dụ: nếu trang web của bạn hiển thị thời gian hiện tại trong tiêu đề) thì bạn nên sử dụng Time.zone.now để nó được hiển thị theo múi giờ chính xác. Nếu bạn chỉ lưu trữ nó trong db thì nó không thực sự quan trọng - activerecord chuyển đổi nó thành một TimeWithZone.

Q3.Các phương pháp so sánh trên TimeWithZone được thực hiện bằng cách so sánh phiên bản utc của ngày, vì vậy bạn có thể so sánh một cách an toàn thời gian ở các vùng khác nhau - bạn không cần phải chuyển đổi chúng thành một số múi giờ chung. Bạn cũng có thể so sánh các cá thể TimeWithZone với các đối tượng thời gian đơn giản.

Q4. Bạn thường không cần làm gì cả. Một cách phổ biến để thực hiện điều này là có thuộc tính published_at trên mô hình của bạn. Các trang hiển thị các bài viết trong danh sách sẽ thêm một điều kiện

where('published_at <= ?', Time.now) 

điều kiện cho truy vấn. Khi bạn tạo bài viết của mình, Rails lấy ngày tháng từ biểu mẫu và chuyển đổi nó thành utc, vì vậy những gì được lưu trữ trong cơ sở dữ liệu là phiên bản utc của thời gian đó published_at. So sánh là độc lập múi giờ, do đó truy vấn chỉ hoạt động bất kể múi giờ là gì. Điều này có thể phức tạp với thời gian trong ngày (ví dụ: '4pm') vì chuyển đổi múi giờ chỉ có thể được thực hiện đúng khi bạn biết ngày đó (tức là bạn biết chính xác thời gian), tùy thuộc vào DST (hoặc các sự kiện chính trị như các quốc gia thay đổi múi giờ của họ) bù đắp từ những thay đổi của UTC. Trong tình huống như thế này, bạn thường muốn lưu trữ thời gian trong ngày và chỉ chuyển đổi nó thành toàn bộ thời gian càng muộn càng tốt, khi bạn biết ngày tháng.

Q5. Rails luôn lưu trữ UTC trong cơ sở dữ liệu. Một hậu quả trực tiếp của việc này là việc thay đổi config.time_zone không yêu cầu bạn thay đổi dữ liệu được lưu trữ trong cơ sở dữ liệu. Bạn thậm chí có thể đặt Time.zone trên cơ sở mỗi người dùng để người dùng xem thời gian trong múi giờ của họ - config.time_zone chỉ kiểm soát giá trị mặc định của Time.zone

+0

Giải thích toàn diện tuyệt vời. Cảm ơn bạn. –

+0

Tôi luôn bối rối về điều đó, câu trả lời của bạn thật tuyệt vời. –