How to subtract date and time out of date time object? - ruby-on-rails

Here is what I am trying to achieve - I have set up a scheduler to execute midnight of every friday, which collects the data from a service for the start date of last friday at 00:00:00 hrs and end time of last thursday at 23:59:59 hrs. Since it has to work every friday, I cannot hard code the dates so I thought of trying out DateTime.
So as per my requirement, if I am running the job on this Friday midnight i.e at "2014-12-12T03:00:00Z", then my start date should be "2014-12-05T00:00:00Z" and my end date should be "2014-12-11T23:59:59Z".
So to get start and end dates, I am trying to subtract days out of my now object. This is what I tried:
now = DateTime.now
p now.new_offset(0).to_s
startDate = now - 7
p startDate.new_offset(0).to_s
endDate = now - 1
p endDate.new_offset(0).to_s
This gives me the right date, but the time is wrong i.e. instead of start date with 00:00:00 and end date with 23:59:59 this would be start date with 03:00:00 and end date with 03:00:00.
How do I modify the DateTime object to get the start date with time at beginning of the day and end date with time at end of the day?
Sorry I am very bad in dealing with dates. Thanks in advance!!

You can use he beginning_of_day and end_of_day methods
1.9.3-p448 :001 > DateTime.now.beginning_of_day
=> Tue, 09 Dec 2014 00:00:00 +0300
1.9.3-p448 :002 > DateTime.now.end_of_day
=> Tue, 09 Dec 2014 23:59:59 +0300

I think what you are trying to do is easier done with the Date class :
require 'date'
start_date = (Date.today - 7).to_time
end_date = Date.today.to_time - 1

Instead of doing this manually, I will suggest a gem called Whenever: https://github.com/javan/whenever
It's a simple DSL for Ruby cron jobs.
Also remember that DateTime has beginning_of_day and end_of_day methods.

Related

Ruby Rails Time zone rush hour

The last developer is using time in our app like this.
:timestamp_requested => Time.now.utc
I want to check if :timestamp_requested is between 4:15PM and 6:00PM CST.
I saw another post that uses in_time_zone but not sure how to check for between two times?
t = foo.start_time
#⇒ 2000-01-01 14:20:00 UTC
t.zone
#⇒ "UTC"
t.in_time_zone("America/Chicago")
#⇒ Sat, 01 Jan 2000 09:20:00 EST -05:00
You might want to try the use_zone method
Time.use_zone("America/Chicago") { (16..18).cover?(time.hour) && time.min >= 15 }
The easiest way to check the time is in the specific range would be to compare hours and minutes:
cst = time.in_time_zone("America/Guatemala") # CST whole year
(16..18).cover?(cst.hour) && cst.min >= 15

Get Record Created 30 Minutes Ago - Rails

I need to get records created 30 minutes ago from Time.now. I'm using a cron and I want to fire the cron once ever minute.
I essentially need this except it should ignore the seconds so that if Time.now == Wed, 31 Jan 2018 18:00:31 +0000 then a record with created_at = "Wed, 31 Jan 2018 17:30:23 +0000 should match.
Here is the query I have so far which doesn't work because the time is improperly evaluated.
Cart.joins(:cart_addresses).group('carts.id').where(created_at: Time.now - 30.minutes).each do |i|
puts i.id
end
Please try below query:
# if current time is 3:00:03
# it will return carts created at 2:30:00 -> 2:30:59
from_mins_ago = 30.minutes.ago.change(sec: 0)
to_mins_ago = from_mins_ago.change(sec: 59)
Cart.joins(:cart_addresses).group('carts.id').where(created_at: from_mins_ago..to_min_ago).pluck('carts.id')
You could use a range.
Cart.joins(:cart_addresses).group('carts.id').where(created_at: 30.minutes.ago..DateTime.now)
There's a lot of solutions.
More: Rails ActiveRecord date between

get time until hour in user timezone

I'm trying to get the time until 12:00 AM in the users timezone. How can I do this in rails?
I want to get the time until 12:00 AM and then add that time to the current time in rails to store it in the database because I want to have a field with the GMT time at is the equivalent to 12:00 AM in the users timezone
I'm using this gem:
gem 'time_difference', '~> 0.5.0'
In order to get the time difference between two timestamps
TimeDifference.between(DateTime.now, created_at)
But I'm not sure how to get the time until 12:00 AM in the users timezone.
Thanks
Given a particular timezone, you can use Rails' tools for dealing with timezones to just directly find out when midnight is for a particular timezone. This example supposes you have a time_zone column on your User model with an appropriate value (e.g., America/Chicago, or anything else Rails supports):
midnight_for_user = ActiveSupport::TimeZone[user.time_zone].now.midnight.tomorrow
For example, I can use the same logic to find when midnight is for a person in New York:
pry(main)> Time.current
=> Thu, 05 Jan 2017 10:34:02 CST -06:00
pry(main)> ActiveSupport::TimeZone['America/New_York'].now.midnight.tomorrow
=> Fri, 06 Jan 2017 00:00:00 EST -05:00
Note that I'm looking for midnight tomorrow; remember that "midnight" for a given day is actually the very first minute of the day, not the last.

Storing dates in UTC after updating the user entered time zone to reflect proper UTC time

I have an Event model which has start and end date/times and an associated time zone.
I need the date times submitted to be stored in the correct version of UTC based off of the time zone entered.
Example, if the user submits 2014-04-24 7PM EST
The database should be:
2014-04-24T23:00:00.000Z
Not this:
2014-04-24T19:00:00.000-07:00
Ok, I know rails stores everything in UTC, but I need to store the UPDATED UTC time based off the time zone - since my form is 3 fields, x2 date/time & x1 time zone
This is my model validation I thought would work properly:
def calc_utc_based_off_timezone
time_zone = self.time_zone
puts "start date before assignment: "
puts self.start_date
self.start_date = self.start_date.in_time_zone(time_zone)
self.end_date = self.end_date.in_time_zone(time_zone)
puts "start date after assignment: "
puts self.start_date
end
Entered in my form:
2014-04-24 - 19:00
2014-04-26 - 19:00
est
Output:
start date before assignment:
2014-04-24 19:00:00 UTC
start date after assignment:
2014-04-24 19:00:00 UTC
What I'm expecting:
start date before assignment:
2014-04-24 19:00:00 UTC
start date after assignment:
2014-04-24 23:00:00 UTC <-- updated UTC to reflect the time zone
Any help would be appreciated, thanks.
There is support for Time objects with Time Zones in the ActiveSupport::TimeWithZone class.
As long as you set the Time zone before giving the params to the new object function Event.new(params[:event]) rails will apply the offset that is set, and interpret as if its in that time zone.
# example params like the request
params = {
time_zone:"EST",
event:{
start_date:"2014-04-24 - 19:00",
end_date:"2014-04-26 - 19:00"}
}
Time.zone = params[:time_zone] # pulled from a time_zone_select field
#event = Event.new(params[:event])
if you have separate time and date fields, just combine them into whichever field holds the datetime in the database.
params[:event][:start_date] = "#{params[:event][:start_date]} #{params[:event][:start_time]}"
params[:event][:end_date] = "#{params[:event][:end_date]} #{params[:event][:end_time]}"
#event = Event.new(params[:event])
The timezones offset will be automatically applied and you should get the following if you inspect the object.
> puts #event.start_date
2014-04-25 00:00:00 UTC
> puts #event.end_date
2014-04-27 00:00:00 UTC
Here is a great guide that deals with Rails and Time Zones - The Exhaustive Guide to Rails Time Zones
You're right, there is something in Rails ActiveSupport for this,
Time.parse("2014-04-24 - 19:00").in_time_zone
Thu, 24 Apr 2014 23:00:00 UTC +00:00
Time.parse("2014-04-24 - 19:00").getutc
2014-04-24 23:00:00 UTC
You can also specify the detail and format (like iso8601) of your response by passing additional arguments like this:
> Time.parse("2014-04-24 - 19:00").getutc.iso8601(2)
"2014-04-24T23:00:00.00Z"
> Time.parse("2014-04-24 - 19:00").getutc.iso8601(3)
"2014-04-24T23:00:00.000Z"
Documentation for ActiveSupport::TimeWithZone: http://api.rubyonrails.org/classes/ActiveSupport/TimeWithZone.html#method-i-getutc

Rails Time objects

I've got a quick-add action in my events controller, as the client really only schedules events at three different time slots in a given day. Date and Time are working fine with the default form, but trying to set the values by hand are giving me some trouble.
def quick_add #params are date like 2012-04-29, timeslot is a string
timeslot = params[:timeslot].to_sym
date = params[:date].to_date
#workout = Workout.new do |w|
w.name = 'Workout!'
w.date = date
case timeslot
when :morning
w.time = Time.local(w.date.year, w.date.month, w.date.day, 6)
when :noon
w.time = Time.local(w.date.year, w.date.month, w.date.day, 12)
when :evening
w.time = Time.local(w.date.year, w.date.month, w.date.day, 18, 15)
else
w.time = Time.now
end
end
The events are getting created, the dates are correct, but times are:
Morning: 2000-01-01 10:00:00 UTC
Expected: 2012-05-02 06:00:00 UTC -400
Noon: 2000-01-01 16:00:00 UTC
Expected: 2012-05-02 12:00:00 UTC -400
Evening: 2000-01-01 22:15:00 UTC
Expected: 2012-05-02 18:15:00 UTC -400
It's worth noting that running the commands in rails console seems to get the results I'd expect.
Time values are stored in UTC/GMT (+0) time zone as an integer so that no time zone data has to be stored with it. Rails always stores times in the database as UTC times. When you read them out, you'll want to convert them back to your local time zone again.
You can use time.getlocal to convert it to your local time zone.

Resources