如何验证和解析带有用户时区的 ISO 8601 时间戳?
How can I validate and parse an ISO 8601 timestamp with user's time zone?
我需要能够接收用户输入的时间戳,带有 可选 时区组件,validate 这是一个有效的 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, 16 Nov 0004 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 方式验证和解析时间?
我认为您仍然可以将 around_action
用于您的用例。这就是我使用的,对我来说效果很好。
在我的 ApplicationController
我有:
class ApplicationController < ActionController::Base
around_action :set_time_zone
def set_time_zone
old_time_zone = Time.zone
Time.zone = user_time_zone
yield
ensure
Time.zone = old_time_zone
end
end
对 Time
的任何调用都将使用请求范围内的用户时区。
我建议您简单地将作业分为两步:首先验证 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
我需要能够接收用户输入的时间戳,带有 可选 时区组件,validate 这是一个有效的 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, 16 Nov 0004 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 方式验证和解析时间?
我认为您仍然可以将 around_action
用于您的用例。这就是我使用的,对我来说效果很好。
在我的 ApplicationController
我有:
class ApplicationController < ActionController::Base
around_action :set_time_zone
def set_time_zone
old_time_zone = Time.zone
Time.zone = user_time_zone
yield
ensure
Time.zone = old_time_zone
end
end
对 Time
的任何调用都将使用请求范围内的用户时区。
我建议您简单地将作业分为两步:首先验证 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