059_add_birth_date_to_person.rb 6.77 KB
require File.dirname(__FILE__) + '/../../config/environment'

class AddBirthDateToPerson < ActiveRecord::Migration

  class ConvertDates
    def self.convert(date_string)
      return if date_string.blank?
      return date_string if date_string.kind_of?(Date)
      return unless date_string.kind_of?(String)
      return if date_string =~ /[a-zA-Z]/

      if date_string =~ /^\d\d([^\d]+)\d\d$/
        date_string += $1 + (Date.today.year - 100).to_s
      end

      if date_string =~ /[^\d](\d\d)$/
        year = $1.to_i
        date_string = date_string[0..-3] + (year > (Date.today.year - 2000) ? year + 1900 : year + 2000).to_s
      end

      if ! ((date_string =~ /(\d+)[^\d]+(\d+)[^\d]+(\d+)/) || (date_string =~ /^(\d\d)(\d\d)(\d\d\d\d)$/))
        return nil
      end
      begin
        Date.new($3.to_i, $2.to_i, $1.to_i)
      rescue Exception => e
        nil
      end
    end
  end

  class Person < ActiveRecord::Base
    set_table_name 'profiles'
    serialize :data, Hash
  end

  def self.up
    add_column :profiles, :birth_date, :date
    offset = 0
    while p = Person.find(:first, :conditions => "type = 'Person'", :order => 'id', :offset => offset)
      p.birth_date = ConvertDates.convert(p.data[:birth_date].to_s)
      p.save
      offset += 1
    end
  end

  def self.down
    remove_column :profiles, :birth_date
  end
end

if $PROGRAM_NAME == __FILE__
  require File.dirname(__FILE__) + '/../../test/test_helper'

  class ConvertDatesTest <  Test::Unit::TestCase
    SAMPLE = [
      "",
      "06/06/1973",
      "08/02/1981",
      "",
      "06/01/1955",
      "06 de dezembro ",
      "",
      "01/10/2980",
      "06/03/68",
      "21/07/1975",
      "13/11/1985",
      "",
      "17/11/2007",
      "",
      "19/10/1982",
      "",
      "22/07/1973",
      "17/02",
      "",
      "24/03/1966",
      "02-07-62",
      "11/071987",
      "10/01/1978",
      "04/07/1981",
      "",
      "14/06/00",
      "06/05",
      "21/12/1941",
      "04/04",
      "02.01.1956",
      "",
      "06/02/1986",
      "11/03/1981",
      "17.08.1956",
      "",
      "",
      "",
      "14/12/1981",
      "29/10/1962",
      "13/01/1982",
      "14/07/1984",
      "",
      "05/02/1976",
      "",
      "02-07-1962",
      "15/11/1976",
      "06/10/1970",
      "",
      "23/ 12/ 1999",
      "10/05/1972",
      "26/06/1951",
      "19/11/1954",
      "14/03/2002",
      "",
      "",
      "",
      "17/06/1979",
      "07/08/1976",
      "19/09/1990",
      "21/06/1958",
      "",
      "09/10/1968",
      "17/11/1984",
      "21/02/1989",
      "18 de março",
      "",
      "23/03/1984",
      "18/08/1969",
      "01/07/1991",
      "22/02/1981",
      "02/05/1984",
      "",
      "19/10/1988",
      "04 de maio",
      "",
      "",
      "",
      "",
      "25/09/1985",
      "29/04/1991",
      "",
      "21/09/1975",
      "15/06/1976",
      "23/04/1983",
      "15/08/1981",
      "15/06/1972",
      "",
      "",
      "AGOSTO",
      "01/02",
      "",
      "24/10/1980",
      "11/07/1976",
      "",
      "",
      "01/02",
      "",
      "",
      "",
      "",
      "03/09/1982",
      "",
      "",
      "13/03/1985",
      "",
      "",
      "03/10/1974",
      "14.08.1981",
      "",
      "14/11/1979",
      "",
      "",
      "30/07/1981",
      "",
      "",
      "13/09/1979",
      "14/06/1978",
      "05/09/1957",
      "",
      "",
      "03/09/1982",
      "12/01/1987",
      "13/03/1986",
      "9/12/80",
      "21/12/1982",
      "15/12/85",
      "07/05/84",
      "21/10/1983",
      "4/07/1984",
      "17/04/1977",
      "9 junio 86",
      "12 diciembre 1983",
      "25/04/1959",
      "08/08/1972",
      "12/01/1986",
      "13/09/1979",
      "19/01/1986",
      "05/04/1982",
      "24/12/1958",
      "07 / 05 / 1956",
      "02/05/1984",
      "14/06/1980",
      "03/09/1982",
      "12/01/1987",
      "13/03/1986",
      "9/12/80",
      "21/12/1982",
      "15/12/85",
      "07/05/84",
      "21/10/1983",
      "4/07/1984",
      "17/04/1977",
      "9 junio 86",
      "12 diciembre 1983",
      "25/04/1959",
      "08/08/1972",
      "12/01/1986",
      "13/09/1979",
      "19/01/1986",
      "05/04/1982",
      "24/12/1958",
      "07 / 05 / 1956",
      "02/05/1984",
      "14/06/1980"
    ]

    should 'convert with slash' do
      date = AddBirthDateToPerson::ConvertDates.convert('10/01/2009')
      assert_equal [10, 1, 2009], [date.day, date.month, date.year]
    end

    should 'convert with hyphen' do
      date = AddBirthDateToPerson::ConvertDates.convert('10-01-2009')
      assert_equal [10, 1, 2009], [date.day, date.month, date.year]
    end

    should 'convert with dot' do
      date = AddBirthDateToPerson::ConvertDates.convert('10.01.2009')
      assert_equal [10, 1, 2009], [date.day, date.month, date.year]
    end

    should 'convert with slash and space' do
      date = AddBirthDateToPerson::ConvertDates.convert('10/ 01/ 2009')
      assert_equal [10, 1, 2009], [date.day, date.month, date.year]
    end

    should 'convert with empty to nil' do
      date = AddBirthDateToPerson::ConvertDates.convert('')
      assert_nil date
    end

    should 'convert with nil to nil' do
      date = AddBirthDateToPerson::ConvertDates.convert(nil)
      assert_nil date
    end

    should 'convert with two digits 1900' do
      date = AddBirthDateToPerson::ConvertDates.convert('10/01/99')
      assert_equal [10, 1, 1999], [date.day, date.month, date.year]
    end

    should 'convert with two digits 2000' do
      date = AddBirthDateToPerson::ConvertDates.convert('10/01/09')
      assert_equal [10, 1, 2009], [date.day, date.month, date.year]
    end

    should 'convert with two numbers' do
      date = AddBirthDateToPerson::ConvertDates.convert('10/01')
      assert_equal [10, 1, (Date.today.year - 100)], [date.day, date.month, date.year]
    end

    should 'convert to nil if non-numeric date' do
      date = AddBirthDateToPerson::ConvertDates.convert('10 de agosto de 2009')
      assert_nil date
    end

    should 'do nothing if date' do
      date = AddBirthDateToPerson::ConvertDates.convert(Date.today)
      assert_equal Date.today, date
    end

    should 'return nil when not string nor date' do
      date = AddBirthDateToPerson::ConvertDates.convert(1001)
      assert_nil date
    end

    should 'convert date without separators' do
      date = AddBirthDateToPerson::ConvertDates.convert('27071977')
      assert_equal [ 1977, 07, 27] , [date.year, date.month, date.day]
    end

    should 'not try to create invalid date' do
      assert_nil AddBirthDateToPerson::ConvertDates.convert('70/05/1987')
    end

    SAMPLE.each_with_index do |string,i|
      should "convert sample #{i} (#{string})" do
        result = AddBirthDateToPerson::ConvertDates.convert(string)
        assert(result.nil? || result.is_a?(Date))
      end
    end

  end

end