Rails 3.1 time zone confused? - ruby-on-rails

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.

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

rails - Store DateTime objects in same time zone as timestamps

When i save a DateTime schedule_time to the DB, it saves according to my local time, but the timestamps (created_at) are saved apparently in UTC (7 hours ahead of my pacific time)
So if i submit the form setting my schedule_time for right now it will be 7 hours different than my created_at.
i need to show many users their times in their own selected zone, and i also need to compare times against each other, so i want all db entries to be in the same zone. Testing on my machine, my user has his zone saved as Pacific (-7:00), but its saving schedule_time in local time, not really UTC, so when i try to display the time back like this:
#item.schedule_time.in_time_zone(#user.time_zone)
it actually takes the stored datetime and subtracts seven hours from it giving me 7 hours before i wanted. i think the best thing is to just store all the datetimes in a uniform way so i can compare them easily.
changing this value config.time_zone = 'UTC' does nothing to change the stored format of my datetime. it stores in my local time regardless, while storing the timepstamps in real UTC.
ive also tried to reformat the datetime before storing it, with in_time_zone(#user.time_zone) but it had no effect on the stored time.
if i can just get schedule_time stored in UTC just like my timestamps are stored i could make this work! any ideas?
If you want to store schedule_time converted to UTC before storing it in the database, you can include a before_save callback in your Item model to convert it as follows:
before_save { |item| item.schedule_time = item.schedule_time.utc }
sorry i was totally on the wrong track.
the issue was with the jquery date picker i was using (will_pickdate). it returns a date and time but with a +0000 time zone offset. by default, the picker autofills with the current local time, but when i submitted that, rails basically thought it was receiving a time in UTC and added it as my local time but with +0000.
in order to store the date properly i have to keep the time and date from the picker intact, but just shift the +0000 part to something appropriate:
my_time.change(offset: user_time_zone_offset)

Rails application stores incorrect time in datetime field

Whenever I create a model, the two datetime fields are created (created_at and updated_at). Whenever I create a new instance of the object the times for those two fields are 5 hours ahead of my current time. I set config.time_zone = 'Central Time (US & Canada)' inside config/locales/application.rb but that doesn't help.
thanks,
mike
By design, active record always stores UTC dates in the database. These are converted into the timezone specified by Time.zone (which defaults to config.time_zone) when displayed to the user. Similarly if you had a date/time select in one of your forms then that time would be converted from Time.zone to UTC before storage in the database.
Assuming that DST is in effect where you're based then 5 hours ahead of your local time is UTC.

Rails ActiveRecord not converting time to UTC but saving unconverted time as UTC

I am using Rails 2.3.3 with Postgresql.
In my application environment.rb file I have set config.time_zone = 'UTC' and in my before_filter I set Time.zone = current_user.time_zone.
The problem I face is the Time that gets saved is in the users time_zone but gets saved as UTC in the database.
For example if I select 12:00 am IST (i.e +530 IST) it gets stored as 12:00 am UTC. However locally the configurations seem to work as expected and while fetching the data the time gets converted to the users time_zone so it gains 530 hours.
Would appreciate some help on this.
Thanks
Do you use time or datetime as the database column type for your object?
This recent (and very similar) question to yours could be resolved by changing the type from time to datetime.

Row based Time Zones in Rails 2.3.4

What is the best way to handle the following situation:
We have "admins" who create "events". These events can be nationwide, ie: different time zones. As of now there is a select menu with the current list of US time zones. There is a corresponding column in the database table, for the time zone selected. This is so the admin can select 5PM Eastern, 5PM Pacific, etc. Instead of trying to figure out the GMT equivalent.
The application is using UTC as per the environment.rb file, as the default time-zone.
If an admin selects "Eastern Time (US & Canada)", the date stamp selected is still saved as UTC (or the app default). I need to perform queries where events don't show up before the time selected above including the time zone.
Since the events need their own time zone, how should the data be saved?
I was originally thinking I need to trick Rails before it saves the value, so it saves UTC offset for the time zone.
This would be handled in before_save and after_find model methods. But it doesn't seem to work, or rather I am missing something..
You're missing a simple fact. Time is universal. 1:00pm in UTC is 1:00pm in UTC anywhere. You don't even need to store a time_zone with every event. You just need to let admins select it for easier time input. As far as backend, it's always in UTC. You can certainly input time from different timezone, and output into different timezone, but it's still the same "1:00pm in London" no matter how you twist it. So when a user is looking at events, you can simply do event_date < Time.now.utc (all past events).
However, if the observing user is actually in a different timezone from the events, and you want to display event dates in the user's home timezone, then you can let user select their home timezone, and store it in users table. Then in before_filter on your ApplicationController you can just do:
class ApplicationController < ActionController::Base
before_filter :set_time_zone
private
def set_time_zone
Time.zone = current_user.time_zone if current_user
end
end
Then every Time value that comes from database (such as event.date) will be automatically converted in the user's home time zone.
Or maybe I misunderstood the question. : ) Let me know.

Resources