Hibariya

Rubyで日付っぽい文字列を日時や日付に変換するときのこと

Chronicべんり。別に最近のものでもないのだけど、しらなかった。

それまではActiveSupportで頑張っていた。

require 'active_support/core_ext/object'
require 'date'

def parse_date_str(date_str)
  case date_str
  when /^yesterday$/i then 1.day.ago
  when /^today$/i     then 0.day.ago
  when /^tomorrow$/i  then 1.day.since
  when /^[0-9]+[\.\s](?:days?|weeks?|months?|years?)[\.\s](?:ago|since)$/i
    eval(date_str.gsub(/\s+/, '.'))
  else
    Date.parse(date_str)
  end.to_date
end

parse_date_str '20110101'   # => Sat, 01 Jan 2011
parse_date_str 'yesterday'  # => Tue, 20 Mar 2012
parse_date_str '1 week ago' # => Wed, 14 Mar 2012

こんなコード書かなくてもよかったんだ!

require 'date'
require 'chronic'

def parse_date_str(date_str)
  (Chronic.parse(date_str) || Date.parse(date_str)).to_date
end

parse_date_str '20110101'   # => #<Date: 2011-01-01 ((2455563j,0s,0n),+0s,2299161j)>
parse_date_str 'yesterday'  # => #<Date: 2012-03-20 ((2456007j,0s,0n),+0s,2299161j)>
parse_date_str '1 week ago' # => #<Date: 2012-03-14 ((2456001j,0s,0n),+0s,2299161j)>

Chronicはparseできなかったときはnilを返す。 Date.parseを残しているのは、YYYYMMDDみたいな形式も使いたかったからで、それを除けばだいたいChronicだけで充分だった。

戻り値の見た目(Date#inspect)が違うのはActiveSupportの拡張っぽい。