Rails Active Record TimeZones - ruby-on-rails

I have set the default time zone of my application to Pacific Time.
config.time_zone = 'Pacific Time (US & Canada)'
config.active_record.default_timezone = 'Pacific Time (US & Canada)'
The problem I am facing is that when I query in rails console..for example
Transaction.last
it returns an object like this
=> #<Transaction id: 4926, offer_id: 4926, date: "2014-10-08 04:23:03", reference: "CBRNCUQU", driver_id: 464, driver_type: "User", amount: 80.0, status: "paid", created_at: "2014-10-08 04:23:03", updated_at: "2014-10-07 22:15:27">
The date field shown here is date: "2014-10-08 04:23:03" which is in UTC and actually the date now in PDT is 2014-10-07
But if I query like this Transaction.last.date it returns
Tue, 07 Oct 2014 21:23:03 PDT -07:00
which is correct and expected output
The problem that I am facing is,I want to display the details of the current days transaction in my page and it returns a transaction with future date in my page.This might be happening because the DB saves the records in UTC
Is there any way that I could fix the issue.

As I can see from the api documentation http://apidock.com/rails/ActiveRecord/Base/default_timezone/class
default_timezone only accepts :local or :utc

Related

How set my timezone correctly to save a record correctly?

In my rails application I'm getting data and saving it by its date for all the records that has the today's date for a later call.
The problem is the data comes in this format "8:05 PM ET"
When I parse it to get it in the date format I get this:
"Mon, 24 Aug 2015 20:05:00 EDT -04:00"
,which is the right date. The thing is when I save it in the database is saved as
"2015-08-25 00:05:00 UTC"
When I request to the db give me all the data from today it doesn't retrieve this record because the date says that record is 25 "tomorrow"** and not **24 "today".
How can I save that record in my database as
today "24" and not as
tomorrow "25"?
My configuration:
application.rb
class Application < Rails::Application
Dir["#{Rails.root}/lib/**/**/*.rb"].each { |f| require f }
config.time_zone = 'Eastern Time (US & Canada)'.freeze
config.active_record.default_timezone = :local
config.active_record.raise_in_transactional_callbacks = true
end
and before save it:
string = '7:05 PM ET'
datetime = DateTime.now
Time.use_zone('Eastern Time (US & Canada)') do
datetime = Time.zone.parse(string)
end
baz.create(time: datetime, foo: 'bar')
when i try to acces it
baz.where(time:Date.today.to_time.beginning_of_day..Date.today.to_time.end_of_day)
In your database, dates are saved in UTC.
But, if you want to retrieve the dates in your own timezone format, you can specify your timezone in the config/application.rb filelike this:
config.time_zone = 'Eastern Time (US & Canada)'.freeze
Then, you can do:
time_now = DateTime.now
time_now_in_my_zone = time_now.in_time_zone(Rails.application.config.time_zone).to_datetime
See ActiveSupport::TimeWithZone
To keep things consistent and saving time in local timezone to database, this has to be set in application.rb
config.active_record.default_timezone = :local
Default timezone is :utc.
See Configuring Active Record for more options.
So, you can use config.active_record.default_timezone = :local setting to save the date in your local format and retrieve it in your format too, and keep things consistent. I think, this answers your question. Let me know if not!
Update
Change:
Time.use_zone('Eastern Time (US & Canada)') do
datetime = Time.zone.parse(string)
end
to:
datetime = Time.now.in_time_zone(Rails.application.config.time_zone).to_datetime
baz.create(time: datetime, foo: 'bar')
You might want to consider studying a little more about time zones.
in your case Mon, 24 Aug 2015 20:05:00 EDT -04:00 is the same date as 2015-08-25 00:05:00 UTC
UTC means the timezone +00:00
A shorter way to achieve that:
Set config.time_zone in your application.rb file.
Use Time.zone.now to save your records.
Example:
Setting 'Buenos Aires' timezone in a Rails application.rb file.
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
config.time_zone = 'Buenos Aires'
Then you can use this to store the properly Time:
Time.zone.now # => Mon, 24 Aug 2015 13:06:21 ART -03:00
If you want to know what time_zone do you need, you can run this: rake time:zones:all
Hope this help :)

`DateTime.strptime` mysteriously add one hour to the inputted time

I used Jquery datetime picker to pass time as text to the controllers:
Parameters: {"assignment"=>{"deadline"=>"08/29/2014 09:00"}}
In assignments_controller.rb, I parse the params as follow (my config.time_zone = "Eastern Time (US & Canada)":
#assignment.deadline = DateTime.strptime(params[:assignment][:deadline] + " Eastern Time (US & Canada)", "%m/%d/%Y %H:%M %Z").in_time_zone
But somehow, when #assignment.save, the following is recorded in database:
UPDATE "assignments" SET "deadline" = ? WHERE "assignments"."id" = 9 [["deadline", Fri, 29 Aug 2014 10:00:00 EDT -04:00]]
So, even though in params, deadline is 9 AM, in Active record it is 10. Why?
I think I figured it out: It's due to daylight saving time. The answer in this question lead to to create a helper method:
def parse_time_with_correct_zone(input_string)
input_format = "%m/%d/%Y %H:%M"
datetime_with_wrong_zone = DateTime.strptime(input_string, input_format)
correct_datetime = Time.zone.parse(datetime_with_wrong_zone.strftime('%Y-%m-%d %H:%M:%S'))
correct_datetime
end
Then I just use this method in controller instead of DateTime.strptime.

Make Rails ignore daylight saving time when displaying a date

I have a date stored in UTC in my Rails app and am trying to display it to a user who has "Eastern Time (US & Canada)" as their timezone. The problem is that rails keeps converting it to Eastern Daylight Time (EDT) so midnight is being displayed as 8am when it should be 7am. Is there anyway to prevent the DST conversion?
>> time = DateTime.parse("2013-08-26T00:00:00Z")
=> Mon, 26 Aug 2013 00:00:00 +0000
>> time.in_time_zone("Eastern Time (US & Canada)")
=> Sun, 25 Aug 2013 20:00:00 EDT -04:00
Update
I eventually went with a twist on #zeantsoi 's approach. I'm not a huge fan of adding too many rails helpers so I extended active support's TimeWithZone class.
class ActiveSupport::TimeWithZone
def no_dst
if self.dst?
self - 1.hour
else
self
end
end
end
Now I can do time.in_time_zone("Eastern Time (US & Canada)").no_dst
Create a helper that utilizes the dst? method on TimeZone to check whether the passed timezone is currently in DST. If it is, then subtract an hour from the supplied DateTime instance:
# helper function
module TimeConversion
def no_dst(datetime, timezone)
Time.zone = timezone
if Time.zone.now.dst?
return datetime - 1.hour
end
return datetime
end
end
Then, render the adjusted (or non-adjusted) time in your view:
# in your view
<%= no_dst(DateTime.parse("2013-08-26T00:00:00Z"), 'Eastern Time (US & Canada)') %>
#=> Sun, 25 Aug 2013 19:00:00 EDT -04:00

Rails timezone activerecord

My application.rb:
config.time_zone = 'Moscow'
config.time_zone = "(GMT+04:00) Moscow"
config.active_record.default_timezone = 'Moscow'
config.active_record.default_timezone = :local
When i run this commands, i get:
1.9.3-p362 :001 > Time.now
=> 2013-02-14 14:18:42 +0400
1.9.3-p362 :002 > Time.zone.now
=> Thu, 14 Feb 2013 10:18:52 UTC +00:00
So in db i see 10:18:52 UTC +00:00.
But what and how to configure, to see such time, as in Time.Now? (when i insert new row to db i must see time, as given by Time.now, what to configure?)
Server's time is Moscow....
also db is mysql
You can use local time like this:
> current_time = Time.now.utc
=> 2013-02-14 15:15:58 UTC
> current_time .localtime
=> 2013-02-14 10:15:58 -05 hours
You can use also:
Time.now.utc.in_time_zone("Moscow")
But for the answer to your question, the solution could be to set it like this:
config.time_zone = 'Moscow' (don't set this - delete this line)
config.active_record.default_timezone = :local
And also you can use your local time something like this:
Time.local_time
I hope some of this approaches might help you
In your application.rb include these lines:
config.time_zone = 'Moscow'
config.active_record.default_timezone = 'Moscow'
Now that you have set the time zone:
Time.now
=> 2013-02-14 11:14:46 +0000
Time.current
=> Thu, 14 Feb 2013 15:14:48 MSK +04:00
user = User.create(name: 'test')
=> #<User id: 6, name: "test", created_at: "2013-02-14 11:15:00", updated_at: "2013-02-14 11:15:00">
user.created_at
=> Thu, 14 Feb 2013 15:15:00 MSK +04:00
As you can see, despite the fact that rails stores the time as UCT +0000 (very clever btw), the rails interface is providing the required offset. If you call any object, such as user.created_at it will offset the database time to return the zone time.
It is very useful, because it allows the configuration of different time zones for different users. The time will be stored without offset, but each user will get its equivalent time zone.
Time.now return +00:00, doesn't matter your time zone.
Time.current is the same as Time.zone.now.

Convert DateTime String to UTC in rails

I have a string like this:
"2010-01-01 12:30:00"
I need that to convert to UTC from the current local time zone.
I tried this, but it seems to think that the string is already UTC.
"2010-01-01 12:30:00".to_datetime.in_time_zone("Central Time (US & Canada)")
=> Fri, 01 Jan 2010 06:30:00 CST -06:00
I am not sure where to go from here.
added this from my comment:
>> Time.zone = "Pacific Time (US & Canada)"
=> "Pacific Time (US & Canada)"
>> Time.parse("2010-10-27 00:00:00").getutc
=> Wed Oct 27 06:00:00 UTC 2010
>> Time.zone = "Mountain Time (US & Canada)"
=> "Mountain Time (US & Canada)"
>> Time.parse("2010-10-27 00:00:00").getutc
=> Wed Oct 27 06:00:00 UTC 2010
Thanks for any help.
Time.parse("2010-01-01 12:30:00").getutc
EDIT
(grinding teeth while thinking about the nightmare which is Ruby/Rails date/time handling)
OK, how about this:
Time.zone.parse("2010-01-01 12:30:00").utc
Note that Time.zone.parse returns a DateTime, while appending the .utc gives you a Time. There are differences, so beware.
Also, Time.zone is part of Rails (ActiveSupport), not Ruby. Just so you know.
In Rails 4 and above you can directly use in_time_zone
"2010-01-01 12:30:00".in_time_zone
#=> Fri, 01 Jan 2010 12:30:00 EST -05:00
"2010-01-01 12:30:00".in_time_zone.utc
#=> 2010-01-01 17:30:00 UTC
For APIs you can use:
utc_date = Time.parse("2013-05-31 00:00").utc.iso8601 #=> Result will be: 2013-05-30T21:00:00Z
You can check these articles:
Working with time zones in Ruby on Rails
ISO8601 - Dates In Ruby

Resources