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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1048937/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 21:23:51  来源:igfitidea点击:

How do I change the zone offset for a time in Ruby on Rails?

ruby-on-railsruby

提问by Janak

I have a variable foo that contains a time, lets say 4pm today, but the zone offset is wrong, i.e. it is in the wrong time zone. How do I change the time zone?

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

When I print it I get

当我打印它时,我得到

Fri Jun 26 07:00:00 UTC 2009

So there is no offset, and I would like to set the offset to -4 or Eastern Standard Time.

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

I would expect to be able to just set the offset as a property of the Time object, but that doesn't seem to be available?

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

采纳答案by Janak

I'm using Rails 2.0 before they added the code that makes weppos solution work. Here's what I did

在他们添加使 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)

I break the time down into a 10 element array, change the timezone and then convert the array back into a time.

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

回答by Chris McCauley

You don't explicitly say how you get the actual variable but since you mention the Time class so I'll assume you got the time using that and I'll refer to that in my answer

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

The timezone is actually part of the Time class (in your case the timezone is shown as UTC). Time.now will return the offset from UTC as part of the Time.now response.

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

>> local = Time.now
=> 2012-08-13 08:36:50 +0000
>> local.hour
=> 8
>> local.min
=> 36
>> 


... in this case I happen to be in the same timezone as GMT


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

Converting between timezones

时区之间的转换

The easiest way that I've found is to change the offset using '+/-HH:MM' format to the getlocal method. Let's pretend I want to convert between the time in Dublin and the time in New York

我发现的最简单的方法是使用 '+/-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

Assuming that 'EST' is the name of the Timezone for New York, as Dan points out sometimes 'EDT' is the correct TZ.

假设“EST”是纽约时区的名称,正如丹指出的那样,有时“EDT”是正确的 TZ。

回答by 99miles

If given:

如果给出:

2011-10-25 07:21:35 -700

you want:

你要:

2011-10-25 07:21:35 UTC

then do:

然后做:

Time.parse(Time.now.strftime('%Y-%m-%d %H:%M:%S UTC')).to_s

回答by Kelvin

This takes advantage of the fact that Time#asctimedoesn't include the zone.

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

Given a time:

给定时间:

>> time = Time.now
=> 2013-03-13 13:01:48 -0500

Force it to another zone (this returns an ActiveSupport::TimeWithZone):

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

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

Note that the original zone is ignored completely. If I convert the original time to utc, the result will be different:

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

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

You can use to_timeor to_datetimeon the result to get a corresponding Timeor DateTime.

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

This questionuses an interesting approach with DateTime#changeto set the tz offset. (Remember that ActiveSupport makes it easy to convert between Timeand DateTime.) The downside is that there's no DST detection; you have to do that manually by using TZInfo's current_period.

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

回答by ALW

...

...

>> 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

One note: make sure that the current time object is set to UTC time first, otherwise Ruby will try and convert the Time object to your local timezone, thus throwing the calculation. You can always get the adjusted time by applying ".utc" to the end of the above statements in that case.

一个注意事项:确保首先将当前时间对象设置为 UTC 时间,否则 Ruby 会尝试将 Time 对象转换为您的本地时区,从而引发计算。在这种情况下,您始终可以通过在上述语句的末尾应用“.utc”来获得调整后的时间。

回答by jmervine

For those that came across this while looking for a non-rails solution (as I did), TZInfo solved it for me...

对于那些在寻找非 Rails 解决方案时遇到这个问题的人(就像我一样),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

This also handles DST, which is what I needed that wasn't handled above.

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

See: http://tzinfo.rubyforge.org/

请参阅:http: //tzinfo.rubyforge.org/

回答by Simone Carletti

in you environment.rb search for the following line.

在您的 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'

Keep in mind ActiveRecord and Rails always handle Time as UTC internally.

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

回答by Janak

Here is what worked for me...

这是对我有用的...

def convert_zones(to_zone)
   to_zone_time = to_zone.localtime
end


# have your time set as time

time = convert_zones(time)
time.strftime("%b #{day}, %Y (%a) #{hour}:%M %p %Z")

回答by Chris Kimpton

This is what I did, as I am not using Rails and don't want to use any non-core gems.

这就是我所做的,因为我没有使用 Rails,也不想使用任何非核心 gem。

t = Time.now # my local time - which is GMT
zone_offset = 3600 # offset for CET - which is my target time zone
zone_offset += 3600 if t.dst? # an extra hour offset in summer
time_cet = Time.mktime(t.sec, t.min, t.hour, t.mday, t.mon, t.year, nil, nil, t.dst?, zone_offset)

回答by ryan0

It's probably a good idea to store the time as UTC and then show it in a specific time zone when it is displayed. Here's an easy way to do that (works in Rails 4, unsure about earlier versions).

将时间存储为 UTC,然后在显示时以特定时区显示它可能是一个好主意。这是一个简单的方法来做到这一点(适用于 Rails 4,不确定早期版本)。

t = Time.now.utc

=> 2016-04-19 20:18:33 UTC

t.in_time_zone("EST")

=> Tue, 19 Apr 2016 15:18:33 EST -05:00

But if you really want to store it in a specific timezone, you can just set the initial Time object to itself.in_time_zone like this:

但是如果你真的想把它存储在一个特定的时区,你可以像这样将初始 Time 对象设置为 self.in_time_zone :

t = t.in_time_zone("EST")