diff --git a/README.md b/README.md index 30617b9..b02b368 100644 --- a/README.md +++ b/README.md @@ -223,6 +223,17 @@ class Timely end ``` +If you have a specific date format that you need to use for parsing the date string, you can specify the format in the column type. For example: + +```ruby +class Task + include MotionModel::Model + include MotionModel::ArrayModelAdapter + + columns :due_date => {:type => :date, :format => "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"} +end +``` + You can also include the `Validatable` module to get field validation. For example: ```ruby diff --git a/motion/date_parser.rb b/motion/date_parser.rb index b59c17e..afe4499 100644 --- a/motion/date_parser.rb +++ b/motion/date_parser.rb @@ -14,6 +14,11 @@ def self.parse_date(date_string) detect(date_string).first.date end + + def self.parse_date_with_format(date_string, format) + allocate_date_formatter_with_format(format) + return @@isoDateFormatter.dateFromString(date_string) + end # Parse time zone from date # @@ -52,6 +57,11 @@ def self.allocate_date_formatter @@isoDateFormatter = NSDateFormatter.alloc.init @@isoDateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ'" end + + def self.allocate_date_formatter_with_format(format) + @@isoDateFormatter = NSDateFormatter.alloc.init + @@isoDateFormatter.dateFormat = format + end def self.fractional_date(date_string) allocate_date_formatter if @@isoDateFormatter.nil? diff --git a/motion/model/model_casts.rb b/motion/model/model_casts.rb index 3764b40..a8b0ffb 100644 --- a/motion/model/model_casts.rb +++ b/motion/model/model_casts.rb @@ -18,11 +18,16 @@ def cast_to_float(arg) arg.is_a?(Float) ? arg : arg.to_f end - def cast_to_date(arg) + def cast_to_date(arg, column_name) case arg when String - return DateParser::parse_date(arg) - # return NSDate.dateWithNaturalLanguageString(arg.gsub('-','/'), locale:NSUserDefaults.standardUserDefaults.dictionaryRepresentation) + date_format = options(column_name).key?(:format) && options(column_name)[:format] + if date_format + return DateParser::parse_date_with_format(arg,date_format) + else + return DateParser::parse_date(arg) + # return NSDate.dateWithNaturalLanguageString(arg.gsub('-','/'), locale:NSUserDefaults.standardUserDefaults.dictionaryRepresentation) + end when Time, NSDate return arg # return NSDate.dateWithNaturalLanguageString(arg.strftime('%Y/%m/%d %H:%M:%S'), locale:NSUserDefaults.standardUserDefaults.dictionaryRepresentation) @@ -52,7 +57,7 @@ def cast_to_type(column_name, arg) #nodoc when :boolean, :bool then cast_to_bool(arg) when :int, :integer, :belongs_to_id then cast_to_integer(arg) when :float, :double then cast_to_float(arg) - when :date, :time, :datetime then cast_to_date(arg) + when :date, :time, :datetime then cast_to_date(arg,column_name) when :text then cast_to_string(arg) when :array then cast_to_array(arg) when :hash then cast_to_hash(arg) diff --git a/spec/date_spec.rb b/spec/date_spec.rb index 7d3c9a8..efbf8de 100644 --- a/spec/date_spec.rb +++ b/spec/date_spec.rb @@ -96,4 +96,12 @@ class Model m.test_date.utc.to_s.should.not.eql '2012-04-23 18:25:51 UTC' end end + + describe "user specified date formats" do + it 'parses a user date format' do + date = DateParser::parse_date_with_format("2014-10-28T22:30:00.000-07:00", "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ") + date.should.not.be.nil + date.utc.to_s.should.eql '2014-10-29 05:30:00 UTC' + end + end end diff --git a/spec/model_casting_spec.rb b/spec/model_casting_spec.rb index 66c678b..7b12e05 100644 --- a/spec/model_casting_spec.rb +++ b/spec/model_casting_spec.rb @@ -8,6 +8,7 @@ class TypeCast :a_double => :double, :a_date => :date, :a_time => :time, + :b_date => {:type => :date, :format => "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ"}, :an_array => :array end @@ -20,6 +21,7 @@ class TypeCast @convertible.a_float = '3.7' @convertible.a_double = '3.41459' @convertible.a_date = '2012-09-15' + @convertible.b_date = "2014-10-28T22:30:00.000-07:00" @convertible.an_array = 1..10 end @@ -30,6 +32,7 @@ class TypeCast @convertible.a_float.should.is_a Float @convertible.a_double.should.is_a Float @convertible.a_date.should.is_a NSDate + @convertible.b_date.should.is_a NSDate @convertible.an_array.should.is_a Array end @@ -109,9 +112,18 @@ class TypeCast @convertible.a_date.should.is_a(NSDate) end + it 'returns an NSDate for a date field when provided a proper format for a given date string' do + @convertible.b_date.should.is_a(NSDate) + end + it 'the date field should be the same as it was in string form' do @convertible.a_date.to_s.should.match(/^2012-09-15/) end + + it 'parses date using a format if specified in column definition' do + @convertible.b_date.should.not.be.nil + @convertible.b_date.utc.to_s.should.eql '2014-10-29 05:30:00 UTC' + end it 'returns an Array for an array field' do @convertible.an_array.should.is_a(Array)