如何在Ruby on Rails中更改区域偏移一段时间?

Jan*_*nak 25 ruby ruby-on-rails

我有一个包含时间的变量foo,比如今天下午4点,但是区域偏移是错误的,即它在错误的时区.如何更改时区?

当我打印它时,我得到了

Fri Jun 26 07:00:00 UTC 2009
Run Code Online (Sandbox Code Playgroud)

所以没有偏移,我想将偏移设置为-4或东部标准时间.

我希望能够将偏移量设置为Time对象的属性,但这似乎不可用?

Chr*_*ley 17

你没有明确说明你是如何获得实际变量的,但是因为你提到了Time类所以我假设你有时间使用它,我会在我的回答中提到

时区实际上是Time类的一部分(在您的情况下,时区显示为UTC).Time.now将返回UTC的偏移量,作为Time.now响应的一部分.

>> local = Time.now
=> 2012-08-13 08:36:50 +0000
>> local.hour
=> 8
>> local.min
=> 36
>> 
Run Code Online (Sandbox Code Playgroud)


......在这种情况下,我碰巧与GMT在同一时区

在时区之间转换

我发现最简单的方法是使用'+/- HH:MM'格式将偏移量更改为getlocal方法.让我假装我想在都柏林和纽约时间之间进行转换

?> dublin = Time.now
=> 2012-08-13 08:36:50 +0000
>> new_york = dublin + Time.zone_offset('EST')
=> 2012-08-13 08:36:50 +0000
>> dublin.hour
=> 8
>> new_york.hour
=> 3
Run Code Online (Sandbox Code Playgroud)

假设'EST'是纽约时区的名称,Dan指出有时'EDT'是正确的TZ.


99m*_*les 15

如果给出:

2011-10-25 07:21:35 -700
Run Code Online (Sandbox Code Playgroud)

你要:

2011-10-25 07:21:35 UTC
Run Code Online (Sandbox Code Playgroud)

然后做:

Time.parse(Time.now.strftime('%Y-%m-%d %H:%M:%S UTC')).to_s
Run Code Online (Sandbox Code Playgroud)


Kel*_*vin 14

这利用了Time#asctime不包括区域的事实.

给定时间:

>> time = Time.now
=> 2013-03-13 13:01:48 -0500
Run Code Online (Sandbox Code Playgroud)

强制它到另一个区域(这会返回一个ActiveSupport::TimeWithZone):

>> ActiveSupport::TimeZone['US/Pacific'].parse(time.asctime)
=> Wed, 13 Mar 2013 13:01:48 PDT -07:00
Run Code Online (Sandbox Code Playgroud)

请注意,原始区域将被完全忽略.如果我将原始时间转换为utc,结果将会有所不同:

>> ActiveSupport::TimeZone['US/Pacific'].parse(time.getutc.asctime)
=> Wed, 13 Mar 2013 18:01:48 PDT -07:00
Run Code Online (Sandbox Code Playgroud)

您可以使用to_timeto_datetime在结果上获得相应的TimeDateTime.

这个问题使用一种有趣的方法DateTime#change来设置tz偏移量.(请记住,ActiveSupport可以轻松地在Time和之间进行转换DateTime.)缺点是没有DST检测; 你必须使用TZInfo手动完成current_period.


ALW*_*ALW 11

...

>> Time.at(Time.now.utc + Time.zone_offset('PST'))
=> Mon Jun 07 22:46:22 UTC 2010
>> Time.at(Time.now.utc + Time.zone_offset('PDT'))
=> Mon Jun 07 23:46:26 UTC 2010
>> Time.at(Time.now.utc + Time.zone_offset('CST'))
=> Tue Jun 08 00:46:32 UTC 2010
Run Code Online (Sandbox Code Playgroud)

注意:确保当前时间对象首先设置为UTC时间,否则Ruby将尝试将Time对象转换为您的本地时区,从而抛出计算.在这种情况下,您可以通过在上述语句的末尾应用".utc"来获得调整时间.

  • 这里的问题是返回的值显示UTC而不是您尝试转换为的特定时区. (5认同)

jme*_*ine 10

对于那些在寻找非导轨解决方案时遇到这种情况的人(就像我一样),TZInfo为我解决了这个问题......

require 'tzinfo'
def adjust_time time, time_zone="America/Los_Angeles"
    return TZInfo::Timezone.get(time_zone).utc_to_local(time.utc)
end

puts adjust_time(Time.now) 
#=> PST or PDT
puts adjust_time(Time.now, "America/New_York")
#=> EST or EDT
Run Code Online (Sandbox Code Playgroud)

这也处理DST,这是我需要的,上面没有处理.

见:http://tzinfo.rubyforge.org/

  • 我建议使用`getutc`而不是`utc`,因为后者改变了接收器. (2认同)

Sim*_*tti 5

在你的environment.rb中搜索以下行.

# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names.
config.time_zone = 'UTC'
Run Code Online (Sandbox Code Playgroud)

请记住,ActiveRecord和Rails始终在内部处理时间为UTC.

  • @jcm因为这个问题被标记为`ruby-on-rails`. (29认同)
  • 为什么每个人都认为所有Ruby问题都与Rails有关? (4认同)
  • 它位于rails3中的`application.rb`文件中. (3认同)

Jan*_*nak 2

在他们添加使 weppos 解决方案工作的代码之前,我正在使用 Rails 2.0。这就是我所做的

# Silly hack, because sometimes the input_date is in the wrong timezone
temp = input_date.to_time.to_a
temp[8] = true
temp[9] = "Eastern Daylight Time"
input_date = Time.local(*temp)
Run Code Online (Sandbox Code Playgroud)

我将时间分解为 10 个元素的数组,更改时区,然后将数组转换回时间。