How do I keep the time, but change the time zone? - ruby-on-rails

I've looked at a few StackOverflow questions but none of them seem to crack the case.
My time for example is :
2012-04-19 08:42:00 +0200
This is what is inputed through the form. But everything is displayed relative to what timezone it is in. So because the computer works in UTC, this time after it is saved comes out as :
Wed, 18 Apr 2012 23:42:00 PDT -07:00
How do I keep the same time, but just change the zone?

I think the method Time.use_zone might help you. In the app I'm working one we wanted times to be interpreted according to the current user's time zone. Our User class was given a time_zone attribute, which is just a valid ActiveSupport::TimeZone string, and we created an around_filter as follows:
class ApplicationController < ActionController::Base
around_filter :activate_user_time_zone
def activate_user_time_zone
return yield unless current_user # nothing to do if no user logged in
return yield unless current_user.time_zone && ActiveSupport::TimeZone[current_user.time_zone] # nothing to do if no user zone or zone is incorrect
Time.use_zone(ActiveSupport::TimeZone[current_user.time_zone]) do
yield
end
end
end
Basically, this will execute the code in the controller action as if it was in the current user's time zone.

I have same requirement. Please check this and this link also
Alternatively
"2012-04-19 08:42:00 +0200".to_time.strftime("%c").to_datetime

Related

From where Rails take their DateTime.now?

Recently I wanted to change updated_at column of a post, but it's not that simple!
Nevertheless, server time is 12:06 and when I use console (irb) it is 12:06
Also tried:
irb(main):001:0> Time.zone.to_s
=> "(GMT+03:00) Moscow"
Still when I do :
post.update!(updated_at: DateTime.now)
=> true
And if I retrieve the record, the result is "2018-10-29 09:06:47"
Any help is appreciated!
Try using DateTime.current - that will get the zoned time if your app is operating in one.
From the docs:
Returns Time.zone.now.to_datetime when Time.zone or config.time_zone are set, otherwise returns Time.now.to_datetime.
Basically, Time.zone should reflect DateTime.current if you're working with a time zone, while Time.now and DateTime.now will ignore any zone. The method's source is quite self explanatory here:
def current
::Time.zone ? ::Time.zone.now.to_datetime : ::Time.now.to_datetime
end
Hope that helps - give me a shout if you've any questions.

Rails Twitter created_at TimeZone

Never dealt with timezones before. Haven't heard pleasant things.
I am pulling Tweets from a Twitter account to post on an application. I am using the following line of code to display the date as follows: November 26th, 2015.
<%= Date::MONTHNAMES[tweet.created_at.month] %> <%= tweet.created_at.day.ordinalize %>, <%= tweet.created_at.year %>
However, the time is displayed as +0600 further into time than my current location. I am located in Canada/US Central which is -0600. All my local records are correct (both in time and timezone), but I assume this is different because I am pulling it from a non-local source.
2015-11-27 03:07:04 +0000 is the date displayed from the created_at property of the tweet.
I am wanting to change the tweet's time so that is correct for my timezone at minimum, if not too hard to do I'd prefer it to be compatible with all timezones.
You can use in_time_zone method to convert the time to your desired timezone:
created_at = '2015-11-27 03:07:04 +0000'
created_at.in_time_zone('Central Time (US & Canada)')
# => Thu, 26 Nov 2015 21:07:04 CST -06:00
ActiveRecord keeps track of time zones and stores all times as UTC in the database. In you're code you're retrieving that time from the database, but using a very non-standard way to output it which is bypassing ActiveRecord's time zone conversion.
you can try this
tweet_time = tweet.created_at.in_time_zone
tweet_time.strftime("#{tweet_time.day.ordinalize} %B, %Y")
to get the time in your server's timezone, which can be configured in config/application.rb
have a look here and here for more information on working with time zones
In order to get each user to see the time in their own zone you need to capture each user's timezone, then can do this in your action controller
around_filter :user_time_zone, :if => :current_user
def user_time_zone(&block)
Time.use_zone(current_user.time_zone, &block)
end

Rails - Getting datetime_select into user timezone for model validation

I tried to get this answered with no luck so I'll try again.
I've implemented the railcast timezone goodies to allow the user to set their time zone. It works. Time.zone.now gives the correct time zone. It's in here
http://stevenyue.com/2013/03/23/date-time-datetime-in-ruby-and-rails/
I have events and have been trying to get the datetime_select in my form to give me a time that is also in the user's time zone.
My goal is to be able to compare it to current time (Time.zone.now) to validate that the start time is not before current time. And eventually end time > start time etc.
I've tired several ways including this one with no luck...
This one - he answered his own question later (is exactly my problem)
Rails datetime_select posting my current time in UTC
def start_date_cannot_be_in_the_past
if date_start.in_time_zone(Time.zone) < Time.zone.now
errors.add(:date_start, "has already passed")
end
end
The above doesn't seem to work because you can't extract date_start just like that. It's separated into different components, so I tried to do something like this
def start_date_cannot_be_in_the_past
date = DateTime.new(params[event][date_start(1i)].to_i, params[event][date_start(2i)].to_i, params[event][date_start(3i)].to_i, params[event][date_start(4i)].to_i, params[event][date_start(5i)].to_i)
if date.in_time_zone < Time.zone.now
errors.add(:date_start, "has already passed")
end
end
In my model I can't access params so I don't know how to get this to work...
I want to move to a jquery calendar/time picker if possible as I can't seem to get this work.. but any suggestions on alternatives or on this is appreciated..
Make sure you have this line in your model:
validate :start_date_cannot_be_in_the_past
and then this method can be something like:
private
def start_date_cannot_be_in_the_past
errors.add(:date_start, "has already passed") if self.date_start < Time.zone.now
end
See this for more information.

How to change Rails app time zone setting based on user's input?

I have a User model, which allow user to provide their own time zone. User can choose their own time zone using the time_zone_select. So we will store something like Pacific Time (US & Canada) in database.
My Rails 3 application default setting is using Pacific Time (US & Canada). So all the time display is in this time zone.
May I change the time time display based on user time zone? For example, User A will see all the time displayed in his time zone Central Time (US & Canada), and User B will see all the time in London.
Thanks all.
In controllers/application.rb
before_filter :set_user_time_zone
private
def set_user_time_zone
Time.zone = current_user.time_zone if logged_in?
end
From railscast
First you'll need to add a column to your users table, to keep the selected timezone for this user (user.timezone should be fine).
in the form, you'll need to use ActiveSupport's #time_zone_select to allow the user to select their desired timezone.
finally, you'll need a before filter in ApplicationController to set the current sessions's timezone to the user's specific timezone.
Here is a gist with the migration, partial view and application controller filter:
https://gist.github.com/eladmeidar/6121183

How to display the time in user's timezone

I am using rails 3.0.5 and I have created_at and updated_at stored in UTC. Now I want to display the created_at time in users' timezone. I believe it is possible to pick user's timezone from the browser and then convert time to user's timezone.
I am sure rails will have a gem/plugin to take care of something like this. Is there something?
Rails by default converts every date into UTC before storing the value into the database. This means that, regardless the server timezone, you always have UTC dates in your database.
In order to convert the dates into your user's timezone you have basically two possibilities:
server-side approach
client-side approach
Server-side approach
If your site allows registration, you can store the user timezone as user preference. In the user table, store the user timezone. Then create a custom helper you can use to format any date/time into the proper timezone using the in_time_zone method.
> t = Time.current
# => Mon, 23 Dec 2013 18:25:55 UTC +00:00
> t.zone
# => "UTC"
> t.in_time_zone("CET")
# => Mon, 23 Dec 2013 19:25:55 CET +01:00
Your helper may looks like
def format_time(time, timezone)
time.in_time_zone(timezone)
end
I normally also like to output a standard format, using the I18n.l helper
def format_time(time, timezone)
I18n.l time.to_time.in_time_zone(timezone), format: :long
end
Client-side approach
If your site has no registration or you don't want to ask your users for their timezone or you simply want to use the user system timezone, then you can use JavaScript.
My suggestion is to create a custom helper that will print out every time in a proper way so that you can create a generic JavaScript function to convert the values.
def format_time(time, timezone)
time = time.to_time
content_tag(:span, I18n.l(time, format: :long), data: { timezone: timezone, time: time.iso8601 })
end
Now, create a JavaScript function that is performed on DOM load and that will select all the HTML tags with data-time attribute. Loop them and update the value inside the span tag with the proper time in the given timezone.
A simple jQuery example would be
$(function() {
$("span[data-time]").each(function() {
// get the value from data-time and format according to data-timezone
// write the content back into the span tag
});
});
I'm not posting the full code here, since there are plenty of JavaScript time formatters available with a simple search. Here's a few possible solutions
Convert date to another timezone in JavaScript
Convert date in local timezone using javascript
There is a nice gem by Basecamp called local_time for client side rendering - https://github.com/basecamp/local_time. It's great for applications where user is not signed in and it's caching friendly.
You can add this to your application controller to convert all times to the User's timezone:
class ApplicationController < ActionController::Base
around_filter :user_time_zone, :if => :current_user
def user_time_zone(&block)
Time.use_zone(current_user.timezone_name, &block)
end
end
You just have to capture the user's timezone
Assuming that the value you want displayed is coming from the database, :ie started_at and is (as is the default) stored in UTC.
If you have the user's timezone as an offset you can also localize the time by doing:
started_at.in_time_zone(-2)
=> Mon, 24 Feb 2014 23:07:56 GST -02:00
Which then can be munged in all sorts of way to get the parts you want:
started_at.in_time_zone(-2).yesterday
=> Sun, 23 Feb 2014 23:07:56 GST -02:00
started_at.in_time_zone(-2) + 3.days
=> Thu, 27 Feb 2014 23:07:56 GST -02:00
http://api.rubyonrails.org/classes/Time.html#method-c-use_zone
This is what you're looking for :
Time.use_zone(#user.timezone) do
blah blah blah
end
If you'd like to convert your date to a specific Timezone:
deadline.in_time_zone(time_zone)
Here deadline is a date.
In addition, you can find Universal time through your local machine Timezone plus local time and vice verse, like in Karachi - +05:00, you can simply add it to value in Universal time to find time in your time zone or get Universal time from your local time by subtraction of Timezone difference (05:00 in our case) from your local time
My jquery is a rusty, so it took me a little while to figure out how to implement the client-side approach of the accepted answer above.
Here's my solution:
HTML:
<span data-time="<%= last_message_at %>"> </span>
Jquery/Javascript:
<script type="text/javascript">
$(document).ready($(function() {
$("span[data-time]").each(function() {
var timestamp = $(this).attr("data-time");
var localeTimestamp = new Date(timestamp).toLocaleString();
$(this).html(localeTimestamp);
});
}));
</script>
You might want to take a look at these links in addition to the one Ben posted:
http://railscasts.com/episodes/106-time-zones-in-rails-2-1

Resources