Mike Neumegen
Mike Neumegen

Reputation: 2486

Ruby on Rails 3 Time - Parse Milliseconds

I'm trying to parse a date like: 2011-05-21 04:20:46.011 into a Time object in Rails. So far I have the following:

Time.strptime("2011-05-21 04:20:46.011", "%Y-%m-%d %H:%M:%S.%3N")

But it doesn't seem to like the "%3N" at the end. How do I parse this date?

Upvotes: 2

Views: 6870

Answers (3)

Jignesh Gohel
Jignesh Gohel

Reputation: 6562

With Ruby v 2.3.2 and Rails v 5.0.0.1 in rails console

2.3.2 :035 > Time.parse("2011-05-21 04:20:46.011", "%Y-%m-%d %H:%M:%S.%3N")
NoMethodError: undefined method `getlocal' for "%Y-%m-%d %H:%M:%S.%3N":String
    from /home/jignesh/.rvm/rubies/ruby-2.3.2/lib/ruby/2.3.0/time.rb:264:in `make_time'
    from /home/jignesh/.rvm/rubies/ruby-2.3.2/lib/ruby/2.3.0/time.rb:366:in `parse'
    from (irb):35

Note: In code below in the parse format, NOT prefixed %N with the number of fractional digits like %3N and instead simply specified %N and it works

2.3.2 :037 > Time.strptime("2011-05-21 04:20:46.011", "%Y-%m-%d %H:%M:%S.%N")
 => 2011-05-21 04:20:46 +0530 
2.3.2 :038 > tt = Time.strptime("2011-05-21 04:20:46.011", "%Y-%m-%d %H:%M:%S.%N")
 => 2011-05-21 04:20:46 +0530 
2.3.2 :039 > tt.usec
 => 11000 

The above code didn't worked when using parse

2.3.2 :040 > tt = Time.parse("2011-05-21 04:20:46.011", "%Y-%m-%d %H:%M:%S.%N")
NoMethodError: undefined method `getlocal' for "%Y-%m-%d %H:%M:%S.%N":String
    from /home/jignesh/.rvm/rubies/ruby-2.3.2/lib/ruby/2.3.0/time.rb:264:in `make_time'
    from /home/jignesh/.rvm/rubies/ruby-2.3.2/lib/ruby/2.3.0/time.rb:366:in `parse'
    from (irb):40

It looks strange because Time.strptime(date, format, now=self.now) official documentation does mention about %3N, %6N and %9N explicitly and using them in the parse format doesn't work!

Rails does provide a counterpart strptime(str, format, now=now()) as part of ActiveSupport::TimeZone API and it internally does the parsing using Ruby's standard DateTime._strptime as shown in its source-code:

# File activesupport/lib/active_support/values/time_zone.rb, line 382
def strptime(str, format, now=now())
  parts_to_time(DateTime._strptime(str, format), now)
end

And I guess DateTime._strptime internally delegates to Ruby's standard Time.strptime

For those who are looking for leveraging Rails's Time.zone.parse counterpart for parsing in a specific format they can use below code:

tt = Time.zone.strptime('1999-12-31 14:00:00.011111', '%Y-%m-%d %H:%M:%S.%N')
 => Fri, 31 Dec 1999 14:00:00 UTC +00:00 
2.3.2 :031 > tt.usec
 => 11111 

Hope someone from the core-team can clarify about this behaviour observed and if the behaviour is normal then at-least a note should be made about in the documentation.

Upvotes: 3

Zabba
Zabba

Reputation: 65517

Use parse:

x = Time.parse("2011-05-21 04:20:46.011", "%Y-%m-%d %H:%M:%S.%3N")
# => 2011-05-21 04:20:46 -0700
x.usec
# => 11000

In many case you don't need to pass in the format either:

x = Time.parse("2011-05-21 04:20:46.011")
# => 2011-05-21 04:20:46 -0700
x.usec
# => 11000

Upvotes: 9

Chandresh Pant
Chandresh Pant

Reputation: 1183

Try Time.parse("2011-05-21 04:20:46.011", "%Y-%m-%d %H:%M:%S.%3N")

Upvotes: 3

Related Questions