Hi I've start_date column which capture time stamp, I'd like to query the data based on days like if date falls on sunday or monday like that.
For example
from_date = Tue Nov 22 23:00:00 UTC 2016
to_date = Sun Nov 27 02:00:00 UTC 2016
Here I need get all the records from tuesday 23:00 pm to sunday 02:00 am.
Updated Answer
MySQL has dayofweek function for this.
You can write your query as:
MyModel.where('dayofweek(start_date) = ?', 1) # 1 is Sunday
To get all models which start_date is on Sunday.
To achieve your goal, you can query start_date on Tuesday AND start_date hour is later than 23:00, start_date on Wed, start_date on Thurs and etc.
So the final query would be like:
MyModel.where('(dayofweek(start_date) = ? AND hour(start_date) > ?)
OR dayofweek(start_date) = ? OR dayofweek(start_date) = ? OR
dayofweek(start_date) = ? OR dayofweek(start_date) = ? OR
(dayofweek(start_date) = ? AND hour(start_date) > ?)'
, 3, 23, 4, 5, 6, 7, 1, 2)
Previous Answer
You can use a range query with where:
Model.where(start_date: from_date..to_date)
Related
I have a Holiday model, with a holiday_date attribute of DateTime.
I added a new Holiday (New Years Day) with a date of 1/1/2019.
When I do in the console Holiday.last, I see this:
#<Holiday id: 50, name: "New Years Day", holiday_date: "2018-12-31 23:00:00", created_at: "2018-11-13 13:15:54", updated_at: "2018-11-13 13:15:54">
So it is saved in UTC time, a day earlier. When I then do Holiday.last.holiday_date I get this:
Tue, 01 Jan 2019 00:00:00 CET +01:00
Great, the date is converted to our CET date and time. But when I query for a year like this:
Holiday.where("extract(year from holiday_date) = '2019'")
It returns no results. So it seems that there is no conversion to CET time with this query. How can I make sure that the query returns the holiday I added?
You'll have to cast timezones twice:
Holiday.where(
"extract(year from holiday_date AT TIME ZONE 'UTC' AT TIME ZONE 'CET') = '2019'"
)
This will work, but it would be nice to use indices for your query, we'll just have to prepare it better:
year = Time.zone.parse("2019-01-01")
Holiday.where("holiday_date BETWEEN ? AND ?", year.beginning_of_year, year.end_of_year)
# SELECT "holidays".* FROM "holidays" WHERE (holiday_date BETWEEN '2018-12-31 23:00:00' AND '2019-12-31 22:59:59.999999')
I would really think whether you need datetimes for your holiday_date column, perhaps dates would be enough, so that you don't have to deal with timezones.
You can query by timezone like this
Holiday.where("extract(year from holiday_date AT TIME ZONE 'CET') = '2019'")
Given day in week (let's say Monday), I need to find closest date (in future) to given date (for example 9-4-2016) which is this day in week (for these examples, it should be 11-4-2016).
This is a pure Ruby solution.
require 'date'
d = Date.strptime('9-4-2016', '%d-%m-%Y')
#=> #<Date: 2016-04-09 ((2457488j,0s,0n),+0s,2299161j)>
d + (1 - d.wday) % 7
#=> #<Date: 2016-04-11 ((2457490j,0s,0n),+0s,2299161j)>
1 is Monday's offset. d.wday #=> 6.
I have assumed that if the date falls on a Monday, the "closest" Monday is the same day. If it is to be the following Monday, use:
d + (d.wday == 1) ? 7 : (1 - d.wday) % 7
You can find this date in the nearest week of your date:
date = Date.parse('9-4-2016')
(date..date + 6).find {|d| d.strftime("%A") == "Monday"}
#=> Mon, 11 Apr 2016
Would it be possible to go to a certain month of the year with just a given integer. For example
date = Date.today
=> Wed, 30 Dec 2015
What if I want to go back to a certain month based on that date and I am just given a number let's say 7 which is July in the Date::MONTHNAMES so would it be possible to do something like
date = Date.today
=> Wed, 30 Dec 2015
date.go_to_month_of(7) # which will bring me back to July 30, 2015
Okay I found it. It's:
date = Date.today
date.change(:month => x)
Hope this helps you!
I have day of the year. For example 15th day of 2014, or 210th day of 2014. I need to get the Date on the particular day. Is there any library function in Rails/Ruby that I can use, or any other elegant way?
Something like:
15th day of 2014 = 15-Jan-2014
210th day of 2014 = 29-Jul-2014
You can use Date.ordinal for that:
require 'date'
Date.ordinal(2014, 210)
# => #<Date: 2014-07-29 ((2456868j,0s,0n),+0s,2299161j)>
Date.new(2014, 1, 1) + 210
=> Wed, 30 Jul 2014
Edit - you'd need to subtract 1 day. I prefer #wonderb0lt's suggestion.
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.