ruby-on-rails - 如何验证和解析带有用户时区的 ISO 8601 时间戳?

标签 ruby-on-rails timezone iso8601

我需要能够接收用户输入的时间戳,带有可选时区组件,验证它是否是有效的 ISO 8601 时间表示,并解析它根据用户配置的时区

我在 Ruby 2.3 上使用 Rails 4.2.6。我曾希望 Time.zone (ActiveSupport::TimeZone) 具有与 Time::iso8601 等效的实现,这样我就可以拯救 ArgumentError 异常以确定用户输入是否是有效的 ISO 8601 时间表示。然后我可以做类似的事情:

user_time_zone = 'America/Los_Angeles' # Would actually be from user's stored settings
params = {when: '2016-04-01T01:01:01'} # Would actually be from user input

# Would actually use Time::use_zone in around_action filter
Time.use_zone(user_time_zone) do
  timestamp = Time.zone.iso8601 params[:when]
end

但是,遗憾的是,不存在这样的方法。而且我找不到等效的。

我不能使用 Time.zone.parse,因为它将不明确的日期视为有效(例如 Time.zone.parse '04/11/16' # => Tue, 0004 年 11 月 16 日 00:00:00 LMT -07:52).

到目前为止,我能想到的最佳替代方案是:

Time.use_zone(user_time_zone) do
  old_tz = ENV['TZ']
  ENV['TZ'] = Time.zone.name
  timestamp = Time.iso8601 params[:when] # => 2016-04-01 01:01:01 -0700
  ENV['TZ'] = old_tz
end

但这很丑陋,以这种方式摆弄环境变量感觉不妥,而且它肯定不是 Rails 风格的。如何以 Rails 方式根据用户时区验证和解析时间?

最佳答案

我建议您简单地将分配分为两个步骤:首先验证 ISO8601 格式,如果有效,则解析它:

user_time_zone = 'America/Los_Angeles'
params = { when: '2016-04-01T01:01:01' }

begin
  Time.iso8601(params[:when])      # raises ArgumentError if format invalid
rescue ArgumentError => e
  puts "invalid time format" 
  return
end

Time.use_zone(user_time_zone) do
  timestamp = Time.zone.parse(params[:when])
end

关于ruby-on-rails - 如何验证和解析带有用户时区的 ISO 8601 时间戳?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36557175/

相关文章:

php - 如何将字符串持续时间转换为 ISO 8601 持续时间格式? (例如 "30 minutes"到 "PT30M")

java - 在 Scala 中解析具有 ISO 格式的日期时间

.net - 测量耗时会计日光节约

asp.net - .net JSON 序列化程序将本地客户端时间返回给浏览器?

java - 将 localDate 与 UTC 结合使用

ruby-on-rails - 网站的 Web 前端缓存最佳实践?

powershell - 在 Powershell 中获取给定日期的 ISO 8601 年中的第几周

ruby-on-rails - 在 CanCan 中使用 block 定义能力会引发异常

ruby-on-rails - 将 Sidekiq 升级到 v6 后,它不会在生产环境中自动启动

ruby-on-rails - ruby 子类 : Including Different Modules Based on Inheritance