文字列の中に年月日時分秒っぽい文字列があったら DateTime オブジェクトを生成して返す関数を書いてみた。自分が使うつもりの機能は実装できたが、完璧にパースするのは無理。


# coding: UTF-8
require 'date' # using DateTime
 
# 年表現を正規化
def normalize_year(y)
  # 年が2桁以下の場合、2000年以降とみなす
  # return (y < 100) ? (2000 + y) : y
 
  # 年が2桁以下の場合、平成年とみなす
  # return (y < 100) ? (1988 + y) : y
 
  # 何もしない
  return y
end
 
# フォーマットがわからない文字列を日時オブジェクトへ変換する
def parse_datetime(s)
 
  # 数字以外の文字で分割する
  strlist = s.split(/\D/)
  # 空文字列を削除
  strlist.reject!{|i|i.empty?}
 
  # 整数に変換
  intlist = strlist.map(&:to_i)
 
  # パターンに応じて DateTime オブジェクトを生成する
  if intlist.length == 6 then
    # 6個のときは[年,月,日,時,分,秒]
    intlist[0] = normalize_year(intlist[0])
    return DateTime.new(*intlist)

  elsif intlist.length == 3 then
    # 3個のときは[年,月,日]
    intlist[0] = normalize_year(intlist[0])
    return DateTime.new(*intlist)
 
  elsif strlist.length == 2 then
    # 2個のときは[年月日,時分秒]
    strlist = [
      strlist[0][ 0..-5],
      strlist[0][-4..-3],
      strlist[0][-2..-1],
      strlist[1][ 0..-5],
      strlist[1][-4..-3],
      strlist[1][-2..-1],
    ]
    intlist = strlist.map(&:to_i)
    intlist[0] = normalize_year(intlist[0])
    return DateTime.new(*intlist)
 
  elsif strlist.length == 1 then
    # 1個のときは[年月日時分秒]
    strlist = [
      strlist[0][  0..-11],
      strlist[0][-10..-9],
      strlist[0][ -8..-7],
      strlist[0][ -6..-5],
      strlist[0][ -4..-3],
      strlist[0][ -2..-1],
    ]
    intlist = strlist.map(&:to_i)
    intlist[0] = normalize_year(intlist[0])
    return DateTime.new(*intlist)
 
  else
    # あきらめて標準ライブラリにまかせる
    return DateTime.parse(s)
  end
end
 
# テストデータをパースしてみる
targets = [
  '動画 2014-07-24 7 43 59.mov',
  '写真 2014-07-24 15 1 2.mov',
  '2014_07_24_メモ.txt',
  '2014_07_29_10_11_12',
  '20140102_101112',
  '140102_91011',
  '20140102101112',
  '140102101112',
  'Mon, 01 Jan 1999 01:02:03 GMT',
]
targets.each{|t|
  d = parse_datetime(t)
  puts "#{t} => #{d.to_s}"
}

テストデータをパースしてみた実行結果。


動画 2014-07-24 7 43 59.mov => 2014-07-24T07:43:59+00:00
写真 2014-07-24 15 1 2.mov => 2014-07-24T15:01:02+00:00
2014_07_24_メモ.txt => 2014-07-24T00:00:00+00:00
2014_07_29_10_11_12 => 2014-07-29T10:11:12+00:00
20140102_101112 => 2014-01-02T10:11:12+00:00
140102_91011 => 0014-01-02T09:10:11+00:00
20140102101112 => 2014-01-02T10:11:12+00:00
140102101112 => 0014-01-02T10:11:12+00:00
Mon, 01 Jan 1999 01:02:03 GMT => 1999-01-01T01:02:03+00:00

tags: ruby

Posted by NI-Lab. (@nilab)