ruby DateTime parsing from 'mm/dd/yyyy' format - ruby

I am using ruby 1.9.3 and want to get Date or Time object from 'mm/dd/yyyy' date format string
Time.zone.parse("12/22/2011")
this is giving me *** ArgumentError Exception: argument out of range

require 'date'
my_date = Date.strptime("12/22/2011", "%m/%d/%Y")

As above, use the strptime method, but note the differences below
Date.strptime("12/22/2011", "%m/%d/%Y") => Thu, 22 Dec 2011
DateTime.strptime("12/22/2011", "%m/%d/%Y") => Thu, 22 Dec 2011 00:00:00 +0000
Time.strptime("12/22/2011", "%m/%d/%Y") => 2011-12-22 00:00:00 +0000
(the +0000 is the timezone info, and I'm now in GMT - hence +0000. Last week, before the clocks went back, I was in BST +0100. My application.rb contains the line config.time_zone = 'London')

Try Time.strptime("12/22/2011", "%m/%d/%Y")

Would it be an option for you to use Time.strptime("01/28/2012", "%m/%d/%Y") in place of Time.parse? That way you have better control over how Ruby is going to parse the date.
If not there are gems: (e.g. ruby-american_date) to make the Ruby 1.9 Time.parse behave like Ruby 1.8.7, but only use it if it's absolutely necessary.
1.9.3-p0 :002 > Time.parse '01/28/2012'
ArgumentError: argument out of range
1.9.3-p0 :003 > require 'american_date'
1.9.3-p0 :004 > Time.parse '01/28/2012'
=> 2012-01-28 00:00:00 +0000

Related

`DateTime.strptime` returns invalid date for weekday/time string

Why won't Ruby's strptime convert this to a DateTime object:
DateTime.strptime('Monday 10:20:20', '%A %H:%M:%S')
# => ArgumentError: invalid date
While these work?
DateTime.strptime('Wednesday', '%A')
# => #<DateTime: 2015-11-18T00:00:00+00:00 ((2457345j,0s,0n),+0s,2299161j)>
DateTime.strptime('10:20:20', '%H:%M:%S')
# => #<DateTime: 2015-11-18T10:20:20+00:00 ((2457345j,37220s,0n),+0s,2299161j)>
This looks like a bug - minitech's comment is spot on. For now, though, a workaround (because you probably want this to work now):
You can split it on the space, get the date from the weekday, then get the time component from the other string (using the _strptime method minitech mentioned). Then you can set the time on the first date to the time component from the second string:
def datetime_from_weekday_time_string(string)
components = string.split(" ")
date = DateTime.strptime(components[0], '%A')
time = Date._strptime(components[1], '%H:%M:%S') # returns a hash like {:hour=>10, :min=>20, :sec=>20}
return date.change(time)
end
2.2.2 :021 > datetime_from_weekday_time_string("Monday 10:20:20")
=> Mon, 16 Nov 2015 10:20:20 +0000
2.2.2 :022 > datetime_from_weekday_time_string("Saturday 11:45:21")
=> Sat, 21 Nov 2015 11:45:21 +0000
2.2.2 :023 > datetime_from_weekday_time_string("Thursday 23:59:59")
=> Thu, 19 Nov 2015 23:59:59 +0000

How to use to_date in rails?

Ruby 2.0
controller action
#date = "2013-12-21"
#new_date = #date.to_date
p #new_date
o/p: Sat, 21 Dec 2013
at view
<%= #new_date %>
o/p: 2013-12-21
i want on view "Sat, 21 Dec 2013"
Rails is so intelligent that it automatically calls all objects in a view that are not already a string via the method .to_s, which always converts the content of the object to a string.
Lets first dig me into the root cause, why such unexpected output :
kirti#kirti-Aspire-5733Z:~/workspace/testproject$ rvm use 1.9.3
Using /home/kirti/.rvm/gems/ruby-1.9.3-p484
kirti#kirti-Aspire-5733Z:~/workspace/testproject$ rails c
Loading development environment (Rails 3.2.16)
1.9.3p484 :001 > d = "2013-12-21".to_date
=> Sat, 21 Dec 2013
1.9.3p484 :002 > d.to_s
=> "2013-12-21"
1.9.3p484 :003 > d
=> Sat, 21 Dec 2013
1.9.3p484 :004 > d.class
=> Date
1.9.3p484 :005 > d.strftime('%a, %e %b %Y')
=> "Sat, 21 Dec 2013"
1.9.3p484 :006 >
"2013-12-21".to_date giving you a Date instance, not a String instance.d.class proved that. d is a Date instance, on which in view again to_s method is called as I told in the begining, so Sat, 21 Dec 2013 is again set back into the "2013-12-21". So your solution will be :
#date = "2013-12-21".to_date.strftime('%a, %e %b %Y')
"2013-12-21".to_date.strftime('%a, %e %b %Y') will give you the desired result as an String instance.So on string instance(receiver) if you apply to_s,you will get the same receiver back. Now you can use this #date variable in your view.
in Ruby 2.0 in a controller's action:
#date = "2013-12-21"
#new_date = #date.to_date
# => Sat, 21 Dec 2013
And use the #new_date on your view.
#new_date.strftime('%a, %e %b %Y')
Use it directly on the view.
From what I understand, you are getting
2013-12-21
but want
Sat, 21 Dec 2013
The reason it is outputted in the console nicely is because the console will auto format it for you. This can be verified by printing #new_date.to_s in the console, it'll be the unformatted version. To print it out on a screen in the way you want, you have to format it yourself.
You should use strftime like this:
#new_date = #new_date.strftime('%a, %e %b %Y')
or
#date.to_date.strftime('%a, %e %b %Y')
This will output Sat, 21 Dec 2013 correctly.
The best way to format a date object in Rails is by using the available I18n formatters.
<%= l # new_date, format: :long %>
As described in the guide, you can also create additional formats. For example, if none of the defaults matches your desired format, simply define
# config/locales/en.yml
en:
time:
formats:
custom: "%a, %e %b %Y"
then use
<%= l # new_date, format: :custom %>

What's up with Ruby Time including dates?

I love ruby's magic, but every so often you run across something that seems like a no-brainer.
Here's my problem:
I'm storing a value as Time in my DB using MySQL's Time Column type.
This store just the hh:mm:ss values.
Later when doing comparison's Ruby will grab this value and append 2001-01-01 hh:mm:ss UTC to it. (Record1 below was taken from my DB and is an ActiveRecord object obtained from a collection that happens to have a time attribute stored using MYSQL's Time function)
So it appears that my only option for useful comparions's is to use strftime? Is that right?
(ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-darwin10.8.0])
ruby-1.9.2-p290 :009 > record1.time
=> 2000-01-01 08:30:00 UTC
ruby-1.9.2-p290 :001 > time1 = "08:30:00"
=> "08:30:00"
ruby-1.9.2-p290 :002 > #time_obj1 = Time.parse time1
=> 2012-01-27 08:30:00 -0700
ruby-1.9.2-p290 :003 > #time_obj1.to_s
=> "2012-01-27 08:30:00 -0700"
ruby-1.9.2-p290 :004 >
So it appears that my only option for useful comparions's is to use
strftime? Is that right?
That, or you could do something like
timestring = "#{#time_obj1.hour}:#{#time_obj1.min}:#{#time_obj1.sec}"
But strftime is quite a few less characters, and the more standard way to achieve what you're after.

Ruby Time.zone.now.zone bug

What I mean is that there are different timezones with the same name, like CST (-06:00 in US and +09:30 in Australia). Accordingly conversion to utc gives wrong results for Adelaide.
Any elegant way to solve this?
an easy way would be that you use the other nomenclature of naming time zones..
e.g. for UTC+9:30 intstead of using CST, you can use "Australia/Adelaide"
tz = TZInfo::Timezone.get("Australia/Adelaide")
t = Time.now # you could also get the UTC time here with Time.now.utc
t.zone
=> "PDT"
t.utc_offset
=> -25200
t.in_time_zone(tz) # this is a Rails extension of the Time class
=> Sat, 01 Oct 2011 14:31:05 CST +09:30
t.in_time_zone(tz).zone
=> "CST"
t.in_time_zone(tz).utc_offset
=> 34200
See:
http://api.rubyonrails.org/classes/Time.html
http://tzinfo.rubyforge.org/doc/
http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
do a "gem install activesupport", and in your script:
require 'rubygems'
require 'tzinfo'
require 'active_support'

Rails 2.3.2, wrong date, system date is correct

ruby-1.8.6-p399 :005 > Date.today
=> Wed, 24393 Dec 2135
ruby-1.8.6-p399 :006 > DateTime.now
=> Wed, 24393 Dec 2135 17:07:09 +0100
wopi#wopi-desktop:~/work/trunk$ date
Mi 2. Feb 17:08:46 CET 2011
What's wrong ?
https://gist.github.com/807916
What do you get with: Time.at(0) ?
Should be 1969...
What do you get with Time.now?
The date objects come from the date class, which inherits from the time class:
http://corelib.rubyonrails.org/classes/Time.html
Other helpful methods to test could be there. Try doing straight ruby to see if it's a problem with your rails setup or with ruby. You should be able to trace the specific place where this goes wrong.

Resources