Ruby Time.new giving time zone offset of 14 minutes - ruby

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.

Related

Ruby 2.3.1 Date.parse returns another date when separator is space char

Just got this today with my ruby console:
$ irb
2.3.1 :001 > require 'date'
=> true
2.3.1 :002 > Date.parse '30/08/2016'
=> #<Date: 2016-08-30 ((2457631j,0s,0n),+0s,2299161j)>
2.3.1 :003 > Date.parse '30 08 2016'
=> #<Date: 2016-09-30 ((2457662j,0s,0n),+0s,2299161j)>
2.3.1 :004 >
Separating with spaces (dates were formatted like this on a spreadsheet from work...dont ask why..hehe), it gave me a date one month after!!
What am I missing? Or shouldn't I expect a correct date, because I'm passing an invalid format anyway?
Use Date.strptime instead, it can take a template to parse the input
i.e.
Date.strptime('30 08 2016', '%d %m %Y')
=> #<Date: 2016-08-30 ((2457631j,0s,0n),+0s,2299161j)>
Just re-iterating my comments, it looks like Date.parse ignores the input after first space and just uses current month and year.
Date.parse '01 01 2015'
=> #<Date: 2016-10-01 ((2457663j,0s,0n),+0s,2299161j)>
Funnily enough spaces are fine if you spell the month.
Date.parse '01 jan 2015'
=> #<Date: 2015-01-01 ((2457024j,0s,0n),+0s,2299161j)>

Convert string datetime to Ruby datetime

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

I am trying to convert UTC datetime to a specific timezone in ruby

I have an XML file which has a datetime value. I loop through the elements and get the attribute value timeutc.
I managed to convert it to local time zone, but what I am trying to do is convert it to any time zone, PST, CST, EST.
$Appointments = '<appointments><appointment timeutc="2013-10-10T06:00:00" /><appointment timeutc="2013-10-10T06:00:00" /><appointment timeutc="2013-10-10T15:00:00" /></appointments>'
index = 0
doc = REXML::Document.new("#{$Appointments}")
doc.elements.each("appointments/appointment") do |element|
index += 1
value = element.attribute("timeutc").value
to_datetime = DateTime.parse(value).to_s
to_UTC = Time.iso8601(to_datetime).to_s
local_time = Time.iso8601(to_datetime).localtime
puts local_time # => 2013-10-09 23:00:00 -0700
puts local_time.strftime("%A") # => Wednesday
puts local_time.strftime("%B") # => October
puts local_time.strftime("%-d") # => 9
puts local_time.strftime("%l") # => 11
puts local_time.strftime("%M") # => 00
puts local_time.strftime("%p") # => PM
end
You could use the in_time_zone method:
For CST:
local_time.in_time_zone('Central Time (US & Canada)')
For PST:
local_time.in_time_zone('Pacific Time (US & Canada)')
For EST:
local_time.in_time_zone('Eastern Time (US & Canada)')
Ruby's support for time zones hasn't been that great (not sure if this has changed with 2.0), hence the various ActiveSupport libs.
Ruby looks to the environment variable TZ to determine what zone to operate in:
irb [1.9.3]$ ENV["TZ"] # Ruby will look elsewhere and see that I'm in NYC
=> nil
irb [1.9.3]$ Time.iso8601 "2013-10-10T06:00:00"
=> 2013-10-10 06:00:00 -0400
irb [1.9.3]$ ENV["TZ"]="America/Los_Angeles"
=> "America/Los_Angeles"
irb [1.9.3]$ Time.now.zone
=> "PDT"
irb [1.9.3]$ Time.iso8601 "2013-10-10T06:00:00"
=> 2013-10-10 06:00:00 -0700
So... while I'd strongly encourage using the active support methods, you could use something like this:
irb [1.9.3]$ def parse_in_zone(date, zone)
1{ old = ENV["TZ"]
1{ ENV["TZ"] = zone
1{ Time.iso8601 date
1{ ensure
1* ENV["TZ"] = old
1{ end
=> nil
irb [1.9.3]$ parse_in_zone "2013-10-10T06:00:00", "America/Los_Angeles"
=> 2013-10-10 06:00:00 -0700
irb [1.9.3]$ parse_in_zone "2013-10-10T06:00:00", "America/New_York"
=> 2013-10-10 06:00:00 -0400
Also note that DateTime.parse(value) is not necessary. It considers the string's zone when parsing the date:
irb [1.9.3]$ DateTime.parse("2013-10-10T06:00:00").zone
=> "+00:00"
irb [1.9.3]$ DateTime.parse("2013-10-10T06:00+04:00").zone
=> "+04:00"
irb [1.9.3]$ DateTime.parse("2013-10-10T06:00+07:00").zone
=> "+07:00"
Note that in your case I don't think the string: 2013-10-10T06:00:00 is a valid iso date/time (extra :00) but it looks like ruby doesn't care:
irb [1.9.3]$ DateTime.parse("2013-10-10T06:00:0000:000000").to_s
=> "2013-10-10T06:00:00+00:00"

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"

Rubygems Chronic cannot parse "2010-09-12 3:12pm" but can parse "2010-09-12 3pm" or "last monday 3:12pm"?

It seems strange that "2010--9-12 3:12pm" is a weak spot of Chronic Rubygem? Is there a way to make it work? (or another gem that can do it?) I also hope to find a parser that can handle 2010-09-12 3:12pm UTC or other timezones such as PDT, PST, or UTC+8 or -0700
irb(main):001:0> RUBY_VERSION
=> "1.8.7"
irb(main):002:0> require 'rubygems'
=> true
irb(main):003:0> require 'chronic'
=> true
irb(main):004:0> Chronic.parse('9/12/2010')
=> Sun Sep 12 12:00:00 -0700 2010
irb(main):005:0> Chronic.parse('9/12/2010 3pm')
=> Sun Sep 12 15:00:00 -0700 2010
irb(main):006:0> Chronic.parse('9/12/2010 3:12pm') # <-- cannot work
=> nil
irb(main):007:0> Chronic.parse('last monday 3:12pm')
=> Mon Sep 06 15:12:00 -0700 2010
irb(main):008:0> Chronic.parse('2010-09-12')
=> Sun Sep 12 12:00:00 -0700 2010
irb(main):009:0> Chronic.parse('2010-09-12 3:12pm') # <-- cannot work
=> nil
It works for me using latest Chronic on Github on Ruby 1.8.7 (2009-06-12 patchlevel 174):
>> RUBY_VERSION
=> "1.8.7"
>> require './chronic/lib/chronic'
=> true
>> Chronic.parse('9/12/2010 3:12pm')
=> Sun Sep 12 15:12:00 +0100 2010
>> Chronic.parse('2010-09-12 3:12pm')
=> Sun Sep 12 15:12:00 +0100 2010
In the test suite there are tests for:
time = parse_now("2006-08-20 7pm")
assert_equal Time.local(2006, 8, 20, 19), time
time = parse_now("2006-08-20 03:00")
assert_equal Time.local(2006, 8, 20, 3), time
But not exact match to your problem date(s). So if you have discovered a bug then it might be worth telling Chronic's author so that he can update the tests.
BTW... what do you get when you try:
require 'time'
puts Time.parse('2010-09-12 3:12pm')
Because I get the correct: Sun Sep 12 15:12:00 +0100 2010 (NB. I'm in day light saving time here). I mention this because I saw a ambiguous tweet this morning about problem with time API in a minor point release.
/I3az/

Resources