Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Date parsing #29

Open
Dan2552 opened this issue Apr 1, 2013 · 8 comments
Open

Date parsing #29

Dan2552 opened this issue Apr 1, 2013 · 8 comments

Comments

@Dan2552
Copy link

Dan2552 commented Apr 1, 2013

I'm getting weird results with date parsing

(main)> a.date_column = "2013-04-01T09:00:00+01:00"
=> "2013-04-01T09:00:00+01:00"
(main)> a.date_column
=> 2013-04-01 02:00:00 +0100

edit---
ooer now I'm confused, it uses the NSDate.dateWithNaturalLanguageString method which isn't even an iOS NSDate method but rather an OS X one

@sxross
Copy link
Owner

sxross commented Apr 1, 2013

The current version uses a deprecated conversion, 'NSDate.dateWithNaturalLanguageString:`. There's been some discussion about whether this kind of date conversion actually belongs here, but I came up with another solution, which I proposed to @colinta for SugarCube. You can see it here:

https://github.com/rubymotion/sugarcube/blob/master/lib/sugarcube/date_parser.rb

    def cast_to_date(arg)
      case arg
        when String
          return NSDate.dateWithNaturalLanguageString(arg.gsub('-','/'), locale:NSUserDefaults.standardUserDefaults.dictionaryRepresentation)
        when Time
          return NSDate.dateWithNaturalLanguageString(arg.strftime('%Y/%m/%d %H:%M'), locale:NSUserDefaults.standardUserDefaults.dictionaryRepresentation)
        else
          return arg
      end
    end

I do consider this an issue in MotionModel, and if you want a quick fix, there are two paths to take:

Do the cast yourself. I.e., my_model.my_date = MakeADateOutOf(my_form_data)

-or-

Try overriding the cast:

module MotionModel
  module Model
    def cast_to_date(arg)
      case arg
        when String
          return arg.to_date # uses the SugarCube data detector
        when Time
          return arg.strftime('%Y/%m/%d %H:%M').to_date # uses the SugarCube data detector
        else
          return arg
      end
    end
  end
end

I haven't tried this, but I did supply specs for the SugarCube implementation.

If you know your date will always be in the 8601 format, you might be able to use Time.parse.

I'll leave this issue open until I can get it "fixed".

@Dan2552
Copy link
Author

Dan2552 commented Apr 1, 2013

turns out Sugarcube doesn't like 8601 either

(main)> SugarCube::DateParser.parse_date("2013-04-01T09:00:00+01:00")
=> 2013-04-01 00:00:00 +0100

If anybody else comes across this, seems you can use NSDateFormatter:

> formatter = NSDateFormatter.new
> formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
> formatter.dateFromString "2013-04-01T09:00:00+01:00"
=> 2013-04-01 09:00:00 +0100

@sxross
Copy link
Owner

sxross commented Apr 1, 2013

Then it's not SugarCube -- it's Apple's data detector. Time.parse does understand 8601 according to the documentation. Have you given this a try? Again, if you absolutely know it's 8601, you have significant latitude to override this cast method in MotionModel.

On Apr 1, 2013, at 11:38 AM, Dan2552 [email protected] wrote:

turns out Sugarcube doesn't like 8601 either

(main)> SugarCube::DateParser.parse_date("2013-04-01T09:00:00+01:00")
=> 2013-04-01 00:00:00 +0100

Reply to this email directly or view it on GitHub.

@Dan2552
Copy link
Author

Dan2552 commented Apr 1, 2013

Where is Time.parse supposed to be defined? I get

#<NoMethodError: undefined method `parse' for Time:Class>

@Dan2552
Copy link
Author

Dan2552 commented Apr 1, 2013

Bubblewrap has an iso8601 method, alas it doesn't like the time zone

> Time.iso8601 "2012-05-31T19:41:33Z"
=> 2012-05-31 21:41:33 +0200
> Time.iso8601 "2013-04-01T09:00:00+0100"
=> nil

I'm personally fine with using the NSDateFormatter way that I added earlier (I just had a thought that you maybe missed my edit if you were replying by email rather than web)

@sxross
Copy link
Owner

sxross commented Apr 1, 2013

Arrrrgh. Ruby 1.8.7 Docs point to this:

http://ruby-doc.org/stdlib-1.8.7/libdoc/time/rdoc/Time.html#method-c-parse

Ruby 1.9.2 docs point to this:

http://ruby-doc.org/stdlib-1.9.2/libdoc/time/rdoc/Time.html#method-c-parse

However... This appears not to have been implemented in RubyMotion as Time is a wrapper for NSDate. I think that's the wrong answer and submitted a ticket: [#648] Time.parse is not implemented.

In the meantime, try this:

class Time
def self.from_8601(str)
regex8601 = /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(.)(\d{2})(\d{2})/
matches = str.match(regex8601)
return nil if matches.nil?
time = Time.new(matches[1].to_i,
matches[2].to_i,
matches[3].to_i,
matches[4].to_i,
matches[5].to_i,
matches[6].to_i,
matches[7] + matches[8] + ':' + matches[9]
)
end
end

On Apr 1, 2013, at 12:54 PM, Dan2552 [email protected] wrote:

Where is Time.parse supposed to be defined? I get

#<NoMethodError: undefined method `parse' for Time:Class>

Reply to this email directly or view it on GitHub.

@sxross
Copy link
Owner

sxross commented Apr 1, 2013

Follow-up to this. HipByte points out, correctly, that Time.parse is in stdlib and not core. Looks like we'll have to roll our own solutions here.

I'll leave this issue open for discussion about what kind of date input MotionModel should recognize:

  • arbitrary user strings like "tomorrow", "12/18/16", "three days from now"
  • specific strings like rfc8601 (and others?)
  • none of the above
  • all of the above

One place to put core extensions is in the active_support gem (https://github.com/hookercookerman/motion_support). That takes the date-related concerns outside of the data-modeling domain and places it in a more logical location.

On Apr 1, 2013, at 2:03 PM, Steve Ross [email protected] wrote:

Arrrrgh. Ruby 1.8.7 Docs point to this:

http://ruby-doc.org/stdlib-1.8.7/libdoc/time/rdoc/Time.html#method-c-parse

Ruby 1.9.2 docs point to this:

http://ruby-doc.org/stdlib-1.9.2/libdoc/time/rdoc/Time.html#method-c-parse

However... This appears not to have been implemented in RubyMotion as Time is a wrapper for NSDate. I think that's the wrong answer and submitted a ticket: [#648] Time.parse is not implemented.

In the meantime, try this:

class Time
def self.from_8601(str)
regex8601 = /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(.)(\d{2})(\d{2})/
matches = str.match(regex8601)
return nil if matches.nil?
time = Time.new(matches[1].to_i,
matches[2].to_i,
matches[3].to_i,
matches[4].to_i,
matches[5].to_i,
matches[6].to_i,
matches[7] + matches[8] + ':' + matches[9]
)
end
end

On Apr 1, 2013, at 12:54 PM, Dan2552 [email protected] wrote:

Where is Time.parse supposed to be defined? I get

#<NoMethodError: undefined method `parse' for Time:Class>

Reply to this email directly or view it on GitHub.

@DougPuchalski
Copy link
Contributor

You may want to have a look at https://github.com/archan937/MocRuby/blob/master/lib/moc_ruby/mocks/mac_ruby-0.12/time.rb.

This and lock-o-motion are becoming valuable additions to my project. I think there may be a lot of MacRuby code that can be leveraged, and good for it to come from a common place.

IMO parsing RFC dates is one thing, natural language is entirely another. I always vote for being explicit on format expectations as incorrect results often go unnoticed.

On Monday, April 1, 2013 at 2:36 PM, s.ross wrote:

Follow-up to this. HipByte points out, correctly, that Time.parse is in stdlib and not core. Looks like we'll have to roll our own solutions here.

I'll leave this issue open for discussion about what kind of date input MotionModel should recognize:

  • arbitrary user strings like "tomorrow", "12/18/16", "three days from now"
  • specific strings like rfc8601 (and others?)
  • none of the above
  • all of the above

One place to put core extensions is in the active_support gem (https://github.com/hookercookerman/motion_support). That takes the date-related concerns outside of the data-modeling domain and places it in a more logical location.

On Apr 1, 2013, at 2:03 PM, Steve Ross <[email protected] (mailto:[email protected])> wrote:

Arrrrgh. Ruby 1.8.7 Docs point to this:

http://ruby-doc.org/stdlib-1.8.7/libdoc/time/rdoc/Time.html#method-c-parse

Ruby 1.9.2 docs point to this:

http://ruby-doc.org/stdlib-1.9.2/libdoc/time/rdoc/Time.html#method-c-parse

However... This appears not to have been implemented in RubyMotion as Time is a wrapper for NSDate. I think that's the wrong answer and submitted a ticket: [#648] Time.parse is not implemented.

In the meantime, try this:

class Time
def self.from_8601(str)
regex8601 = /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(.)(\d{2})(\d{2})/
matches = str.match(regex8601)
return nil if matches.nil?
time = Time.new(matches[1].to_i,
matches[2].to_i,
matches[3].to_i,
matches[4].to_i,
matches[5].to_i,
matches[6].to_i,
matches[7] + matches[8] + ':' + matches[9]
)
end
end

On Apr 1, 2013, at 12:54 PM, Dan2552 <[email protected] (mailto:[email protected])> wrote:

Where is Time.parse supposed to be defined? I get

#<NoMethodError: undefined method `parse' for Time:Class>

Reply to this email directly or view it on GitHub.


Reply to this email directly or view it on GitHub (#29 (comment)).

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

No branches or pull requests

3 participants