Skip to content

Instantly share code, notes, and snippets.

@maxshelley
Created February 6, 2015 20:06
Show Gist options
  • Save maxshelley/6581d8a3897e81493d39 to your computer and use it in GitHub Desktop.
Save maxshelley/6581d8a3897e81493d39 to your computer and use it in GitHub Desktop.
Date/Time Reformer for Rails 4.1 and Virtus.
class DateTimeReformer
include ActiveModel::Validations
def initialize(object: nil, field_name: nil, date: nil, time: nil)
@object, @field_name, @date, @time = object, field_name, date, time
@time.nil? ? check_valid_date(@date) : check_valid_date_time(@date, @time)
end
def reform_date
return unless errors.empty?
date = convert_values_to_integer(@time ? @date.merge(@time) : @date)
reformed_value = Date.new(date[:year], date[:month], date[:day])
reformed_value = DateTime.new(
date[:year], date[:month], date[:day], date[:hour], date[:minute]
) unless @time.nil?
@object.send("#{@field_name}=", reformed_value)
end
private
def convert_values_to_integer(hash)
hash.each { |_k, v| hash[hash.key v] = Integer(v, 10) if v }
end
def check_valid_date(d)
Date.strptime("#{d[:year]}-#{d[:month]}-#{d[:day]}", '%Y-%m-%d')
rescue ArgumentError => e
process_exception(e)
end
def check_valid_date_time(d, t)
DateTime.strptime(
"#{d[:year]}-#{d[:month]}-#{d[:day]}T#{t[:hour]}:#{t[:minute]}:00",
'%Y-%m-%dT%H:%M:%S')
rescue ArgumentError => e
process_exception(e)
end
def process_exception(e)
if e.message =~ /invalid value for Integer()/ || e.message =~ /invalid date/
errors.add @field_name.to_sym, 'is an invalid date.'
nil
else
fail e
end
end
end

Using Virtus as a form object, I found myself needing to take the date and time params that Rails was passing and re-form them into a Date or DateTime object.

If invalid date is passed back, I wanted to have errors I could pass directly to the form object.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment