如何使用 ruby 的 stdlib 中的时区函数?

How to use the timezone function in ruby's stdlib?

提问人:Lou Zell 提问时间:11/13/2023 更新时间:11/13/2023 访问量:103

问:

ruby 文档指出,我可以将 a 传递给 Time 初始值设定项:timezone

zone = timezone("Europe/Athens")      # Eastern European Time, UTC+2
Time.new(2002, 10, 31, 2, 2, 2, zone) #=> 2002-10-31 02:02:02 +0200

但是,当我尝试打电话时,我得到.我有什么特别的要求吗?timezoneundefined method 'timezone'

Ruby

评论


答:

1赞 disanv 11/13/2023 #1

事实上,时区方法是未定义的。不过,在 Unix 上有一个技巧可以将 Time 对象转换为任何时区。timezone(“Europe/Athens”) 用于与 Time 类(位于 /usr/share/zoneinfo/ 中的“zoneinfo”数据库)下的 C 库进行通信。因此,您可以通过将环境变量 TZ 设置为适当的值来临时更改当前进程的“系统”时区。

class Time
  def convert_zone(to_zone)
    original_zone = ENV["TZ"]
    utc_time = dup.gmtime
    ENV["TZ"] = to_zone
    to_zone_time = utc_time.localtime
    ENV["TZ"] = original_zone
    return to_zone_time
  end
end

t = Time.now
t.convert_zone("Europe/Athens")

这相当于编写自己的时区方法:)

评论

0赞 Stefan 11/13/2023
您的代码返回 的实例 ,而不是可以传递到的时区,如 OP 的示例所示。TimeTime.new
0赞 Lou Zell 11/14/2023
就我而言,ENV[“TZ”] 未设置,因此可能您的基础设施的某些部分正在为您配置该环境变量。不过我理解这种方法,谢谢你的诀窍!
1赞 disanv 11/14/2023
是的,如果没有设置 ruby,则正确引用 /etc/localtime。如果在 ENV 中设置了会影响时间显示方式的 TZ(例如在 ~/.bashrc 中),否则您可以直接在脚本中设置它 (ENV[“TZ”] = “your_timezone”)
5赞 Simone Carletti 11/13/2023 #2

你所指的方法实际上只是一个例子。它在 Ruby 中不存在。我同意,措辞和例子可能有点误导。timezone

Ruby stdlib 通过传递时区 UTC 偏移量或名称,以字符串的形式传递时区。这在第一个示例中显示:

您可以传递 UTC 偏移量:

Time.new(2002, 10, 31, 2, 2, 2, "+02:00") #=> 2002-10-31 02:02:02 +0200

请注意字符串 ."+02:00"

那么你所指的“有罪”例子:

或者时区对象:

zone = timezone("Europe/Athens")      # Eastern European Time, UTC+2
Time.new(2002, 10, 31, 2, 2, 2, zone) #=> 2002-10-31 02:02:02 +0200

阅读此示例的方式就好像您在某处有一段代码,这里是假设的方法,它返回一个对象,该对象表示可以提供给初始值设定项的 TZ。timezone

下面是一个实际的例子,它使用了广泛采用的 tzinfo 库:

[2] pry(main)> require 'tzinfo'
=> true
[3] pry(main)> tz = TZInfo::Timezone.get('America/New_York')
=> #<TZInfo::DataTimezone: America/New_York>
[4] pry(main)> Time.new(2002, 10, 31, 2, 2, 2, tz)
=> 2002-10-31 02:02:02 -0500
[5] pry(main)> Time.new(2002, 10, 31, 2, 2, 2)
=> 2002-10-31 02:02:02 +0100

请注意,在上面的示例中,假设的方法是如何替换为从 初始化新 TZ 对象的实际代码的。timezonetzinfo

最后,您可以通过调用对象来访问时区设置。请注意,您获得的内容取决于您用于初始化区域的对象。默认情况下,它是一个字符串,但是如果我使用以下示例,我将获得tzinfo实例。zoneTimetzinfo

[6] pry(main)> Time.new(2002, 10, 31, 2, 2, 2, tz).zone
=> #<TZInfo::DataTimezone: America/New_York>
[7] pry(main)> Time.new.zone
=> "CET"

总而言之,没有定义方法(实际上它在文档中的显示方式需要在 中定义它,这在 Ruby 中会更奇怪)。这只是一个占位符示例。timezoneKernel