2009-09-06 34 views
90

created_at timestamps của tôi được lưu trữ trong UTC:Chuyển đổi Thời gian từ một múi giờ khác trong Rails

>> Annotation.last.created_at 
=> Sat, 29 Aug 2009 23:30:09 UTC +00:00 

Làm thế nào để chuyển đổi một trong số họ để 'Eastern Time (Mỹ & Canada)' (có tính đến ánh sáng ban ngày tài khoản tiết kiệm)? Một cái gì đó như:

Annotation.last.created_at.in_eastern_time 

Trả lời

159

Sử dụng phương pháp in_time_zone của lớp DateTime

Loading development environment (Rails 2.3.2) 
>> now = DateTime.now.utc 
=> Sun, 06 Sep 2009 22:27:45 +0000 
>> now.in_time_zone('Eastern Time (US & Canada)') 
=> Sun, 06 Sep 2009 18:27:45 EDT -04:00 
>> quit 

Vì vậy, ví dụ cụ thể của bạn

Annotation.last.created_at.in_time_zone('Eastern Time (US & Canada)') 
+6

hoặc bạn chỉ có thể sử dụng giờ ident 'now.in_time_zone (3) ' – fl00r

+7

' created_at.in_time_zone ("EST") 'ngắn hơn – Orlando

+40

" EST "=" Giờ chuẩn miền Đông ", do đó, nó sẽ sai trong Thời gian tiết kiệm ánh sáng ban ngày. "Giờ Miền Đông (Hoa Kỳ và Canada)" cho biết đó là DST hay không cho bạn. – jhiro009

2

Đặt múi giờ của bạn để Eastern Time.

Bạn có thể đặt múi giờ mặc định của bạn trong config/environment.rb

config.time_zone = "Eastern Time (US & Canada)" 

Bây giờ tất cả hồ sơ bạn kéo ra sẽ nằm trong múi giờ đó. Nếu bạn cần múi giờ khác nhau, hãy nói dựa trên múi giờ của người dùng, bạn có thể thay đổi múi giờ đó bằng một before_filter trong bộ điều khiển của mình.

class ApplicationController < ActionController::Base 

    before_filter :set_timezone 

    def set_timezone 
    Time.zone = current_user.time_zone 
    end 
end 

Chỉ cần đảm bảo bạn lưu trữ tất cả thời gian trong cơ sở dữ liệu dưới dạng UTC và mọi thứ sẽ trở nên ngọt ngào.

+2

Tôi sẽ tránh 'Time.zone = ..'vì nó không phải là chủ đề an toàn. – gertas

+0

Điều này có quan trọng không nếu bạn đang chạy một máy chủ ứng dụng như mongrel, mỏng hoặc hành khách? Họ chạy nhiều hơn một ví dụ, đơn luồng tôi tin? Tôi có thể sai, rất muốn biết! – nitecoder

+4

'Time.zone =' là an toàn chủ đề https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/time/zones.rb#L36-38. – lest

8

Nếu bạn thêm này để bạn /config/application.rb

config.time_zone = 'Eastern Time (US & Canada)' 

Sau đó, bạn có thể di

Annotation.last.created_at.in_time_zone 

để có được thời gian theo múi giờ quy định.

14

Mặc dù đây là một câu hỏi cũ, nhưng đáng nói đến điều gì đó. Trong một previous reply, bạn nên sử dụng before_filter để đặt múi giờ tạm thời.

Bạn nên không bao giờ, bao giờ làm điều đó vì Time.zone lưu trữ thông tin trong chuỗi và có thể sẽ bị rò rỉ cho yêu cầu tiếp theo được xử lý bởi chuỗi đó.

Thay vào đó, bạn nên sử dụng around_filter để đảm bảo rằng Time.zone được đặt lại sau khi yêu cầu hoàn tất. Một cái gì đó như:

around_filter :set_time_zone 

private 

def set_time_zone 
    old_time_zone = Time.zone 
    Time.zone = current_user.time_zone if logged_in? 
    yield 
ensure 
    Time.zone = old_time_zone 
end 

Đọc thêm về vấn đề này here

+0

Có một phương pháp [Time.use_zone] (https://apidock.com/rails/Time/use_zone/class) tốt đẹp hiện nay. – freemanoid

2

Nếu bạn cấu hình của bạn /config/application.rb

config.time_zone = 'Eastern Time (US & Canada)' 

Time.now.in_time_zone 

DateTime.now.in_time_zone 
Các vấn đề liên quan