【问题标题】:Change Time zone in pure ruby (not rails)在纯红宝石(不是铁轨)中更改时区
【发布时间】:2014-10-08 16:55:40
【问题描述】:

我正在构建一个具有混合 UTC/PST 数据源的 Sinatra 站点,但将在 PST 中查看。所以我需要一种方法来轻松地将时间对象从 UTC 转换为 PST。 如果没有 Rails,我将无法访问 Time.zonein_time_zone 等。

我只需要更改 Time 对象的时区,例如2014-08-14 21:44:17 +0000 => 2014-08-14 14:44:17 -0700.

首先我尝试了这个:

class Time
  def to_pst
    self.utc + Time.zone_offset('PDT')
  end
end

但这会改变实际的时间戳,而不是区域。我需要time.to_itime.strftime 才能工作;所以我不能改变时间戳的绝对值。

> t = Time.now
=> 2014-08-14 21:46:20 +0000
> t.to_pst
=> 2014-08-14 14:46:20 UTC
> t.to_i
=> 1408052780
> t.to_pst.to_i
=> 1408027580

gem 'timezone' 提出了类似的问题。

This 解决方案有效,但会更改全局变量并且不是线程安全的。

操作系统时区需要保持 UTC。

我只需要一种方法来更改单个 Time 对象的时区。这是一个简单的问题,似乎应该有一个简单的解决方案!有人找到了吗?提前致谢!

【问题讨论】:

  • 考虑使用TZInfo gem。此外,您应该使用完整的 IANA 时区标识符 'America/Los_Angeles'。时区缩写可能不明确(例如,CST 有 5 种不同的含义)。

标签: ruby time timezone sinatra


【解决方案1】:

纯红宝石

Time.now.utc.localtime("+05:30")

其中 +05:30 (IST) 是特定区域的偏移量

【讨论】:

  • 太棒了!在搜索了这么多答案之后——这对我来说是唯一完美的答案......
  • 这有问题。我运行此代码Time.new(1942).utc.localtime('+05:30'),一个在我的本地机器上(我的 tz 是亚洲/加尔各答),一个在位于 +0100 tz (rextester.com/l/ruby_online_compiler) 的服务器上,返回的时间在我的系统上提前 15 小时 30 分钟即使我保持时区完好无损!我想让你看看 1942 年的时区,它是 +0630:>> Time.new(1942).zone # => "+0630" ,即使我在 +05:30...
【解决方案2】:

您可以在 Rails 之外使用 Active Support 中的 Time 扩展:

require 'active_support/core_ext/time'

t = Time.now
#=> 2014-08-15 15:38:56 +0200

t.in_time_zone('Pacific Time (US & Canada)')
#=> Fri, 15 Aug 2014 06:38:56 PDT -07:00

现在你可以做

class Time
  def to_pst
    in_time_zone('Pacific Time (US & Canada)')
  end
end

t = Time.now
#=> 2014-08-15 15:42:39 +0200

t.to_i
#=> 1408110159

t.to_pst
#=> Fri, 15 Aug 2014 06:42:39 PDT -07:00

t.to_pst.to_i
#=> 1408110159

# timestamp does not change!

此外,您可能还希望在NumericDate 上延长时间:

require 'active_support/core_ext/date'
require 'active_support/core_ext/numeric/time'

2.days.from_now
#=> 2014-08-17 15:42:39 +0200

【讨论】:

  • 非常感谢!这行得通。将来,当我在 Sinatra 项目中需要一些 Rails 功能时,它也会有所帮助。
  • 我还添加了一些您可能会觉得有用的扩展。
  • 请注意,gem(如果需要,我在 docker 容器中,所以我必须明确包含所有内容)称为“activesupport”,而不是“active_support”
【解决方案3】:

如果您不想加载大量库,并且不介意按照穷人的方式进行操作,并且您知道偏移量为 -8,例如,您可以减去 8*3600 秒得到新的时间。例如,

offset=-8
t = Time.now + offset * 3600

不过,您需要自己调整夏令时,这也不会改变时区,因此 %z 是不正确的。

【讨论】:

  • 我在尝试导入 activerecord 时间库时遇到问题,并且不想简单地导入所有 - 我有一个云应用程序,所以少即是多......在这些情况下这是一个不错的选择跨度>
【解决方案4】:

我最近对一个默认时间是 UTC 的 Iron.io 工作人员做了同样的事情

# For generality/testing, only require what you need. 
require 'active_support/all'  

# Set the Timezone 
Time.zone = "Asia/Hong_Kong" 

t = Time.zone.now
#=> 2015-01-20 16:44:58 +0800

有关支持的时区的信息,请查看 ActiveSupport http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html

【讨论】:

    【解决方案5】:

    以utc方式获取当前时间,然后加上偏移量:

    Time.now.utc + Time.zone_offset('PDT')
    #=> 2015-12-01 18:10:07 UTC
    

    这里的问题是PDT 固定为-8PST 固定为-7 和太平洋区域(根据一年中的时间和夏令时在两者之间调整的区域)不存在,为此,您可能需要 ActiveSupport。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-13
      • 2016-01-07
      • 2010-09-09
      • 2016-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多