将时区字符串(即 US/Eastern)转换为偏移量

Converting timezone string, i.e. US/Eastern, to offset

我正在寻找一种纯 Ruby 的方法,该方法采用诸如“US/Eastern”之类的时区字符串,并将其与时间戳的字符串表示形式一起使用,以转换为带时区的时间戳.

到目前为止我发现的是 strptime,它支持像“EST”这样的短时区名称或像“-0500”这样的时区偏移量,但不支持完整的时区字符串。

我需要能够 运行 这作为 Logstash ruby 过滤器的一部分。我有一些 JSON 包含没有时区的时间戳,如下所示:

{
 "event": {
    "created": "2021-02-15_11-26-29",
  },
  "Accounts": [
    {
      "Name": "operator",
      "Caption": "SERVER\operator",
      "Domain": "SERVER",
      "PasswordChangeable": "False",
      "PasswordRequired": "True",
      "PasswordExpires": "False",
      "Disabled": "False",
      "Lockout": "False",
      "LocalAccount": "True",
      "FullName": "operator",
      "Status": "OK",
      "LastLogon": "07/08/2020 2:14:13 PM"
    },
    ...
  ]
}

对于 event.created 字段,我可以只使用 date 过滤器:

    date {
        match => [ "[event][created]", "yyyy-MM-dd_HH-mm-ss" ]
        timezone => "${TIMEZONE}"
        target => "[event][created]"
    }

其中 ${TIMEZONE} 是保存完整时区名称的环境变量,即“US/Eastern”。但是对于 Acounts.LastLogin 字段我不能使用 date 过滤器,因为它驻留在一个可变长度的列表中,所以我不得不求助于 ruby 过滤器。我能得出的最接近的结果是:

    ruby {
        code => 'event.get("[Accounts]").each_index {|x|
                    tz = "-0500"
                    last_logon_str = event.get("[Accounts][#{x}][LastLogon]")
                    last_logon = DateTime.strptime(last_logon_str + " " + tz, "%m/%d/%Y %I:%M:%S %p %z")
                    event.set("[users][#{x}][last_logon]", last_logon.strftime("%Y-%m-%dT%H:%M:%S%z"))
                 }'
    }

但是当然这是使用硬编码的时区偏移量而不是包含全名的变量。

我在 https://ruby-doc.org/core-2.6/Time.html 查看的 Time 对象的文档指出可以使用 timezone:

创建 Time 对象

Or a timezone object:

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

然后我可以使用它来提取偏移量,但我无法在任何地方找到对 timezone 的引用。

处理此问题的最佳方法是什么?

时区是 TZInfo class 的一部分。你需要要求它。以下代码

    ruby {
        code => '
            require "tzinfo"
            tz = TZInfo::Timezone.get(ENV["TIMEZONE"])
            event.set("offset", tz.observed_utc_offset())
        '
    }

当 $TIMEZONE 为“US/Eastern”时 "offset" => -18000,