关于ruby on rails:如何在特定时区创建新的DateTime对象(最好是我的应用程序的默认时区,而不是UTC)?

How to create a new DateTime object in a specific time zone (preferably the default time zone of my app, not UTC)?

我在/config/application.rb中设置了时区,我希望应用程序中生成的所有时间默认都在这个时区,但是当我创建一个新的DateTime对象(使用.new)时,它在GMT中创建。我怎样才能让它进入我的应用程序的时区?

/配置/应用.rb

1
config.time_zone = 'Pacific Time (US & Canada)'

IRB

1
2
3
4
5
irb> DateTime.now
=> Wed, 11 Jul 2012 19:04:56 -0700

irb> mydate = DateTime.new(2012, 07, 11, 20, 10, 0)
=> Wed, 11 Jul 2012 20:10:00 +0000                    # GMT, but I want PDT

使用in_time_zone不起作用,因为它只是将格林威治时间转换为pdt时间,这是错误的时间:

1
2
irb> mydate.in_time_zone('Pacific Time (US & Canada)')
=> Wed, 11 Jul 2012 13:10:00 PDT -07:00               # wrong time (I want 20:10)

可以使用ActiveSupport的TimeWithZone(Time.zone对象)在应用程序的时区中创建和分析日期:

1
2
3
4
1.9.3p0 :001 > Time.zone.now
 => Wed, 11 Jul 2012 19:47:03 PDT -07:00
1.9.3p0 :002 > Time.zone.parse('2012-07-11 21:00')
 => Wed, 11 Jul 2012 21:00:00 PDT -07:00


另一种不进行字符串分析的方法:

1
2
irb> Time.zone.local(2012, 7, 11, 21)
=> Wed, 07 Nov 2012 21:00:00 PDT -07:00


如果有,我通常在实例化time.new或datetime.new时指定UTC偏移量。

1
2
3
4
5
6
[1] pry(main)> Time.new(2013,01,06, 11, 25, 00) #no specified utc_offset defaults to system time
 => 2013-01-06 11:25:00 -0500
[2] pry(main)> Time.new(2013,01,06, 11, 25, 00,"+00:00") #UTC
 => 2013-01-06 11:25:00 +0000
[3] pry(main)> Time.new(2013,01,06, 11, 25, 00,"-08:00") #PST
 => 2013-01-06 11:25:00 -0800

这可以在datetime类中通过包括时区来实现。

1
2
3
4
5
6
2.5.1 :001 > require 'rails'
 => true
2.5.1 :002 > mydate = DateTime.new(2012, 07, 11, 20, 10, 0)
 => Wed, 11 Jul 2012 20:10:00 +0000
2.5.1 :003 > mydate = DateTime.new(2012, 07, 11, 20, 10, 0,"PST")
 => Wed, 11 Jul 2012 20:10:00 -0800

https://docs.ruby-lang.org/en/2.6.0/datetime.html

1
2
3
4
2.6.0 :001 > DateTime.new(2012, 07, 11, 20, 10, 0,"-06")
 => Wed, 11 Jul 2012 20:10:00 -0600
2.6.0 :002 > DateTime.new(2012, 07, 11, 20, 10, 0,"-05")
 => Wed, 11 Jul 2012 20:10:00 -0500

我在ApplicationController中执行以下操作,将时区设置为用户的时间。

我不确定这是不是你想要的。

1
2
3
4
5
6
7
8
class ApplicationController < ActionController::Base
  before_filter :set_timezone
  def set_timezone
    # current_user.time_zone #=> 'London'
    Time.zone = current_user.time_zone if current_user && current_user.time_zone
  end

end