Rails/ruby transform string to UTC - ruby-on-rails

I'm currently doing:
DateTime::strptime('12/11/17', "%d/%m/%Y") => Fri, 12 Nov 0017 00:00:00 +0000
But I want Mon, 11 Dec 2017 00:00:00 UTC +00:00
Thanks in advance

The following snipped should do what you are looking for (using ruby 2.3):
DateTime::strptime('12/11/17', "%m/%d/%y").strftime("%a, %d %b %Y %H:%M:%S UTC %Z")
#=> "Mon, 11 Dec 2017 00:00:00 UTC +00:00"

Related

Why my DateTime format changed on Bamboo build

I have a User class that has_many Jobs. I map jobs with the following code, the start_at and end_at are datetime:
def ranges
user.jobs.map { |u| [u.start_at, u.end_at] }
end
I have a spec that compares two arrays:
my_array = [[start1, end1], [start2, end2]]
expect(ranges).to eq my_array
The test data are also datetime created from factory girl e.g.
create(:jobs, start_at:DateTime.parse('2017-03-26 00:00:00'), end_at: DateTime.parse('2017-03-27 00:00:00'))
Everything works fine, expect when Bamboo runs my spec, I get following error:
expect
[[2017-12-31 00:00:00.000000000 +0000, 2017-12-31 10:10:00.000000000 +0000], [2017-12-30 00:00:00.000000000 +0000, 2017-12-31 00:10:00.000000000 +0000], [2017-11-26 00:00:00.000000000 +0000, 2017-11-26 10:10:00.000000000 +0000], [2017-03-24 00:00:00.000000000 +0000, 2017-03-24 10:10:00.000000000 +0000], [2017-03-25 00:00:00.000000000 +0000, 2017-03-25 10:10:00.000000000 +0000], [2017-03-26 00:00:00.000000000 +0000, 2017-03-26 10:10:00.000000000 +0000]]
to match
[[Sun, 26 Mar 2017 00:00:00 UTC +00:00, Sun, 26 Mar 2017 10:10:00 UTC +00:00], [Sat, 25 Mar 2017 00:00:00 UTC +00:00, Sat, 25 Mar 2017 10:10:00 UTC +00:00], [Fri, 24 Mar 2017 00:00:00 UTC +00:00, Fri, 24 Mar 2017 10:10:00 UTC +00:00], [Sun, 26 Nov 2017 00:00:00 UTC +00:00, Sun, 26 Nov 2017 10:10:00 UTC +00:00], [Sat, 30 Dec 2017 00:00:00 UTC +00:00, Sun, 31 Dec 2017 00:10:00 UTC +00:00], [Sun, 31 Dec 2017 00:00:00 UTC +00:00, Sun, 31 Dec 2017 10:10:00 UTC +00:00]]
dose this mean I need to format all my datetime object byiso8601 all the time? what could cause this on Bamboo
The problem isn't your format. The problem is that the array elements are not in the same order. The dates in your expect array begin with the 2017-12-31 dates, while those in your match array begin with the 2017-03-26 dates.
RSpec's eq method returns true only if each element of the first array is identical to the element at the same index of the second array. But the match_array method returns true so long as the two arrays have the same elements, regardless of order.
Change your expectation line to:
expect(ranges).to match_array(my_array)
And you should be good to go.

Include 'UTC` in datetime

One of my assertions is failing because of this slight niggle:
its(:register_token_created_at){ should eq DateTime.now.utc }
results in:
expected: Fri, 28 Mar 2014 00:06:33 +0000
got: Fri, 28 Mar 2014 00:06:33 UTC +00:00
So how should I change DateTime.now.utc for it to pass?
I'm assuming that you have your test environment with the following configuration:
yourapp/config/environments/test.rb
#config.time_zone = "whatever"
config.active_record.default_timezone = :utc
Then, you can replace:
DateTime.now.utc #Fri, 28 Mar 2014 00:54:28 +0000
With:
Time.zone.now #Fri, 28 Mar 2014 00:54:51 UTC +00:00
That works for me...
Another (ugly) solution can be:
DateTime.now.utc.strftime("%a, %m %b %Y %H:%M:%S UTC %:z") #"Fri, 03 Mar 2014 00:55:46 UTC +00:00"
And then, you can compare as strings

Calculations on datetime range

I have a problem with calculation on datetime fields.
I have two variables:
a = Sat, 01 Feb 2014 13:00:00 CET +01:00
and
b = Fri, 28 Feb 2014 13:00:00 CET +01:00
And I want to calculate how many days passed from a to b range.
Please Help.
You can use this.
require 'date'
( Date.parse('Fri, 28 Feb 2014 13:00:00 CET +01:00') - Date.parse('Sat, 01 Feb 2014 13:00:00 CET +01:00')).to_i
=> 27
i.e
( Date.parse(b) - Date.parse(a)).to_i
require 'date'
a=Date.parse('Sat, 01 Feb 2014 13:00:00 CET +01:00')
=> #<Date: 2014-02-01 (4913379/2,0,2299161)>
b=Date.parse('Fri, 28 Feb 2014 13:00:00 CET +01:00')
=> #<Date: 2014-02-28 (4913433/2,0,2299161)>
b-a
=> (27/1)
(b-a).to_i
=> 27
You can also use time_diff gem to calculate the difference.
In your gem file add gem 'time_diff'
I have added the code in index.html.erb but, you can use it any where you want.
take a look on following code.
<% require 'time_diff' %>
<% a = Time.diff(Time.parse('Sat, 01 Feb 2014 13:00:00 CET +01:00'), Time.parse('Fri, 28 Feb 2014 13:00:00 CET +01:00'), "%d") %>
<%= a[:diff] %>
and I got the following result
"27 days"
You can also take a look on
https://github.com/abhidsm/time_diff

How do get a random DateTime rounded to beginning of hour in Rails?

Basically I'd like to get a random datetime within the last year:
rand(1.year).ago #=> Sun, 22 Sep 2013 18:37:44 UTC +00:00 (example)
But how do I go about specifying or limiting this to times on the hour? For example:
Sun, 22 Sep 2013 18:00:00 UTC +00:00
Sat, 02 Nov 2013 10:00:00 UTC +00:00
Fri, 12 Apr 2013 21:00:00 UTC +00:00
I finally found what I was looking for. #Stoic's answer is very good but I found this available method (http://api.rubyonrails.org/classes/DateTime.html):
rand(1.year).ago.beginning_of_hour
Does exactly the same thing but looks neater and prevents you from having to write your own function.
Rounding datetime to the nearest hour in Rails would be
(DateTime.now + 30.minutes).beginning_of_hour
Not the answer to the actual question, but it does answer the title of the question (which is how i got here).
Try this:
def random_time_to_nearest_hour
time = rand(1.year).ago
time - time.sec - 60 * time.min
end
Examples:
[1] pry(main)> random_time_to_nearest_hour
=> Sun, 28 Apr 2013 16:00:00 UTC +00:00
[2] pry(main)> random_time_to_nearest_hour
=> Sat, 08 Jun 2013 15:00:00 UTC +00:00
[3] pry(main)> random_time_to_nearest_hour
=> Thu, 22 Aug 2013 23:00:00 UTC +00:00
[4] pry(main)> random_time_to_nearest_hour
=> Tue, 29 Jan 2013 14:00:00 UTC +00:00
[5] pry(main)> random_time_to_nearest_hour
=> Tue, 13 Aug 2013 06:00:00 UTC +00:00
[6] pry(main)> random_time_to_nearest_hour
=> Mon, 03 Jun 2013 08:00:00 UTC +00:00
[7] pry(main)>
Note that, this method will always floor down to the nearest hour, but since you are anyways generating a random time, it wont matter if this time is getting floor'ed down or getting round'ed. :)

In Rails, what's the nicest way to create a specific time (not now) in a particular time zone?

Here's one way, but can you think of a more idiomatic way?
>> Time.use_zone('Sydney'){ Time.zone.parse('2011-04-12 2pm') }
=> Tue, 12 Apr 2011 14:00:00 EST +10:00
I think you're looking for
Time.find_zone('Alaska').local(2011,1,1)
=> Sat, 01 Jan 2011 00:00:00 AKST -09:00
Time.find_zone('Amsterdam').local(2011,1,1)
=> Sat, 01 Jan 2011 00:00:00 CET +01:00
Time.find_zone('Sydney').local(2011,1,1)
=> Sat, 01 Jan 2011 00:00:00 EST +11:00
Time.find_zone('Wellington').local(2011,1,1)
=> Sat, 01 Jan 2011 00:00:00 NZDT +13:00
This also works with parse
Time.find_zone('Sydney').parse('2011-04-12 2pm')
=> Tue, 12 Apr 2011 14:00:00 EST +10:00
For parsing a date within a specific time zone, you can use ActiveSupport::TimeZone
> ActiveSupport::TimeZone["Sydney"].parse("2011-04-12 2pm")
=> Tue, 12 Apr 2011 14:00:00 EST 10:00
TimeZone API documentation is here:
http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html#method-c-5B-5D
This is what I use:
Time.zone.local(2011, 4, 12, 14, 0)
As said above, to create a time in a specific timezone (e.g., 4/10/2014 1:30pm New York):
#event.start_time = Time.find_zone('Eastern Time (US & Canada)').local(2014,4,10,13,30)
=> Thu, 10 Apr 2014 13:30:00 EDT -04:00
#event.start_time.utc
=> 2014-04-10 17:30:00 UTC
When it is saved to your db, it will be converted to UTC (in Postgres at least if using a timestamp type in your migration), and on future access it will be displayed relative to the application timezone set in config/application.rb
To properly display the local time, we also store the timezone name (e.g., 'Eastern Time (US & Canada)' ) in our database. So, when we want to print the time in our views, we do...
#event.start_time.in_time_zone(#event.timezone)
=> Thu, 10 Apr 2014 13:30:00 EDT -04:00
To get the abbreviated timezone (e.g., EST)
#event.start_time.in_time_zone(#event.timezone).zone
=> "EDT"
How about using the *in_time_zone* helper..
Time.now.in_time_zone('Sydney')

Resources