Chuyển đổi thời gian từ múi giờ này sang múi giờ khác trong Rails


105

created_atDấu thời gian của tôi được lưu trữ trong UTC:

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

Làm cách nào để chuyển đổi một trong số chúng sang 'Giờ miền Đông (Hoa Kỳ & Canada)' (có tính đến tiết kiệm ánh sáng ban ngày)? Cái gì đó như:

Annotation.last.created_at.in_eastern_time

Câu trả lời:


191

Sử dụng phương thức 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, đối với ví dụ cụ thể của bạn

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

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

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

51
"EST" = "Giờ chuẩn miền Đông", vì vậy nó sẽ bị sai trong Giờ tiết kiệm ánh sáng ban ngày. "Giờ miền Đông (Hoa Kỳ và Canada)" xác định xem đó có phải là DST hay không cho bạn.
jhiro009

1
Lưu ý rằng phương thức in_time_zone là một phần của ActiveSupport, do đó nó được tích hợp vào Rails, nhưng không phải là một phần của Ruby stdlib. Nếu bạn có ứng dụng rails, không vấn đề gì. Nếu bạn có một ứng dụng Ruby trực tiếp, bạn sẽ cần đảm bảo yêu cầu hỗ trợ tích cực.
Gayle

Liên kết đến tài liệu cho phương pháp này ở đây: apidock.com/rails/DateTime/in_time_zone
Naved Khan

17

Mặc dù đây là một câu hỏi cũ, nhưng cũng cần nhắc lại một điều. Trong một câu trả lời trước , bạn nên sử dụng before_filter để đặt múi giờ tạm thời.

Bạn không bao giờ nên làm điều đó vì Time.zone lưu trữ thông tin trong chuỗi và nó có thể 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. 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ề điều này ở đây


1
Hiện nay có một phương pháp Time.use_zone rất hay .
freemanoid

9

Nếu bạn thêm cái này vào /config/application.rb

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

Sau đó, bạn có thể tế bào

Annotation.last.created_at.in_time_zone

để có được thời gian trong múi giờ được chỉ định.


nếu chúng ta đang định cấu hình múi giờ trong application.rb thì không cần gọi ".in_time_zone". rails tự động làm điều đó cho chúng tôi, bạn cần gọi Annotation.last.create_at
Vishal

3

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

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

Time.now.in_time_zone

DateTime.now.in_time_zone

2

Đặt múi giờ của bạn thành Giờ miền Đông.

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

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

Bây giờ tất cả các bản ghi bạn kéo ra sẽ nằm trong múi giờ đó. Nếu bạn cần múi giờ khác nhau, giả sử dựa trên múi giờ của người dùng, bạn có thể thay đổi múi giờ bằng 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 rằng bạn đang lưu trữ tất cả thời gian của mình trong cơ sở dữ liệu dưới dạng UTC và mọi thứ sẽ rất tốt.


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


Nó có thể không có trong '09?
nitecoder,

2
@jpwynn: theo cái này: github.com/rails/rails/commit/… thì Thread an toàn hơn 5 năm rồi. Bất kỳ nguồn hoặc ví dụ nào cho Vấn đề của bạn?
Pascal

1
Một chuỗi có thể phân phát nhiều phiên. Bạn đã đặt nó một lần khi người dùng đăng nhập, ví dụ: người dùng CUỐI CÙNG đăng nhập sẽ đặt múi giờ cho TẤT CẢ người dùng có phiên sử dụng cùng một chủ đề đó. Vì vậy, bạn PHẢI sử dụng before_filter để đặt nó cho mọi người dùng cho mỗi lần tải trang.
jpw
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.