Ruby: 列出日期时间格式选项
Ruby: List DateTime Format Options
我正在从 CSV 文件中导入数据,我想让我的用户指定 DateTime 列的格式。我没有让他们输入格式字符串并处理验证输入的痛苦,而是计划给他们一个 select 框,其中列出所有格式选项(例如 %m/%d/%Y
,等等。 ..).有人提到 gem 已经存在,它将列出所有合理的 DateTime 格式,但我一直无法找到它。如何获取可用的日期时间格式列表以供显示?
查看 DateTime
class。它是标准库的一部分,而不是外部 gem。您需要 require date
才能使用它。
以下是 irb 中的一些示例;请注意,使用 strftime
您有很大的灵活性,并且需要指定您自己的格式字符串。
2.3.0 :007 > dt = DateTime.now
=> #<DateTime: 2016-05-21T03:16:51+08:00 ((2457529j,69411s,139202000n),+28800s,2299161j)>
2.3.0 :008 > dt.iso8601
=> "2016-05-21T03:16:51+08:00"
2.3.0 :009 > dt.xmlschema
=> "2016-05-21T03:16:51+08:00"
2.3.0 :010 > dt.jisx0301
=> "H28.05.21T03:16:51+08:00"
2.3.0 :011 > dt.rfc3339
=> "2016-05-21T03:16:51+08:00"
2.3.0 :012 > dt.httpdate
=> "Fri, 20 May 2016 19:16:51 GMT"
2.3.0 :013 > dt.strftime('%Y-%m-%dT%H:%M:%S%z')
=> "2016-05-21T03:16:51+0800"
您可能对另一种选择感兴趣。不久前我不得不做类似的事情,并且支持几乎任意的日期格式。最后,我们从我们支持的所有数据源(CSV 文件)中检测到 29 种不同的格式(所有美国和加拿大国内)。
我想出了这个 class 来解析和缓存结果:
class DateParser
@@date_cache = {}
def self.is_date?(date)
return self.match_digital_date?(date) || self.match_instance_date?(date)
end
def self.parse_date(date)
return nil if date.blank?
return date if date.instance_of?(Date)
date = date.to_s
cached_date = @@date_cache[date]
return cached_date if !cached_date.nil?
match = self.match_instance_date?(date)
if !match.nil?
month_str = match[1].upcase
day = match[2].to_i
year = match[3].to_i
year += (year < 20) ? 2000 : 1900 if year < 1600
month = ['JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC'].find_index {|mon| mon == month_str }
cached_date = Date.new(year, month+1, day) if !month.nil?
else
scrubbed_date = date.gsub(/^([0-9]+)[\/-]+([0-9]+)[\/-]+00$/, '\1/\2/2000')
begin
parsed = Chronic.parse(scrubbed_date)
rescue
parsed = nil
end
return nil if parsed.nil?
cached_date = parsed.to_date
end
@@date_cache[date] = cached_date
return cached_date
end
private
# Matches dates in these formats
# : 2015-01-13
# : 01-13-2015
# : 01-13-15
# : 13-01-15
# : 01/13/2015
# : 01/13/15
# : 13/01/15
def self.match_digital_date?(date)
return /^([0-9]+)[\/-]+([0-9]+)[\/-]+([0-9]+)$/.match(date)
end
def self.match_instance_date?(date)
return /^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d+)\/(\d+)/i.match(date)
end
end
这使用 Chronic gem 进行一些日期解析,基于初始正则表达式匹配来选择解析路径,以及我们在此过程中遇到的一些必要的修正。正确性和速度是这种方法的主要目标。在大多数情况下,缓存结果有助于将 CSV 文件中的日期处理速度提高 5 倍或更多。
如果您想跳过询问用户他们使用的是哪种格式,而只是继续使用您选择的任何日期,这应该可以满足您的需求。
我正在从 CSV 文件中导入数据,我想让我的用户指定 DateTime 列的格式。我没有让他们输入格式字符串并处理验证输入的痛苦,而是计划给他们一个 select 框,其中列出所有格式选项(例如 %m/%d/%Y
,等等。 ..).有人提到 gem 已经存在,它将列出所有合理的 DateTime 格式,但我一直无法找到它。如何获取可用的日期时间格式列表以供显示?
查看 DateTime
class。它是标准库的一部分,而不是外部 gem。您需要 require date
才能使用它。
以下是 irb 中的一些示例;请注意,使用 strftime
您有很大的灵活性,并且需要指定您自己的格式字符串。
2.3.0 :007 > dt = DateTime.now
=> #<DateTime: 2016-05-21T03:16:51+08:00 ((2457529j,69411s,139202000n),+28800s,2299161j)>
2.3.0 :008 > dt.iso8601
=> "2016-05-21T03:16:51+08:00"
2.3.0 :009 > dt.xmlschema
=> "2016-05-21T03:16:51+08:00"
2.3.0 :010 > dt.jisx0301
=> "H28.05.21T03:16:51+08:00"
2.3.0 :011 > dt.rfc3339
=> "2016-05-21T03:16:51+08:00"
2.3.0 :012 > dt.httpdate
=> "Fri, 20 May 2016 19:16:51 GMT"
2.3.0 :013 > dt.strftime('%Y-%m-%dT%H:%M:%S%z')
=> "2016-05-21T03:16:51+0800"
您可能对另一种选择感兴趣。不久前我不得不做类似的事情,并且支持几乎任意的日期格式。最后,我们从我们支持的所有数据源(CSV 文件)中检测到 29 种不同的格式(所有美国和加拿大国内)。
我想出了这个 class 来解析和缓存结果:
class DateParser
@@date_cache = {}
def self.is_date?(date)
return self.match_digital_date?(date) || self.match_instance_date?(date)
end
def self.parse_date(date)
return nil if date.blank?
return date if date.instance_of?(Date)
date = date.to_s
cached_date = @@date_cache[date]
return cached_date if !cached_date.nil?
match = self.match_instance_date?(date)
if !match.nil?
month_str = match[1].upcase
day = match[2].to_i
year = match[3].to_i
year += (year < 20) ? 2000 : 1900 if year < 1600
month = ['JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC'].find_index {|mon| mon == month_str }
cached_date = Date.new(year, month+1, day) if !month.nil?
else
scrubbed_date = date.gsub(/^([0-9]+)[\/-]+([0-9]+)[\/-]+00$/, '\1/\2/2000')
begin
parsed = Chronic.parse(scrubbed_date)
rescue
parsed = nil
end
return nil if parsed.nil?
cached_date = parsed.to_date
end
@@date_cache[date] = cached_date
return cached_date
end
private
# Matches dates in these formats
# : 2015-01-13
# : 01-13-2015
# : 01-13-15
# : 13-01-15
# : 01/13/2015
# : 01/13/15
# : 13/01/15
def self.match_digital_date?(date)
return /^([0-9]+)[\/-]+([0-9]+)[\/-]+([0-9]+)$/.match(date)
end
def self.match_instance_date?(date)
return /^(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d+)\/(\d+)/i.match(date)
end
end
这使用 Chronic gem 进行一些日期解析,基于初始正则表达式匹配来选择解析路径,以及我们在此过程中遇到的一些必要的修正。正确性和速度是这种方法的主要目标。在大多数情况下,缓存结果有助于将 CSV 文件中的日期处理速度提高 5 倍或更多。
如果您想跳过询问用户他们使用的是哪种格式,而只是继续使用您选择的任何日期,这应该可以满足您的需求。