Rails + PostgreSQL: How to query timezone info along with time - ruby-on-rails

I'm using Rails4 and PostgreSQL v9.6.2, my problem is that I want to process datetimes in Rails in the timezone that it was entered, it gets stored properly in PostreSQL but when I retrieve it with Rails the timezone info gets lost.
I'm using a timestamp with time zone in PostgreSQL and datetime in Rails. For example, while on PostgreSQL I see 2012-10-26 19:26:00+02, on Rails I'm getting Fri, 26 Oct 2012 17:26:00 UTC +00:00, which is technically the same date, but on UTC, or without the original timezone. I'd want to get, from Rails, the timezone info stored on PostgreSQL.

From Postgres manual:
For timestamp with time zone, the internally stored value is always in
UTC (Universal Coordinated Time, traditionally known as Greenwich Mean
Time, GMT). An input value that has an explicit time zone specified is
converted to UTC using the appropriate offset for that time zone. If
no time zone is stated in the input string, then it is assumed to be
in the time zone indicated by the system's TimeZone parameter, and is
converted to UTC using the offset for the timezone zone.
When a timestamp with time zone value is output, it is always
converted from UTC to the current timezone zone, and displayed as
local time in that zone. To see the time in another time zone, either
change timezone or use the AT TIME ZONE construct
You can override current time zone on a session level using:
SET TIME ZONE timezone;
where timezone your desired time zone.

Related

Rails, Postgres and Timezone

I have table which have a datetime field named date. When doing a POST in order to insert a new row, the date sent from the client (browser) looks like 2015-11-20T14:30:00+10:00 which is actually a correct date and timezone.
However, inside Postgres this date has been inserted as 2015-11-20 04:30:00.000000, which as you can see, is not at all the same as above. I know the problem is related to the timezone. But I cannot seems to figure out a fix.
For information, I have configured my app timezone :
class Application < Rails::Application
config.time_zone = 'Brisbane'
end
Ideas?
2015-11-20T14:30:00+10:00 means that the local time of 14:30 is 10 hours ahead of UTC. Your database field reflects the correct UTC value of 04:30. This is often the desired behavior, especially if the value represent a timestamp - the date and time something occured (past tense).
In PostgreSQL, there are two different types of timestamp fields (reference)
The TIMESTAMP WITH TIME ZONE field accepts an input that contains a time zone offset. It then converts the value to UTC for storage. On retrieval, it uses the session's timezone setting.
The TIMESTAMP, or TIMESTAMP WITHOUT TIME ZONE simply stores the date and time given, ignoring any offset, and not converting to UTC.
Most of the time, you should indeed use TIMESTAMP WITH TIME ZONE. You should only use TIMESTAMP WITHOUT TIME ZONE if you need to retain the local date and time value, such as in scheduling of future events and calculation of business hours. And for those scenarios, it often makes more sense to split date and time into separate DATE and TIME fields.
One last thing - if you can avoid it, avoid using Rails time zones and use standard tzdb zones. "Australia/Brisbane" is the full tzdb identifier equivalent to the Rails "Brisbane" time zone. Refer to the section on Rails time zones at the bottom of the timezone tag wiki.
I found this gem to be incredibly useful and easy for correctly setting the time https://github.com/kbaum/browser-timezone-rails

One time zone to another time zone conversion

How to convert one time zone value to another time zone value using <s:date>
For example I would like to convert
CTS to GMT+05:30(or IST) using <s:date> tag
In my database I have added date and user time zone value with respect to GMT.
my data base server is showing time zone CTS(I am unalbe to chage it).
Here I would like to convert date from CTS time zone to user time zone that is GMT+05:30(or IST) or users time zone stored in database
For Indian Standard Time, this is the way:
<s:date name = "yourDate"
format = "dd/MM/yyyy HH:mm:ss a"
timezone = "GMT+05:30" />
In the comments to this related question, you can read about common mistakes you might encounter when dealing with this.
A Date has no TimeZone. A date is just a number of milliseconds since a specific point in time (EPOCH: 01-01-1970, 00:00:00 UTC).
When you save a Date into a database, you are just saving that Long number. If your database has a specific TimeZone, it means that when you will run a query on it, it will format the Dates for human representation with that TimeZone. There are TimeZone settings in your DB, in your AS, in your framework too. But through the whole chain, the Date remains always the same Date object, just represented differently.
Many databases allows you to save the TimeZone informations along with the date. But since you said:
In my database I have added date and user time zone value with respect to GMT.
Then you can absolutely ignore the fact that
my data base server is showing time zone CTS
Just take that Date, and format it with your desired TimeZone, with the code provided.
If this is just confusing you (taking GMT dates, shown as CTS in your DB visualizer, and shown as IST in the browser), then log-print that Date three times in the Action using the three different TimeZones, to have a match between the whole chain, that will help you debugging where the conversions are applied and how.

Force time to be stored without localization?

We are building a Rails application that needs to read data from a database that was created, and is used, by another application that I have no control over.
The other application stores all of its time information in a UTC time field but forces local time to be stored there.
Example:
current time: 2014-04-15 11:36:54 -0600
current time in UTC: 2014-04-15 17:36:54 UTC
time stored in db: 2014-04-15 11:36:54 UTC
My problem is that Rails wants to convert the local time to UTC when it stores the time.
Is there any way I can tell Rails to not change my times to UTC when it stores them?
update:
So what a guess my real question is how can I store local time in the database but still have UTC in my models?
If you set
ActiveRecord::Base.default_timezone = :local
Then it should use the local timezone (as set by the TZ environment variable etc.). It's up to you to manage the local timezone and to take care of any oddities due to the timezone changing (eg if you observe daylight savings time)

Ruby on Rails timezone

My server is in US, rails default timezone is set to 'UTC', a user from India submits the form,Will rails convert that user's time zone from India to UTC and save it in created_at column or it will save the UTC current time?
It will save the current time in UTC. Created_at and updated_at are Active Records internal timestamp columns, and as such they are never user input.
Also, basic security protocol dictates that you should never use the client's time settings, always the servers.
Rails will do one thing though - it will use the webserver's current time in UTC and store it in the database instead of the database servers current time.
By default, times are stored in UTC + offset format. When you specify the default timezone as lets say "Mumbai" it will return the datetime objects converted for that timezone.
You can also do:
Time.zone.parse(#post.created_at.zone)

Rails 3.1 time zone confused?

Here is my current situation:
I have a user class that has an attribute time zone.
When the user creates a Lecture with start_time (3pm) and end_time (5pm), I want to ensure that in the database the start_time and end_time are actually 3pm and 5pm, in the user's time zone.
In my application controller I'm doing the following:
def set_timezone
if current_user
Time.zone = current_user.time_zone or "Eastern Time (US & Canada)"
end
end
When the above lecture is saved to the database it seems to add 4 hours. Is it converting it back to UTC? The odd thing is that when I display the time in the view it is correct (I'm guessing it's converted from the UTC time back to the EST time).
I want it so that that if a user selects 4pm it is saved in the database as 4pm AND when I display that time in the view it is 4pm. What am I currently doing wrong?
EDIT: it appears that rails also converts all times to UTC when storing them in the database. Which is ok until I do a query that involves time (I'll have to manually convert it to UTC).
MySQL also has a time zone.
Notably (emphasis mine):
The current session time zone setting affects display and storage of time values that are zone-sensitive. This includes the values displayed by functions such as NOW() or CURTIME(), and values stored in and retrieved from TIMESTAMP columns. Values for TIMESTAMP columns are converted from the current time zone to UTC for storage, and from UTC to the current time zone for retrieval.
Whether or not it's worth doing anything about it... not sure. I'm skeptical.

Resources