Convert string datetime to Ruby datetime - ruby

How do I convert this "2013-10-20 18:36:40" into a Ruby datetime?
I'm trying the following, but it's not working:
"2013-10-20 18:36:40".to_datetime
That's making it this and missing the time:
2013-10-20 00:00:00 UTC

Use DateTime::strptime:
require 'date'
DateTime.strptime("2013-10-20 18:36:40", "%Y-%m-%d %H:%M:%S")
#<DateTime: 2013-10-20T18:36:40+00:00 ((2456586j,67000s,0n),+0s,2299161j)>

You can do the following if rails is installed on your system:--
require 'active_support/core_ext/string/conversions'
"2013-10-20 18:36:40".to_time
1.9.2p320 :001 > require 'active_support/core_ext/string/conversions'
=> true
1.9.2p320 :003 > "2013-10-20 18:36:40".to_time
=> 2013-10-20 18:36:40 UTC

There is also DateTime#parse method:
2.1.0 :001 > require 'date'
=> true
2.1.0 :002 > DateTime.parse('2013-10-20 18:36:40')
=> #<DateTime: 2013-10-20T18:36:40+00:00 ((2456586j,67000s,0n),+0s,2299161j)>
If your work with rails consider writing timezone-safe code:
Time.zone.parse("2013-10-20 18:36:40")
http://www.elabs.se/blog/36-working-with-time-zones-in-ruby-on-rails

Related

How does using String#between? with DateTime objects work in Rails?

Using Ruby 2.3.2, Rails 5.0.0.1
In Ruby console
2.3.2 :001 > date_time_str = "2015-01-08 08:17:15 UTC"
=> "2015-01-08 08:17:15 UTC"
2.3.2 :002 > date_time_range_start = "2015-01-08 08:16:15 UTC"
=> "2015-01-08 08:16:15 UTC"
2.3.2 :003 > date_time_range_end = "2015-01-08 08:20:15 UTC"
=> "2015-01-08 08:20:15 UTC"
2.3.2 :008 > require 'date'
=> true
2.3.2 :009 > date_time_str.between?(DateTime.parse(date_time_range_start), DateTime.parse(date_time_range_end))
ArgumentError: comparison of String with DateTime failed
from (irb):9:in `between?'
from (irb):9
from /home/jignesh/.rvm/rubies/ruby-2.3.2/bin/irb:11:in `<main>'
I expected the above behaviour as I was attempting to compare a String instance with a DateTime instance. However when I attempt the same in rails console it returns expected result as shown below.
In Rails console
Loading development environment (Rails 5.0.0.1)
2.3.2 :001 > date_time_str = "2015-01-08 08:17:15 UTC"
=> "2015-01-08 08:17:15 UTC"
2.3.2 :002 > date_time_range_start = "2015-01-08 08:16:15 UTC"
=> "2015-01-08 08:16:15 UTC"
2.3.2 :003 > date_time_range_end = "2015-01-08 08:20:15 UTC"
=> "2015-01-08 08:20:15 UTC"
2.3.2 :004 > date_time_str.between?(DateTime.parse(date_time_range_start), DateTime.parse(date_time_range_end))
=> true
2.3.2 :005 > date_time_str_2 = "2015-01-08 08:21:15 UTC"
=> "2015-01-08 08:21:15 UTC"
2.3.2 :006 > date_time_str_2.between?(DateTime.parse(date_time_range_end), DateTime.parse(r_e))
=> false
Can anybody please help me understand what Rails does internally to make the above work?
String#<=> in ruby tries to compare itself to the other object. If the other object is incomparable (not a string), then the implementation for string specifically (c-source here) compares the other object to the receiving string.
In other words, "str" <=> obj is equivalent to
if obj.is_a?(String)
# compare bytes
elsif obj.respond_to?(:to_str)
obj = obj.to_str
# compare bytes
else
# a few safety checks
-1 * (obj <=> "str")
end
Now we have "str" <=> obj boiling down to obj <=> "str". So far this is just Ruby, no Rails. Since Datetime#<=> has no special handling for string, it returns nil and story ends here.
In Rails, they redefined Datetime#<=> and defined String#to_datetime

Oj Time dump - differences in linux and windows

I have a time stamp I am obtaining from an Access database. Unfortunately, the timestamp represents the time only, but is stored as 1899-12-30 13:05:00 +0000. The date part of it is in a different field. I need to preserve the data as much as possible while I am storing it in a json blob.
I am using Oj (which is wonderful) to dump the data to json. I have encountered the following behavior on the Windows platform:
irb(main):001:0> require 'oj'
=> true
irb(main):002:0> t = Time.new(1899,12,30,13,5,0) #this is my actual timestamp
=> 1899-12-30 13:05:00 +0000
irb(main):003:0> Oj.dump(t)
RangeError: bignum too big to convert into `long'
from (irb):3:in `dump'
from (irb):3
from C:/RailsInstaller/Ruby2.2.0/bin/irb:11:in `<main>'
irb(main):004:0>
Now, on linux:
2.3.0 :001 > require 'oj'
=> true
2.3.0 :002 > t = Time.new(1899,12,30,13,5,0)
=> 1899-12-30 13:05:00 +0000
2.3.0 :003 > Oj.dump(t)
=> "{\"^t\":-2209114500.000000000e0}"
I need to make this work on Windows because my source database is MS Access. Please help.
Time is not handled properly, but you can convert to float. The result string differ a bit from your original:
irb(main):001:0> require 'oj'
=> true
irb(main):002:0> t = Time.new(1899,12,30,13,5,0)
=> 1899-12-30 13:05:00 +0100
irb(main):003:0> Oj.dump(t)
RangeError: bignum too big to convert into `long'
from (irb):3:in `dump'
from (irb):3
from C:/Ruby23-x64/bin/irb.cmd:19:in `<main>'
irb(main):005:0> Oj.dump(t.to_f)
=> "-2209118100.0"
Or if you need the exact response you can use an array:
irb(main):001:0> require 'oj'
=> true
irb(main):002:0> t = Time.new(1899,12,30,13,5,0)
=> 1899-12-30 13:05:00 +0100
irb(main):012:0> A1 = Array.new(1)
=> [nil]
irb(main):017:0> A1[0] = '^t'
=> "^t"
irb(main):028:0> A1[1] = t.to_f
=> "-2209118100.0"
irb(main):035:0> Oj.dump(A1).tr("[","{").tr("]","}")
=> "{\"^t\",\"-2209118100.0\"}"

Converting date format from 04/08/13 to 2013-04-08 in ruby

$ irb
1.9.3-p429 :001 > require 'date'
=> true
1.9.3-p429 :002 > Date.strptime('04/08/13' , '%m/%d/%Y').strftime('%Y-%m-%d')
=> "0013-04-08"
For some reason, for the year, instead of 2013 it's showing 0013 ? :)
You have format with small mistake, it should be %m/%d/%y
Date.strptime('04/08/13', '%m/%d/%y').strftime('%Y-%m-%d') => "2013-04-08"

Ruby Time.new giving time zone offset of 14 minutes

When I create a time object in Ruby 1.9.2 with a date earlier than 1 September 1919, the time zone is set to +0014 rather than to the system zone (+0100) or UTC. Now that I discovered the problem being the early date, and since all I want is a time without a date, I will just use a recent date. But does anyone know why this happens?
ruby-1.9.2-p0 :034 > Time.new(1919,9,1,0,0,0)
=> 1919-09-01 00:46:24 +0100
ruby-1.9.2-p0 :035 > Time.new(1919,8,31,23,59,59)
=> 1919-08-31 23:59:59 +0014
ruby-1.9.2-p0 :036 > Time.new(1919,8,31,1,0,0)
=> 1919-08-31 01:00:00 +0014
Echoing what others are commenting on: there is no reproducible problem here with the information you have provided. On Windows 7, 64-bit:
irb(main):001:0> Time.new(1919,8,31,23,59,59)
#=> 1919-08-31 23:59:59 -0600
irb(main):002:0> RUBY_DESCRIPTION
#=> "ruby 1.9.2p180 (2011-02-18) [i386-mingw32]"
On Ubuntu 10.04, 32-bit:
ruby-1.9.2-p136 :001 > Time.new(1919,8,31,23,59,59)
#=> 1919-08-31 23:59:59 -0600
ruby-1.9.2-p136 :002 > RUBY_DESCRIPTION
#=> "ruby 1.9.2p136 (2010-12-25) [i686-linux]"
...and on your exact patch level:
ruby-1.9.2-p0 :001 > Time.new(1919,8,31,23,59,59)
#=> 1919-08-31 23:59:59 -0600
ruby-1.9.2-p0 :002 > RUBY_DESCRIPTION
#=> "ruby 1.9.2p0 (2010-08-18) [i686-linux]"
Please provide your OS version and bit-level for additional help.

replicate CSV.generate_line behaviour of ruby 1.8.7 in ruby 1.9.2

ruby 1.9 now uses fastercsv, but how do i replicate the generate_line behaviour of ruby 1.8.7 ?
ruby-1.8.7-p334 :010 > require 'csv'
=> true
ruby-1.8.7-p334 :010 > CSV.generate_line(["ab","cd"], "\t")
=> "ab\tcd"
ruby-1.9.2-p180 :002 > require 'csv'
=> true
ruby-1.9.2-p180 :007 > CSV.generate_line(["ab","cd"], :row_sep => ?\t)
=> "ab,cd\t"
Notice how \t is between the two array items in ruby 1.8.7 and at last in 1.9.2
You have to use col_sep instead. row_sep is the row separator:
CSV.generate_line(["ab","cd"], :col_sep => ?\t)
=> "ab\tcd\n"
or
CSV.generate_line(["ab","cd"], :col_sep => ?\t, :row_sep => '')
=> "ab\tcd"
You can find more details and additional options in the documentation.
CSV.generate_line(['a','b','c'],:col_sep=>"\t")

Resources