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

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.

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 :)

How do i get a fixed time in a fixed timezone in ruby?

I would like to create a Time/DateTime object that always represents "8am in New York", regardless of DST. How can i achieve this ?
One suggestion in the Rails documentation was to use
Time.zone = 'Eastern Time (US & Canada)'
in the following manner
around_filter :set_time_zone
def set_time_zone
if logged_in?
Time.use_zone(current_user.time_zone) { yield }
else
yield
end
end
But i would like to avoid touching thread variables (which is what Time.use_zone is doing)
Try this:
ActiveSupport::TimeZone['Eastern Time (US & Canada)'].parse('8:00')
That will handle day light savings time issues
> eight_am = ActiveSupport::TimeZone['Eastern Time (US & Canada)'].parse('8:00')
=> Fri, 22 May 2015 08:00:00 EDT -04:00
> eight_am.in_time_zone('America/Los_Angeles')
=> Fri, 22 May 2015 05:00:00 PDT -07:00
Well, you could approach the problem this way:
ny = Time.new(Time.now.year,Time.now.month,Time.now.day,8,0,0,"-05:00")
This will return an object ny that is set for 8:00 AM EST (New York) for the current day on any day that you execute it.

Rails Active Record TimeZones

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

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

In Rails, how do I convert and print a time to a different time zone?

I have a variable, start_time:
(rdb:5) start_time.class
ActiveSupport::TimeWithZone
(rdb:5) start_time
Tue, 23 Feb 2010 14:45:00 EST -05:00
(rdb:5) start_time.in_time_zone(ActiveSupport::TimeZone::ZONES_MAP["Pacific Time (US & Canada)"]).zone
"PST"
(rdb:5) start_time.in_time_zone(ActiveSupport::TimeZone::ZONES_MAP["Pacific Time (US & Canada)"]).to_s(:time)
"2:45 PM ET"
I'd like to change 'to_s(:time)' so that it outputs the time in whatever zone is specified in the variable, not the default system time. I.e. The output would be "11:45 AM PT". How do I do this?
I think you want to create a TimeZone object, and use its at() method:
start_time = Time.now
start_time.rfc822 # => "Tue, 23 Feb 2010 10:58:23 -0500"
pst = ActiveSupport::TimeZone["Pacific Time (US & Canada)"]
pst.at(start_time).strftime("%H:%M %p %Z") # => "08:00 AM PST"
I ran into this issue recently and was able to solve it by essentially overriding the .to_s option that I was using. I created an initializer called time_formats.rb and added the following line to it.
Time::DATE_FORMATS[:time_in_zone] = "%H:%M %p"
then changed (:time) to (:time_in_zone) like so...
start_time.in_time_zone(...your timezone here...]).to_s(:time_in_zone)
It should give you the time in the zone you are specifying. My environment is in UTC, so maybe that had something to do with it...
Given Beerlington's comments, I ended up adding the following (which is similar to the Proc defined for Time::DATE_FORMATS[:time]
:time_in_zone => lambda { |time|
time = time.strftime("%I:%M %p %Z").gsub(/([NAECMP])([DS])T$/, '\1T')
time = time[1..-1] if time =~ /^0/ # drop leading zeroes
time
}

Resources