module MultiparameterDateTime::ClassMethods

Public Instance Methods

multiparameter_date_time(attribute_name) click to toggle source
# File lib/multiparameter_date_time.rb, line 28
def multiparameter_date_time(attribute_name)
  date_attribute = :"#{attribute_name}_date_part"
  time_attribute = :"#{attribute_name}_time_part"

  date_ivar_name = "@#{date_attribute}"
  time_ivar_name = "@#{time_attribute}"

  date_part_setter = :"#{date_attribute}="
  time_part_setter = :"#{time_attribute}="

  define_method "#{attribute_name}=" do |date_time_input|
    case date_time_input
    when Date, Time, DateTime
      begin
        date_time_input = date_time_input.in_time_zone
      rescue ArgumentError
      end
      write_attribute_for_multiparameter_date_time(attribute_name, date_time_input)
    when String
      iso8601 = begin
                  Time.iso8601(date_time_input).in_time_zone
                rescue ArgumentError
                  nil
                end
      if iso8601
        write_attribute_for_multiparameter_date_time(attribute_name, iso8601)
      else
        date_part, time_part = date_time_input.split(' ', 2)
        parsed_date_part = begin
                             date_part && Date.parse(date_part)
                           rescue ArgumentError
                             nil
                           end
        if time_part.nil? && parsed_date_part
          write_attribute_for_multiparameter_date_time(
            attribute_name,
            parsed_date_part.in_time_zone)
        else
          public_send(date_part_setter, date_part)
          public_send(time_part_setter, time_part)
        end
      end
    else
      write_attribute_for_multiparameter_date_time(attribute_name, date_time_input)
    end
  end

  define_method date_part_setter do |date_string|
    instance_variable_set(date_ivar_name, date_string)
    time_string = send(time_attribute)
    set_combined_datetime(attribute_name, date_string, time_string)
  end

  define_method time_part_setter do |time_string|
    instance_variable_set(time_ivar_name, time_string)
    date_string = send(date_attribute)
    set_combined_datetime(attribute_name, date_string, time_string)
  end

  define_method time_attribute do
    if instance_variable_defined?(time_ivar_name)
      instance_variable_get(time_ivar_name)
    else
      time = public_send(attribute_name)
      return nil if time.nil? || time == :incomplete

      time.strftime(MultiparameterDateTime.time_format)
    end
  end

  define_method date_attribute do
    if instance_variable_defined?(date_ivar_name)
      instance_variable_get(date_ivar_name)
    else
      date = public_send(attribute_name)
      return nil if date.nil? || date == :incomplete
      date.strftime(MultiparameterDateTime.date_format)
    end
  end
end