Skip to content

Commit

Permalink
Merge pull request #93 from theablefew/feature/cast_datetime_values
Browse files Browse the repository at this point in the history
Fix datetime casting and allow model_format
  • Loading branch information
esmarkowski authored Mar 19, 2024
2 parents cec3b50 + d6019f8 commit 193a66d
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 0 deletions.
50 changes: 50 additions & 0 deletions lib/stretchy/attributes/type/date_time.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,62 @@ module Stretchy::Attributes::Type
class DateTime < Stretchy::Attributes::Type::Base
OPTIONS = [:doc_values, :format, :locale, :ignore_malformed, :index, :null_value, :on_script_error, :script, :store, :meta]
attr_reader *OPTIONS
include ActiveModel::Type::Helpers::Timezone
include ActiveModel::Type::Helpers::AcceptsMultiparameterTime.new(
defaults: { 4 => 0, 5 => 0 }
)
include ActiveModel::Type::Helpers::TimeValue

def initialize(**args)
@model_format = args.delete(:model_format)
super
end

def type
:datetime
end

def type_for_database
:date
end

private
def cast_value(value)
return apply_seconds_precision(value) unless value.is_a?(::String)
return if value.empty?

fast_string_to_time(value) || fallback_string_to_time(value) || custom_string_to_time(value)
end

# '0.123456' -> 123456
# '1.123456' -> 123456
def microseconds(time)
time[:sec_fraction] ? (time[:sec_fraction] * 1_000_000).to_i : 0
end

def custom_string_to_time(string)
::Date.strptime(string, @model_format)
end

def fallback_string_to_time(string)
time_hash = begin
::Date._parse(string)
rescue ArgumentError => e
end
return unless time_hash

time_hash[:sec_fraction] = microseconds(time_hash)

new_time(*time_hash.values_at(:year, :mon, :mday, :hour, :min, :sec, :sec_fraction, :offset))
end

def value_from_multiparameter_assignment(values_hash)
missing_parameters = [1, 2, 3].delete_if { |key| values_hash.key?(key) }
unless missing_parameters.empty?
raise ArgumentError, "Provided hash #{values_hash} doesn't contain necessary keys: #{missing_parameters}"
end
super
end

end
end
29 changes: 29 additions & 0 deletions spec/stretchy/attributes/type/date_time_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
require 'spec_helper'

describe 'datetime' do

let(:model) do
stub_const("DateTimeModel", Class.new(StretchyModel) do
attribute :date, :datetime
end)
end

it 'casts value' do
expect(model.new(date: '2020-01-01').date).to eq(DateTime.parse('2020-01-01'))
expect(model.new(date: '2020-01-01T00:00:00').date).to eq(DateTime.parse('2020-01-01T00:00:00'))

end

it 'allows a custom format' do
model.attribute :custom, :datetime, model_format: '%m/%d/%Y'
expect(model.new(custom: '07/17/1918').custom).to eq(DateTime.parse('1918-07-17'))
expect(model.new(custom: '17/07/1918').custom).to eq(DateTime.parse('1918-07-17'))
expect(model.new(custom: '17/07/1918 ').custom).to eq(DateTime.parse('1918-07-17'))
expect(model.new(custom: '17/07/1918 10:02').custom).to eq(DateTime.parse('1918-07-17 10:02'))
end

it 'returns a time' do
expect(model.new(date: '2020-01-01').date).to be_a(Time)
end

end

0 comments on commit 193a66d

Please sign in to comment.