Different date saved to database - wrong time zone - ruby-on-rails

When I fetch a date from FullCalendar with Javascript I have the following values:
Fri Sep 13 2013 08:30:33 GMT-0400 (EDT)
After I save that date to database I see that in database there are different values:
2013-09-13 12:00:00.000000
So, date is automatically converted to UTC and saved like that into database. How to save the correct date into database? I don't want to hardcode it :)
Thank you.

For that you need to define your time zone in your application.rb
config.time_zone = 'YOUR-TIME-ZONE'
config.active_record.default_timezone = :local
config.active_record.time_zone_aware_attributes = false

By default, the rails app timezone is UTC. Whenever the record is saved the date, datetime, time fields are saved with DB's timezone but when they are fetched back in models it is converted back to UTC.
So, in your case set your application timezone in application.rb like this
config.time_zone = 'Central Time (US & Canada)'
Now, whenever the records are fetched from database it will always be converted to CST timezone irrespective of DBs timezone.
Hope this will help.

Related

Convert particular timezone to UTC timezone

For example my local time_zone is Canada and i am getting date in Chennai timezone. How can I convert the Chennai timezone to UTC?
Using server time
You can call ActiveSupport::TimeWithZone#utc on the result.
Example:
Time.zone.now.utc
Keep in mind that .now is using the server time zone when config.time_zone is set.
When you receive a time
If you are getting the datetime in Chennai timezone it will probably look like this: 2019-11-26T12:20:00.655+05:30
To convert it in different time zone, use:
time = Time.parse("2019-11-26T12:20:00.655+05:30")
pacific_time = time.in_time_zone("Pacific Time (US & Canada)")
# and then UTC if you want
pacific_time.utc

While storing time mysql database it is converting the time

I want to store the date and time in mysql2 database,the time which I want to store is in GMT zone, but after saving the time is getting converted in other zone,
Can any one tell how to change the mysql2 timezone.
You need to set global time zone in mysql. Use following link command to set it to gmt:
SET GLOBAL time_zone = timezone;
If the issue is specific to Rails, set the default time zone in your configuration:
Application.rb
config.time_zone = 'Eastern Time (US & Canada)'
A number of ways:
start the server with the '--timzeone' paramter, in this case, it would be --timezone=UTC.
You can set the TZ environment variable.
Start the server with the --default-global-timezone paramter, set to UTC.
At the start of every connection, issue a SET time_zone = GMT.

How to set the timezone to EST throughout the rails app?

I want to use EST throughout the app. I have set the
config.time_zone = 'Eastern Time (US & Canada)'
config.active_record.default_timezone = 'Eastern Time (US & Canada)'
what I want is, I have to get all the time I have used like "DateTime.now" and it now returns time in my local timezone but I want it to return date time in EST. Also I have date time range picker and I get the start date and end date and parse the string to time using
(params[:start_date]).to_time
which also returns the date time in local zone and instead i want all those to return in EST. How can I do this? Any help is appreciated.
Thanks in advance.
DateTime.now and Time.now doesn't respect Time.zone and will always use the server time. If the machine you're using is set to a different timezone, these 2 will use that timezone.
to_time on the other hand defaults to local timezone as mentioned in apidock (although just tried this out and I get utc by default). To get these times in the timezone set, append in_time_zone
DateTime.now.in_time_zone
Time.now.in_time_zone
string.to_time.in_time_zone
There are some shortcuts for these though. The following code will return the timestamps in the current timezone
Time.zone.now
Time.zone.parse(string)
Normally, in database date-time would be saved in UTC format unless you have selected a specific TimeZone for Active Record and it would be easier if you have to meddle with multiple TimeZones. But, while you access the values you will get the values in you selected TimeZone.
config.time_zone = 'Eastern Time (US & Canada)
Now, suppose you have a datetime value in UTC from table as
datetime1 = "2014-08-25 10:25:57 +0000"
You can convert it to the selected timezone 'Eastern Time (US & Canada)' as below,
Time.zone.parse(datetime1) => Mon, 25 Aug 2014 06:25:57 EDT -04:00
Then, if you need it in a proper format, use method strftime.
Time.zone.parse("2014-08-25 10:25:57 +0000").strftime("%d-%m-%Y %H:%M:%S") => "25-08-2014 06:25:57"
Hoep it helps :)

Rails4: Saving and displaying date in user's timezone

I am working on a rail4 app. Where I want to store dates in all mysql tables in UTC. However I store user's timezone in a specific table, called users. When user logs in, I get user's timezone form user table and save in session.
I am able to save date in all tables in UTC as default value of config.time_zone is UTC for activerecords and activemodels. But while displaying I want to show dates in user's timezone. As well as, when any user inputs a date/time in any html form, then I want to save it in the equivalent UTC format.
What is the best way to achieve this?
Rails, activerecord and MySQL will save all the timestamp fields in UTC. Without you having to do anything.
In your application.rb file where the configuration of the Application is done, you define the default time zone if you want the display of timestamps to take place on time zone different from UTC.
Hence
config.time_zone = 'Central Time (US & Canada)'
will display the timestamp fields (without you having to do anything special in other piece of code) using the Central Time.
When you want each of your users to have timestamps displayed in different time zone you can store the time zone in a column along side the user data. The column can be called time_zone and can contain the string of the user preferred time zone.
But, you have to tell the timestamp object to display itself to the specific timezone. This is done with the help of the method in_time_zone(timezone) that DateTime object responds to.
Example (when the default time zone is UTC):
1.9.3-p194 :004 > d = DateTime.new(2012, 9, 1, 6, 30, 0)
=> Sat, 01 Sep 2012 06:30:00 +0000
1.9.3-p194 :005 > d.in_time_zone("Central Time (US & Canada)")
=> Sat, 01 Sep 2012 01:30:00 CDT -05:00
Or you can change the time zone globally for the request at hand on a before or around filter. There is a documentation on internet if you do a google on that.
Read also this one: http://api.rubyonrails.org/classes/ActiveSupport/TimeWithZone.html
for various alternatives to approach the problem.
You could store the time in UTC, and store the timezone separately. Timezones are commonly stored as a UTC-offset in seconds (seconds are the SI unit of time).
Then you can display it like so:
utime = Time.now.utc.to_i # this value can be any format that Time.at can understand. In this example I'll use a unix timestamp in UTC. Chances are any time format you store in your DB will work.
=> 1375944780
time = Time.at(utime) # parses the time value (by default, the local timezone is set, e.g. UTC+08:00)
=> 2013-08-08 14:53:00 +0800
time_in_brisbane = time.in_time_zone(ActiveSupport::TimeZone[36000]) # sets the timezone, in this case to UTC+10:00 (see http://stackoverflow.com/a/942865/72176)
=> Thu, 08 Aug 2013 16:53:00 EST +10:00
time_brisbane.strftime("%d %b %Y, %l:%M %p %z") # format with strftime however you like!
=> "08 Aug 2013, 4:53 PM +1000"

Why doesn't `config.time_zone` seem to do anything?

In application.rb, it says:
Set Time.zone default to the specified zone and make Active Record
auto-convert to this zone.
Run "rake -D time" for a list of tasks for finding time zone names.
Default is UTC.
But setting config.time_zone = 'Central Time (US & Canada)' or config.time_zone = 'Eastern Time (US & Canada)' has no effect - the created_at field in a model is stil being saved in UTC.
According to this railsforum answer:
config.time_zone just lets rails know
that your server is set to this
timezone so when it writes dates to
the database it can properly convert
it to UTC.
If that is true, then why is it that when my system time is Pacific Time (US & Canada) and config.time_zone = 'Central Time (US & Canada)' or config.time_zone = 'Eastern Time (US & Canada)', that the created_at time is the correct UTC? Should it not be incorrect?!
Because, if the PST time is 8 PM, then EST is 11 PM and UTC is 4 AM.
Presuming that Rails does Time.now, that would be 8 PM. And we told Rails that the server is in EST. So, 8 PM would be EST time as far as Rails is concerned and the UTC would then be 5 AM UTC, which would be incorrect (because the actual time is 8 PM PST/11 PM EST, which is 4 AM UTC)
What's going on here?
Here's a list of concepts and things that may help you:
config.time_zone doesn't set "Server Time", that is controlled by your operating system usually.
Rails always stores your dates in UTC in the database (unless you change a different setting).
Time.now returns the localtime for your computer in your timezone and it also includes the local timezone offset from your operating system, which means Ruby and therefore Rails knows how to convert localtime into UTC. You can try this by using irb directly, so no Rails libraries are loaded:
ctcherry$ irb
>> Time.now
=> Mon Feb 21 20:53:14 -0800 2011
>>
If config.time_zone, or Time.zone is set, to lets say EST, Rails expects that if you set a datetime attribute that you mean for that time and date to be in specified timezone, in this case EST. This is why you set Time.zone equal to your end users timezone, so they can use their local time and dates, and you can pass them directly into your ActiveRecord models and Rails can convert it to UTC for storage in the database.
Does that help at all?
You need to use in_time_zone (i.e. Time.now.in_time_zone) to get some something other than UTC.

Resources