I have users with a birth_date
and now I want to query all users who have their birthday within the next 10 days. I can't just order on birth_date
because then I will get this:
01-01-1960
18-12-1975
16-12-1998
Instead of the desired result:
16-12-1998
18-12-1975
01-01-1960
So how can I only order on the day and month, but not the year?
This works in postgreSQL...
start_month = Date.today.month
start_day = Date.today.day
end_month = (Date.today + 10).month
end_day = (Date.today + 10).day
if start_month == end_month
@users = User.where("DATE_PART('month', birth_date) = ? AND DATE_PART('day', birth_date) >= ? AND DATE_PART('day', birth_date) <= ?", start_month, start_day, end_day)
else
@users = User.where("(DATE_PART('month', birth_date) = ? AND DATE_PART('day', birth_date) >= ?) OR (DATE_PART('month', birth_date) = ? AND DATE_PART('day', birth_date) <= ?)", start_month, start_day, end_month, end_day)
end
@users.order("DATE_PART('month', birth_date), DATE_PART('day', birth_date)")
This selects all records with birthdays within the next 10 days and sorts them.
If ten days in the future is still the same month (say on December 14) it selects December between 14 and 24... if it's in a future month (say on December 25) it selects December to end of month and January from beginning to the 4th.
A ruby implementation. Note that it may not be as performant as the DB version...
ids_of_next_10_days = User.all.pluck(:id, :birth_date).map do |user_info|
next_birthday = user_info[1].change(year: Time.now.year)
next_birthday = next_birthday.change(year: Time.now.year + 1) if next_birthday < Date.today
next_birthday.between?(Date.today, Date.today + 10) ? user_info[0] : nil
end.compact
User.where(id: ids_of_next_10_days)
On the Ruby side you can select needed users at first(Postgresql to_char
is used):
today = Date.current
dates = (today ... today + 10.days).map { |d| d.strftime('%m%d') }
dates << '0229' if dates.include?('0228') # update by SteveTurczyn
users = User.where("to_char(birth_date, 'MMDD') in (?)", dates).to_a
then sort them:
users.sort_by! do |user|
user_yday = user.birth_date.yday
user_yday >= today.yday ? user_yday : user_yday + 366
end
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.